Add Stripe live secret key validity check
What does this MR do and why?
This adds a validity check for Stripe live secret keys (starting with prefix sk_live_).
A user can then tell whether the exposed credential is still live rather than only that it was leaked.
Implementation
This follows ADR-006 and uses the registry directly to map the token straight to the verifier class/client, i.e. StripeClient.
The verifier calls GET https://api.stripe.com/v1/balance with the key as the HTTP Basic username. That endpoint has no side effects.
We map the responses to the following statuses/outcomes:
| Response | Outcome |
|---|---|
200 |
active |
401 |
inactive |
429 |
RateLimitError |
500, 502, 503, 504 |
NetworkError |
anything else, including 403 |
unknown |
Please note that aside from 401, no other status falls to inactive. 403, which a restricted key can return, is therefore never read as revoked.
Reporting a live token as dead is worse than reporting nothing, so unmapped statuses are always unknown.
Other Stripe credentials, deliberately not covered
Stripe has several credentials in secret-detection-rules besides the one registered here: the
24-character StripeLiveShortSecretKey, restricted keys (rk_live_) and publishable keys
(pk_live_). Each of those is its own detection rule.
Under ADR-006 one
token type means one verifier class, so covering them is a matter of adding classes
rather than widening the pattern in this one – and this MR's pattern mirrors StripeLiveSecretKey
exactly. Findings for the others return unknown with no API call in the meantime.
That work is tracked in #588601 and is best done once the generator handles vendors that have several token types.
Stack Position
We have 8 MRs for all new validity checks generated during Sec Challenge #6, with the base targeting master.
Each MR in the stack adds exactly one validity check: the client class, its spec, the registry entry, and the rate limit rule.
Stack (in review order)
| # | Check | Token type |
|---|---|---|
| 1 | GitHub PAT | Github Personal Access Token |
| 2 | OpenAI project key | OpenAiProjectKey |
| 3 | Anthropic API key | anthropic_key |
| 4 | Slack access tokens | Slack token |
| 5 | Stripe live secret key | StripeLiveSecretKey |
| 6 | Datadog API key | DataDogAPIKey |
| 7 | SendGrid API token | Sendgrid API token |
| 8 | Heroku API key | Heroku API Key |
Notes
- Token type and pattern were verified against the authoritative rule in
secret-detection-rules. - Rate limit: 100 checks per minute per project. Stripe allows 25 requests per second on an individual endpoint, so this stays well under it.
- Unmapped statuses are covered by the shared example
a partner token client, which this stack adds once and every verifier reuses. - Verifier code originates from the Sec Challenge #6 PoC branch
ghavenga-summit-ch6-validity-checks.
How to set up and validate locally
-
Run the specs:
bundle exec rspec ee/spec/lib/security/secret_detection/partner_tokens/stripe_client_spec.rb \ ee/spec/services/security/secret_detection/partner_tokens/registry_spec.rb -
Confirm the registry resolves the token type and that the rate limit rule exists:
Security::SecretDetection::PartnerTokens::Registry.client_for('StripeLiveSecretKey') # => #<Security::SecretDetection::PartnerTokens::StripeClient> Gitlab::ApplicationRateLimiter.period_for(:partner_stripe_api) # => 60 seconds -
Optional, with a real credential – a revoked token should come back
inactiveand a live oneactive:Security::SecretDetection::PartnerTokens::Registry .client_for('StripeLiveSecretKey').verify_token(ENV['TOKEN']).status
MR acceptance checklist
I have evaluated this MR against the MR acceptance checklist.