Back to scan results
Check 12 of 24

Exposed API Keys & Secrets

We download your homepage HTML and any same-origin JavaScript it loads, then scan the text for the distinctive prefixes used by major cloud and SaaS providers. Anything matching is reported, because a key in client-side source is a key in the wild.

What this check probes

Regex patterns for the distinctive shape of each provider's keys:

  • AWS — access key id AKIA[0-9A-Z]{16}, secret [A-Za-z0-9/+=]{40} next to the access key.
  • Google — API key AIza[0-9A-Za-z\-_]{35}, OAuth client secret GOCSPX-[A-Za-z0-9_-]{28}.
  • Stripe — live secret sk_live_[0-9a-zA-Z]{24,}, restricted key rk_live_. (Publishable pk_live_ is intentional in client code, not flagged.)
  • GitHub — personal access token ghp_[A-Za-z0-9]{36}, OAuth gho_, fine-grained github_pat_.
  • Slack — bot token xoxb-, user xoxp-, app xoxa-, webhook URL hooks.slack.com/services/T....
  • SendGrid — SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}.
  • Twilio — account SID AC[0-9a-f]{32}, auth token (32 hex), API key SK[0-9a-f]{32}.
  • Mailgun — key-[0-9a-f]{32}.
  • Private keys — -----BEGIN (RSA|EC|DSA|OPENSSH|PRIVATE) KEY-----.
  • JSON Web Tokens — three base64url segments separated by dots (low confidence; flagged only when paired with admin-looking claims).

Why this matters for PCI DSS

A leaked AWS key gives an attacker full access to your S3 buckets, EC2 instances, and IAM. A leaked Stripe secret key allows charges, refunds, and customer data export. A leaked Twilio key lets the attacker send (and pay for) SMS in your name.

PCI DSS 4.0 Requirement 3.5.1 requires cryptographic keys be protected from unauthorized access. Requirement 8.3.1 requires strong authentication factors. Requirement 6.4.3 requires payment-page integrity — a leaked Stripe key is the most direct breach of this.

Also note: scrapers like GitGuardian, TruffleHog, and the Shhgit feed pull billions of new pages a day. A key in your homepage source is harvested within minutes of going live.

How to fix it

1. Rotate the key immediately — at the provider's dashboard. Treat it as compromised the second it appeared in a public response, regardless of whether you can prove it was harvested.

2. Move the key to the server side. Anything secret that needs to talk to a provider should do so from your backend. Your frontend calls your backend over your authenticated API; your backend holds the secret.

  • AWS — use IAM roles attached to your EC2 / ECS / Lambda, never embed access keys in code.
  • Stripe — frontend uses publishable key (pk_live_) for Stripe Elements; payment intent creation happens server-side with the secret key.
  • Google Maps — use a key restricted to your specific HTTP referrers (Google Cloud Console → Credentials → Application restrictions).

3. Add automated secret scanning to CI so this can't happen again:

# GitHub Actions example using TruffleHog
- uses: trufflesecurity/trufflehog@main
  with:
    extra_args: --only-verified

Other options: Gitleaks, git-secrets, GitHub's own native secret scanning (free for public repos).

4. Audit the audit log at the provider — look for unfamiliar IPs, unusual API calls, or charges.

Fixed it? Re-run the scan to confirm.

Run scan again