Browse CTFs New CTF Sign in

API key leakage

web_injection_logic Difficulty 1–5 30 min certifiable

Theory

Why This Matters

API key leakage is one of the most frequently reported bug bounty findings and one of the most preventable. In 2022, Toyota's IT partner T-Connect exposed an API key in a public GitHub repository for five years, potentially leaking email addresses of 296,000 customers. In 2019, researchers scanning GitHub found hundreds of AWS access keys, Google API keys, and Stripe secret keys committed in public repositories — many still active. The 2023 CircleCI security incident began with a developer's session token captured from client-side JavaScript. Twilio, Slack, and Uber have all suffered breaches traced to leaked API credentials in source code or version control history. The pattern is consistent: a credential that should be server-side only is exposed in a client-accessible artifact.

Core Concept

An API key is a shared secret that authenticates a client to an API. Unlike OAuth tokens, API keys typically grant long-lived, broad access without per-request signing. An exposed API key is one that has been placed where an attacker can retrieve it without authentication — in JavaScript bundles, HTML source, mobile app binaries, public git repositories, or server error messages.

Exposure vectors by decreasing frequency:

  1. JavaScript bundles — Frontend build tools (webpack, Vite, Parcel) bundle source files into a single JS file. Any const API_KEY = "sk-..." or process.env.REACT_APP_STRIPE_KEY reference that is included in the bundle is sent to every visitor. Webpack source maps (.js.map files) often expose the original, un-minified source including comments and variable names.
  2. Git history — A key committed and then "deleted" in a later commit still exists in the full git history. git log -p | grep -i "api.key|secret|token|password" recovers deleted secrets. Services: GitGuardian, truffleHog, gitleaks.
  3. .env files committed accidentally.env is excluded from version control by default only if .gitignore includes it. A single git add . without a proper .gitignore commits all environment files.
  4. Mobile app decompilation — Android APKs are ZIP files containing classes.dex (bytecode). apktool d app.apk + jadx -d out/ app.apk reconstruct readable Java/Kotlin. String constants including API keys are preserved in decompiled output.
  5. Error messages and debug endpoints — Stack traces, verbose error responses, and enabled debug endpoints (/api/debug, /_ah/admin) may include credentials in request logging.
  6. Response headers — Some API gateways include internal auth tokens in X-Internal-Token, X-Api-Key, or X-Auth response headers intended for internal routing.

After discovery, the secret rotation workflow is: (1) revoke the key immediately at the provider (Stripe, AWS, Google Cloud console), (2) rotate to a new key deployed via secrets manager (HashiCorp Vault, AWS Secrets Manager), (3) purge the secret from git history using git filter-repo or BFG Repo Cleaner, (4) audit API logs for historical usage by the leaked key, (5) add pre-commit secret scanning to CI.

Technical Deep-Dive

# ── Git history search ─────────────────────────────────────────────────────
# Clone the target repository (or use existing checkout)
git log --all --full-history -p -- "*.env" "*.config" "*.json" 
    | grep -i "api.key|secret|token|password|sk-|pk-|AKIA" 
    | sort -u

# Or use truffleHog (high-signal regex + entropy detection)
trufflehog git file:///path/to/repo --only-verified

# Or use gitleaks (fast, many built-in rules)
gitleaks detect --source /path/to/repo --report-format json

# GitHub Dorking for public repos
# (run in browser or via GitHub Search API)
# site:github.com "STRIPE_SECRET_KEY" "sk_live_"
# site:github.com filename:.env "AWS_SECRET_ACCESS_KEY"
# site:github.com "api_key" extension:js "sk-"

# ── Webpack source map extraction ─────────────────────────────────────────
# Check if source maps exist
curl -s https://app.example.com/static/js/main.chunk.js.map | 
    python3 -c "import sys,json; d=json.load(sys.stdin); [print(s[:200]) for s in d.get('sourcesContent',[]) if 'api' in s.lower()]"

# sourcemapper tool — extracts all original source files from a .map
pip install sourcemapper
sourcemapper -url https://app.example.com/static/js/main.chunk.js.map 
    -output ./extracted_sources/

# Then grep extracted sources for credentials
grep -rEi "api.?key|secret|token|password|sk[-_]live|AKIA[0-9A-Z]{16}" 
    ./extracted_sources/

# ── Mobile app decompilation ───────────────────────────────────────────────
# Extract and decompile an Android APK
apktool d target.apk -o apktool_out/
jadx -d jadx_out/ target.apk

# Search decompiled source for API keys
grep -rEi "api.?key|secret|sk_live|AKIA[0-9A-Z]{16}" jadx_out/ | head -30

# ── Secret scanning in CI (pre-commit hook) ───────────────────────────────
# .pre-commit-config.yaml
# repos:
#   - repo: https://github.com/gitleaks/gitleaks
#     rev: v8.18.0
#     hooks:
#       - id: gitleaks

# ── Verify a discovered key is still active (example: AWS) ────────────────
AWS_ACCESS_KEY_ID=AKIA... AWS_SECRET_ACCESS_KEY=... 
    aws sts get-caller-identity 2>&1
# If response includes "UserId", key is active → rotate immediately
// Vulnerable pattern: React app with hardcoded API key in source
// This appears in the JavaScript bundle sent to all users
const STRIPE_KEY = "sk_live_AbCdEfGhIjKlMnOpQrStUvWx"; // NEVER do this
const GOOGLE_MAPS_KEY = "AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXX";

// Vulnerable pattern: .env variable included in frontend bundle
// REACT_APP_ prefix causes Create React App to embed in the bundle
const apiKey = process.env.REACT_APP_SECRET_KEY; // Exposed in bundle!

// SECURE: API keys for external services must be used server-side only
// Frontend calls your backend, which calls the external API using the key
// The key is stored in process.env on the server, never sent to the browser

Security Assessment Methodology

  1. Enumerate JavaScript assets — Spider the target with Burp Suite. For every .js URL discovered, check for a corresponding .js.map source map. Download all bundles and source maps for offline analysis.
  2. Grep bundles and source maps for credential patterns — Use regex: (sk|pk)_(live|test)_[A-Za-z0-9]{20,} (Stripe), AKIA[0-9A-Z]{16} (AWS), AIzaSy[A-Za-z0-9_-]{33} (Google), [0-9a-f]{32} (generic), Bearer [A-Za-z0-9._-]+.
  3. Search git history — If source code access is in scope, run truffleHog and gitleaks. Search for .env files at any historical commit. Check all branches, not just main.
  4. Decompile mobile apps — Download the APK or IPA from the app store listing or directly. Use jadx (Android) or class-dump + Hopper (iOS) to extract strings.
  5. Check HTTP response headers — Capture responses for all authenticated and unauthenticated requests. Look for X-Api-Key, X-Token, X-Auth, X-Internal-* headers that may carry credentials.
  6. Verify and safely document — For any discovered key, perform the minimum test to confirm validity (e.g., aws sts get-caller-identity for AWS keys). Do not use the key for unauthorized access. Document: key value (truncated in report), discovery location, service, and estimated permission scope. Recommend immediate revocation.

Defensive Countermeasure — All API keys used to call external services must reside exclusively in server-side secrets managers (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager). Never embed secrets in frontend code or include them in environment variables prefixed for frontend bundle injection (REACT_APP_, VITE_, NEXT_PUBLIC_). Enforce pre-commit secret scanning with gitleaks or GitGuardian. Purge any historically leaked secrets from git history using git filter-repo. Implement automatic key rotation schedules and anomaly alerting on API key usage.

Common Assessment Errors

  • Only checking the current commit — Secrets deleted from the latest commit persist in git history. Always scan the full history with truffleHog or gitleaks --log-opts=--all.
  • Skipping source maps — Minified JS bundles are hard to search; .js.map files expose the original source with readable variable names and comments. Always check for source maps.
  • Not verifying key validity before reporting — Reporting an expired or revoked key wastes remediation effort and reduces credibility. Perform a minimal validity check.
  • Ignoring mobile apps — Mobile apps are a common location for hardcoded backend API keys. If a mobile app exists for the target, include APK/IPA analysis in the engagement.
  • Missing .env.example files with real credentials — Some developers commit .env.example or .env.sample files containing actual (not placeholder) credentials. Check these files.
  • Overlooking error message disclosure — Verbose error responses in staging environments frequently include database connection strings, API keys in headers, or internal service URLs. Test all error-triggering inputs.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0007 Knowledge of authentication, authorization, and access control methods Explains API key as a shared-secret authentication mechanism and its exposure failure modes
K0065 Knowledge of policy-based controls for data access Connects key leakage to secrets management policy failures
K0070 Knowledge of system and application security threats and vulnerabilities Maps key leakage to real-world breach incidents across major vendors
S0001 Skill in conducting vulnerability scans and recognizing vulnerabilities in security systems Trains git history search, source map extraction, and mobile decompilation
T0028 Conduct and support authorized penetration testing on enterprise networks Provides a tool-explicit methodology from discovery through validated reporting
T0570 Conduct application security assessments Frames API key leakage as a mandatory check in application security assessments

Further Reading

  • truffleHog GitHub Repository — trufflesecurity (offline reference)
  • "Finding Secrets in Public GitHub Repos" — GitGuardian State of Secrets Sprawl Report
  • OWASP API Security Top 10 2023, API8: Security Misconfiguration — OWASP Foundation

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.