Finding API Keys in JavaScript and GitHub for Bug Bounty
Hard-coded keys still fund beginner months. The catch: half of what looks like a secret is a public client ID, a map tile token with strict referer rules, or a revoked stub. Your edge is triage speed — find candidates fast, prove abuse, skip the junk.
Where keys actually hide
Shipped JavaScript — webpack chunks, config.js, feature-flag dumps, old admin bundles left on a CDN. Search for apiKey, Authorization, Bearer, AKIA, sk_live, xoxb-, private key PEM headers.
Source maps — .js.map next to minified files sometimes restore original paths and comments with credentials.
GitHub — org repos, gists, CI logs, and deleted-but-cached commits. Also check robots.txt-ignored marketing sites that still host /static/js/ from forgotten deploys.
Related reading: OWASP hard-coded key guidance and vendor secret-scanning docs. I still manually verify before filing.
A tight recon loop
- Map JS URLs from the target’s main app and auth subdomain.
- Download bundles; rip strings with a simple regex pass, then open suspicious files by hand.
- For GitHub, search the org name +
AKIA,api_key,BEGIN PRIVATE KEYwithin allowed recon rules. - Classify each hit: publishable vs secret, scoped vs global, prod vs sandbox.
- Prove impact with a minimal authorized call — list buckets you should not list, read a private gist, send a test email to yourself — then stop.
Never burn someone else’s quota or exfiltrate customer data “to show severity.”
Impact framing that survives triage
- High: cloud root-equivalent, payment secret keys, mailer keys that send as the brand, Slack/GitHub tokens with org access
- Medium: third-party keys that read private tenant data or modify records
- Low / N/A: Firebase-style client configs meant for browsers, Stripe publishable keys, map tokens locked to HTTP referers
Screenshot the key location (file + line), redact mid-secret in the public report if the program asks, and include the exact API response that proves privilege.
Habits that keep you out of trouble
Stay in scope. Do not push found keys to your own public repo. Rotate notice: tell the program the secret is already public on the internet so they can revoke fast.
I treat JS and GitHub secret hunting as a daily warm-up — twenty minutes of string triage before deeper logic bugs. Volume is high; judgment is the skill.