Back to Blog
critical SEVERITY8 min read

How Hardcoded API Keys Happen in TOML Configuration Files and How to Fix Them

A hardcoded Google Maps API key was discovered in `exampleSite/config/_default/params.toml` at line 113, exposing a live credential that any attacker could extract from the repository and use to make unauthorized API calls. This critical vulnerability was automatically detected and fixed by replacing the hardcoded key with an empty placeholder, eliminating the risk of credential theft and unauthorized usage charges.

O
By Orbis AppSec
Published August 26, 2026Reviewed August 26, 2026

Answer Summary

This vulnerability is a hardcoded secret (CWE-798) in a Hugo static site configuration file (`exampleSite/config/_default/params.toml`), where a real Google Maps API key (`AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU`) was committed directly to version control. Anyone with repository access — or access to the deployed site's source — could extract and abuse the key. The fix removes the hardcoded value and replaces it with an empty string placeholder, instructing developers to inject the key via environment variables or a secrets manager instead of storing it in source code.

Vulnerability at a Glance

cweCWE-798 (Use of Hard-coded Credentials)
fixReplace hardcoded key with empty string placeholder and inject via environment variables
riskUnauthorized Google Maps API usage, unexpected billing charges, quota exhaustion
languageTOML (Hugo configuration)
root causeA live Google Maps API key was committed in plaintext to `params.toml` line 113
vulnerabilityHardcoded Secret / Exposed API Key

Introduction

The exampleSite/config/_default/params.toml file in this Hugo-based project is responsible for configuring site-wide parameters — including the Google Maps integration used to display an interactive map widget. At line 113, a single configuration entry quietly sat with a value that would make any security engineer wince:

map_api_key = "AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU"

This is not a placeholder. It is not a test key. It is a real, live Google Maps API key committed directly to version control — fully visible to anyone who clones the repository, browses the GitHub interface, or accesses the deployed site's source. The moment this key was pushed to a public (or even a semi-public internal) repository, the clock started ticking on potential abuse.

This post breaks down exactly how this happened, what an attacker could do with it, and how the fix eliminates the risk entirely.


The Vulnerability Explained

What Was in the File

In exampleSite/config/_default/params.toml, the Google Maps configuration block looked like this before the fix:

# google map
[google_map]
enable = false
map_api_key = "AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU"
map_latitude = "51.5223477"
map_longitude = "-0.1622023"
map_marker = "images/marker.png"

The key AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU follows the well-known format of Google Maps JavaScript API keys (AIza prefix followed by 35 alphanumeric characters). Automated secret scanners — and even a casual human reviewer — can immediately identify this pattern.

Why enable = false Doesn't Help

You might notice that enable = false is set in the same block. This might seem like a mitigating factor — if the map feature is disabled, is the key really exposed? The answer is an emphatic yes, for two reasons:

  1. The key exists in the file regardless of the enable flag. The configuration file is committed to the repository. Any attacker who reads the file sees the key, whether the feature is enabled or not.
  2. API keys are not scoped to your application's runtime state. Google's API servers have no idea your Hugo site has enable = false. The key works independently of your application logic.

The Specific Exploit Path

Here is a concrete attack scenario using this exact vulnerability:

  1. An attacker visits the GitHub repository (or any public mirror) and navigates to exampleSite/config/_default/params.toml.
  2. They read line 113: map_api_key = "AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU".
  3. They make a direct HTTP request to the Google Maps Geocoding API:
    https://maps.googleapis.com/maps/api/geocode/json?address=London&key=AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU
  4. If the key has not been restricted by IP or HTTP referrer, the request succeeds — and the API call is billed to the key owner's Google Cloud account.
  5. The attacker scripts thousands of such requests, exhausting the quota or generating significant charges before the owner notices.

Beyond billing fraud, depending on which Google APIs the key is authorized for, an attacker might also access Maps Embed API, Places API, Directions API, or other services — potentially exposing sensitive location data or functionality.

Real-World Impact

  • Unexpected billing charges: Google Maps API calls are billed per request. A single compromised key can generate hundreds or thousands of dollars in charges overnight.
  • Quota exhaustion: Legitimate users of the site's map feature would find the feature broken once the quota is consumed.
  • Reputation damage: If the key is associated with a business account, abuse could trigger account suspension.
  • Compliance implications: Exposed credentials in a repository may violate internal security policies or regulatory requirements.

This vulnerability maps to CWE-798: Use of Hard-coded Credentials, one of the most consistently exploited categories in the CWE Top 25.


The Fix

What Changed

The fix is surgical and unambiguous. In exampleSite/config/_default/params.toml at line 113, the hardcoded key was replaced with an empty string and a clarifying comment:

Before (vulnerable):

map_api_key = "AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU"

After (fixed):

map_api_key = "" # Replace with your Google Maps API key

Why This Fix Works

By replacing the key with an empty string, the fix achieves several things simultaneously:

  1. Eliminates the exposed credential from the codebase. Future clones of the repository will not contain a usable API key.
  2. Preserves the configuration structure. The map_api_key field still exists, so developers know exactly where to supply their own key. No configuration schema changes are required.
  3. Provides clear guidance. The inline comment # Replace with your Google Maps API key tells contributors what to do without leaving them guessing.

What You Should Do Next

The fix removes the key from the current HEAD of the repository, but the key still exists in git history. If this repository was ever public or shared, the key must be considered fully compromised. The correct remediation steps are:

  1. Immediately revoke the exposed key in the Google Cloud Console. Do not wait.
  2. Generate a new API key with appropriate restrictions (HTTP referrer restrictions, API restrictions).
  3. Purge the key from git history using git filter-branch or the BFG Repo Cleaner.
  4. Inject the new key at runtime using environment variables or a secrets manager rather than hardcoding it.

For Hugo sites specifically, environment variable substitution can be handled at build time:

# In your CI/CD pipeline or local .env (never committed)
export GOOGLE_MAPS_API_KEY="your-new-key-here"

Then reference it in your Hugo configuration using Hugo's environment variable support or a build script that populates the value before rendering.


Prevention & Best Practices

Never Commit Real Credentials to Source Control

This sounds obvious, but it happens constantly — especially in example sites, demo configurations, and documentation. The exampleSite/ directory in this repository is meant to demonstrate the theme, but it still gets committed, cloned, and sometimes deployed.

Rule of thumb: If a file is tracked by git, it should never contain a real secret. Period.

Use a .gitignore and Secret Templates

Maintain a params.toml.example with placeholder values and add the real params.toml to .gitignore:

# .gitignore
exampleSite/config/_default/params.toml

Then provide params.toml.example as the committed template:

map_api_key = "" # Set via environment variable GOOGLE_MAPS_API_KEY

Restrict API Keys at the Google Cloud Console

Even if you handle secrets correctly, always restrict your Google Maps API keys:
- Application restrictions: Limit to specific HTTP referrers (your domain only).
- API restrictions: Limit to only the APIs your application actually uses.

A restricted key that leaks is far less dangerous than an unrestricted one.

Pre-commit Hooks and CI Secret Scanning

Add secret detection to your development workflow:

# Install gitleaks
brew install gitleaks

# Scan repository
gitleaks detect --source . --verbose

Or use a pre-commit hook with detect-secrets:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets

GitHub also offers built-in secret scanning that detects Google API key patterns automatically.

OWASP and CWE References

This vulnerability falls under:
- OWASP A07:2021 – Identification and Authentication Failures (credential exposure)
- OWASP Secrets Management Cheat Sheet
- CWE-798: Use of Hard-coded Credentials
- CWE-312: Cleartext Storage of Sensitive Information


Key Takeaways

  • enable = false does not protect a hardcoded API key — the credential is exposed in the file regardless of whether the feature is active in your application.
  • The exampleSite/ directory is still part of your repository — demo and example configurations are just as dangerous as production configs when they contain real credentials.
  • Revoking the key is step one, not the only step — git history must also be purged, or the key remains accessible to anyone who cloned the repo before the fix.
  • The map_api_key field in params.toml should always be empty in committed files — real values belong in environment variables or a secrets manager, injected at build or deploy time.
  • Automated scanning catches what code review misses — this key sat at line 113 of a configuration file that humans routinely skim past; automated tools flag the AIza prefix immediately.

How Orbis AppSec Detected This

  • Source: The hardcoded string "AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU" assigned to map_api_key in exampleSite/config/_default/params.toml:113.
  • Sink: The credential value is directly readable by anyone with repository access — no exploit chain required; the secret is the vulnerability.
  • Missing control: No environment variable substitution, no secrets manager integration, and no .gitignore exclusion prevented the real API key from being committed.
  • CWE: CWE-798 — Use of Hard-coded Credentials.
  • Fix: The hardcoded key AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU was replaced with an empty string "" and a developer-facing comment instructing safe substitution.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

A single line in a configuration file — map_api_key = "AIzaSyCcABaamniA6OL5YvYSpB3pFMNrXwXnLwU" — represented a critical security exposure that could have led to unauthorized API usage, unexpected billing charges, and quota exhaustion. The fix is straightforward: replace the hardcoded value with an empty placeholder and inject the real credential securely at runtime.

What makes this vulnerability particularly instructive is how easy it is to overlook. The exampleSite/ directory feels like demo code. The enable = false flag creates a false sense of safety. But from an attacker's perspective, the key is just a string in a text file — and text files in git repositories are universally readable.

The lesson is clear: treat every file in your repository as potentially public, use automated secret scanning in your CI pipeline, and never let a real credential touch version control.


References

Frequently Asked Questions

What is a hardcoded secret vulnerability?

A hardcoded secret occurs when a real credential — like an API key, password, or token — is written directly into source code or configuration files instead of being injected at runtime from a secure secrets store.

How do you prevent hardcoded secrets in TOML configuration files?

Never place real credentials in committed configuration files. Use environment variable substitution, a secrets manager (like HashiCorp Vault or AWS Secrets Manager), or CI/CD secret injection to provide credentials at build or runtime.

What CWE is a hardcoded API key?

Hardcoded credentials like API keys map to CWE-798 (Use of Hard-coded Credentials), which covers situations where software contains credentials that cannot be easily changed and are visible to anyone with source access.

Is rotating the API key enough to prevent this vulnerability?

Rotation fixes the immediate exposure but does not prevent the pattern from recurring. You must also remove the key from the repository history (using `git filter-branch` or BFG Repo Cleaner) and implement a policy that prevents secrets from being committed in the first place.

Can static analysis detect hardcoded API keys?

Yes. Tools like Semgrep, TruffleHog, GitLeaks, and GitHub's built-in secret scanning can detect patterns matching Google Maps API keys and other credential formats before they reach production.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #242

Related Articles

critical

How Plaintext Secret Storage Happens in Cloudflare Workers (wrangler.toml) and How to Fix It

A critical misconfiguration in `platforms/m365/wrangler.toml` left developers one copy-paste away from committing live API keys directly into git history. The fix adds an explicit warning comment blocking the `[vars]` anti-pattern and adds `.dev.vars` to `.gitignore`, ensuring secrets flow through Cloudflare's encrypted `wrangler secret` mechanism instead of plaintext config. This matters because git history is permanent — a key committed even once can be extracted long after it's "deleted."

critical

How Hardcoded API Keys Happen in JavaScript and How to Fix Them

A critical security vulnerability was discovered in `src/js/init.js` where a Bugsnag API key was hardcoded directly into client-side JavaScript, making it visible to anyone who inspects the page source or JavaScript bundle. The fix replaces the hardcoded string with an environment variable reference (`import.meta.env.VITE_BUGSNAG_API_KEY`), ensuring the key is injected at build time rather than baked into the shipped code. This pattern is one of the most common — and most avoidable — secrets exp

high

How Hardcoded API Keys happen in JavaScript and how to fix it

A critical security vulnerability was discovered in `javascripts/common.js` where Firebase API keys, auth domains, and sender IDs were hardcoded directly in client-side JavaScript. Any user who opened browser DevTools or viewed page source could extract these credentials and make unauthorized calls to the Firebase Realtime Database and Yandex Translation services. The fix moves all sensitive configuration values to environment variables, ensuring secrets never reach the client bundle.

critical

How Plaintext Credential Storage Happens in Node.js Config Files and How to Fix It

A critical vulnerability in `config.js` allowed OAuth tokens and user IDs to silently fall back to empty strings when environment variables were unset, enabling credential bypass and potential hardcoded secret exposure. The fix removes the `|| ""` fallback pattern, ensuring credentials are either properly set or explicitly `undefined`, and updates downstream checks to use truthy evaluation instead of empty-string comparison. This change closes a subtle but dangerous gap that could have allowed A

critical

How Hardcoded API Keys happen in JavaScript plugins and how to fix them

A critical hardcoded API key was discovered in `plugins/ocr.js` at line 21, where the OCR integration used a plaintext fallback credential `'K81241004488957'` whenever the `OCR_API_KEY` environment variable was absent. This exposed a live API key to anyone with repository access, enabling unauthorized use of the OCR service. The fix removes the hardcoded fallback entirely and fails fast with a clear error message when the required environment variable is not configured.

critical

How Archive Path Traversal Happens in Node.js and How to Fix It

CVE-2026-53486 is a critical path traversal vulnerability in the Decompress library, where crafted archive entries can write files and symbolic links outside the intended extraction directory. This vulnerability was transitively introduced through `@vitest/browser` and related packages pinned at version 4.1.5, and was resolved by upgrading to 4.1.6 and 5.0.0-beta.3. Left unpatched, an attacker who controls an archive file processed by any downstream consumer of this dependency chain could overwr