CRITICAL

Exposed API Keys and Secrets

Description

API keys and secrets discovered in client-side code are publicly visible to anyone who visits your website. Attackers can extract these keys using browser developer tools or by viewing page source.

Exposed API keys can lead to unauthorized access to your services, data breaches, resource abuse, and significant financial costs. Many cloud providers will charge your account for any usage, even if it's from stolen credentials.

Client-side code (JavaScript, HTML) is always visible to users. Any secrets embedded in this code should be considered compromised immediately.

Potential Impact & Risks

  • Unauthorized access to your API services and data
  • Financial costs from resource abuse (especially cloud services)
  • Data breaches and exposure of sensitive information
  • Account takeover and service manipulation
  • Reputational damage and loss of customer trust
  • Compliance violations (GDPR, PCI-DSS, etc.)

Remediation

Immediate Actions

1. Revoke and regenerate all exposed API keys immediately

2. Review service logs for unauthorized access

3. Check billing/usage for suspicious activity


Long-term Solution

1. **Move secrets to backend**: Never embed API keys in client-side code

2. **Use proxy pattern**: Create backend endpoints that handle API calls

3. **Implement authentication**: Verify user identity before making API calls

4. **Use environment variables**: Store secrets in .env files (never committed)

5. **Apply rate limiting**: Prevent abuse even if keys are compromised

6. **Enable API restrictions**: Limit keys by domain, IP, or API scope

7. **Monitor usage**: Set up alerts for unusual activity

Code Examples

// ❌ BAD - Never do this:
const apiKey = "sk-1234567890abcdef";
fetch(`https://api.service.com/data?key=${apiKey}`);

// ✅ GOOD - Use backend proxy:
// Frontend:
fetch("/api/get-data", {
  headers: { "Authorization": `Bearer ${userToken}` }
});

// Backend:
app.get("/api/get-data", authenticateUser, async (req, res) => {
  const apiKey = process.env.SECRET_API_KEY;
  const data = await fetch(`https://api.service.com/data?key=${apiKey}`);
  res.json(await data.json());
});