
:white_check_mark: Automate your key and secret validation workflows
:cowboy_hat_face: Over 30 different providers
:robot: Export to JSON, audit via CSV

Keyscope is a key and secret workflow (validation, invalidation, etc.) tool built in Rust, powered by service_policy_kit.
Current workflows supported:
Cargo. Productive installing and running of tasks and examples.Grab a release from releases, or install via Homebrew:
brew tap spectralops/tap && brew install keyscope
You can try out validating a key for a provider, say, Github (assuming the key is in the GITHUB_TOKEN environment variable):
$ keyscope validate github $GITHUB_TOKEN
You can see which other providers are supported by running:
$ keyscope validate --list
.
:
.
twilio:validation
keyscope validate twilio -p twilio_1 -p twilio_2
twitter:validation
keyscope validate twitter -p twitter_1
zendesk:validation
keyscope validate zendesk -p zendesk_1 -p zendesk_2
Total 44 providers available.
$
And what parameters are required for a certain provider by running (say, stripe):
$ keyscope requirements stripe
provider stripe requires:
- param: p1
desc: stripe key
$
Finally the general structure of the validate command is:
$ keyscope validate PROVIDER -p PARAM1 -p PARAM2 .. -p PARAM_N
You can validate a specific provider like so:
$ keyscope validate twilio -p $TWILIO_KEY
With the general pattern of:
$ keyscope validate PROVIDER -p PARAM1 -p PARAM2 ...
The number of keys/params would change based on authentication type:
Bearer - usually just a single key (token)Basic Auth - usually 2 keys: user, passwordOAuth - usually 2 keys: client_id, client_secretEach provider in Keyscope will tell you what it requires using requirements:
$ keyscope requirements twilio
You'll get a report:
$ keyscope --verbose validate stripe -p $STRIPE_KEY
✔ stripe:validation: ok 766ms
Ran 1 interactions with 1 checks in 766ms
Success: 1
Failure: 0
Error: 0
Skipped: 0
And an executable exit code that reflects success/failure.
You can use the --verbose flag to see API responses:
$ keyscope --verbose validate stripe -p $STRIPE_KEY
✗ stripe:validation: failed 413ms
status_code: 200 != 401 Unauthorized
Ran 1 interactions with 1 checks in 413ms
Success: 0
Failure: 1
Error: 0
Skipped: 0
In this case the exit code is 1 (failure).
When you are validating keys that are supposed to be inactive, you can use the flip flag. In this mode, a failed API access is a good thing, and the exit code will reflect that.
$ keyscope --flip validate stripe -p $STRIPE_KEY
✔ stripe:validation: ok 766ms
Ran 1 interactions with 1 checks in 766ms
In this case, the key is active - which is bad for us. Using --flip, the exit code will be 1 (failure).
You can set up a CI job (or other form of scheduled job you like) to perform an audit, by reading all parameters from a dedicated CSV file like so:
$ keyscope validate --csv-in report.csv
The format of the CSV that you need to prepare should include a header line and look like this:
provider,key1,key2,key3
twilio,tw-key1,,,
You can specify as many key columns as you like, as long as you provide an empty value for providers which don't have that many keys, and all rows contain the same amount of cells.
If you have a dump of keys from your vault that are stale have expiry and should have been rotated, you want to test that they are all stale:
$ keyscope --flip validate --csv-in my-key-audit.csv
We're always adding new providers, keep a link to this list or watch this repo to get updated.
We use our service_policy_kit library to specify interactions with services and their policies, if you find a service not in this list feel free to open an issue or contribute back.
| **tester** Tester: valid key | validation | `tester_1` - hookbin ID (https://hookb.in) `tester_2` - fake key to put as a query param |
| ||
| **infura** infura API key | validation | `infura_1` - infura API key |
| ||
| **covalenthq** Covalent: valid key | validation | `covalenthq_1` - covalent token |
| ||
| **asana** Asana: valid token | validation | `asana_1` - asana token |
| ||
| **bitly** Bit.ly: valid access token | validation | `bitly_1` - bit.ly token |
| ||
| **ipstack** ipstack access key | validation | `ipstack_1` - ipstack access key |
| ||
| **localytics** Localytics: valid API credentials | validation | `localytics_1` - localytics user `localytics_2` - localytics key |
| ||
| **algolia** Algolia: valid API credentials | validation | `algolia_1` - algolia application ID `algolia_2` - algolia index `algolia_3` - algolia API key |
| ||
| **branchio** branch.io: valid API credentials | validation | `branchio_1` - branch.io key `branchio_2` - branch.io secret |
| ||
| **browserstack** browserstack: valid API credentials | validation | `browserstack_1` - browserstack key `browserstack_2` - browserstack secret |
| ||
| **buildkite** Buildkite: valid token | validation | `buildkite_1` - buildkite token |
| ||
| **datadog** datadog: valid API credentials | validation | `datadog_1` - datadog API key |
| ||
| **github** github: valid API credentials | validation | `github_1` - github token |
| ||
| **github-ent** Github Enterprise: valid API token | validation | `github-ent_1` - github enterprise instance (without http) `github-ent_2` - github token |
| ||
| **dropbox** dropbox: valid API credentials | validation | `dropbox_1` - dropbox token |
| ||
| **gitlab** gitlab: valid API credentials | validation | `gitlab_1` - gitlab token |
| ||
| **heroku** heroku: valid API credentials | validation | `heroku_1` - heroku token |
| ||
| **mailchimp** mailchimp: valid API credentials | validation | `mailchimp_1` - mailchimp datacenter ID `mailchimp_2` - mailchimp key |
| ||
| **mailgun** mailgun: valid API credentials | validation | `mailgun_1` - mailgun key |
| ||
| **pagerduty** pagerduty: valid API credentials | validation | `pagerduty_1` - pagerduty token |
| ||
| **circleci** circleci: valid API credentials | validation | `circleci_1` - circleci key |
| ||
| **facebook-access-token** facebook: valid API token | validation | `facebook-access-token_1` - facebook token |
| ||
| **salesforce** salesforce: valid API credentials | validation | `salesforce_1` - salesforce instance name `salesforce_2` - salesforce token |
| ||
| **jumpcloud** jumpcloud: valid API credentials | validation | `jumpcloud_1` - jumpcloud key |
| ||
| **saucelabs-us** saucelabs-us: valid API credentials | validation | `saucelabs-us_1` - saucelabs user `saucelabs-us_2` - saucelabs key |
| ||
| **saucelabs-eu** saucelabs-eu: valid API credentials | validation | `saucelabs-eu_1` - saucelabs user `saucelabs-eu_2` - saucelabs key |
| ||
| **sendgrid** sendgrid: valid API credentials | validation | `sendgrid_1` - sendgrid key |
| ||
| **slack** slack: valid API credentials | validation | `slack_1` - slack key |
| ||
| **slack-webhook** slack-webook: valid API credentials | validation | `slack-webhook_1` - slack webhook |
| ||
| **stripe** stripe: valid API credentials | validation | `stripe_1` - stripe key |
| ||
| **travisci** travisci: valid API credentials | validation | `travisci_1` - travisci domain, choose 'org' or 'com' `travisci_2` - travisci key |
| ||
| **twilio** twilio: valid API credentials | validation | `twilio_1` - twilio account sid `twilio_2` - twilio token |
| ||
| **twitter** twitter: valid API credentials | validation | `twitter_1` - twitter API token |
| ||
| **zendesk** zendesk: valid API credentials | validation | `zendesk_1` - zendesk domain `zendesk_2` - zendesk key |
| ||
| **firebase** firebase: valid API credentials | validation | `firebase_1` - firebase API key `firebase_2` |
$ claude mcp add keyscope \
-- python -m otcore.mcp_server <graph>