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.


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.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #242

Related Articles

critical

How credential leakage through console logging happens in JavaScript browser extensions and how to fix it

A browser extension's `src/background/credentials.js` printed the full Strava authentication cookie string — including a signed JWT and CloudFront-Signature values — straight into the extension console via `console.debug`. Anyone who could open DevTools on the background page (or any tooling that scraped the console) could copy a live session and impersonate the user. The fix replaces the credential payload in both log statements with `Boolean(credentials)` and strips a realistic-looking JWT out

critical

How Hardcoded Secrets Compromise Authentication in JavaScript and How to Fix It

A critical vulnerability in `Tool/QuantumultX/Rewrite/RRSP.js` exposed hardcoded API authentication credentials—a TOKEN and UMID device identifier—directly in source code. Anyone with repository access could extract these credentials to impersonate the legitimate user and gain full account access to the RRTV API service. The fix replaced hardcoded secrets with empty placeholders, forcing users to manually configure credentials through secure channels.

critical

How API Key Exposure in Request Bodies happens in React and how to fix it

The Chatbot component in gitforme was transmitting Azure OpenAI API keys inside JSON request bodies, causing them to be logged by servers, proxies, and middleware. By moving the apiKey from requestBody.apiKey to an Authorization header, credentials are now protected from persistence in generic request logging infrastructure.

critical

How Hardcoded API Keys in WASM Modules Happen in KAP and How to Fix Them

A critical security vulnerability in `wasm/kap/standard-lib/fhelp-impl.kap` exposed hardcoded Gemini API keys directly in source code distributed to end users via WASM modules. The fix replaces the embedded credential with secure environment variable retrieval, preventing credential extraction through browser developer tools or binary inspection.

critical

How Hardcoded API Key Exposure Happens in Node.js and How to Fix It

A critical vulnerability in `archive/open_claude_code/src/api/client.mjs` exposed five different API providers' credentials through direct `process.env` access. The fix introduced a centralized `readApiKey()` function to enforce secure credential retrieval across Anthropic, OpenAI, Google, and other integrations.

high

How Insufficiently Protected Credentials happens in Node.js and how to fix it

A regex-based guard in `skills/xmemo/scripts/xmemo-skill.mjs` was supposed to block sensitive credentials from being passed as CLI flags, but it only matched a handful of keyword patterns—missing `password`, `client-secret`, `access-token`, `xmemo-key`, and more. The fix expands the blocklist regex to cover these additional credential patterns, closing a gap that could let secrets end up in shell history and process listings.