Back to Blog
critical SEVERITY7 min read

How hardcoded API key placeholders in documentation happen in Python and how to fix it

A high-severity security issue was discovered in the Context7 API documentation where a hardcoded API key placeholder (`CONTEXT7_API_KEY`) could be copied directly into production code. The fix replaced the static string with a proper environment variable reference using `os.environ`, preventing developers from accidentally deploying exposed credentials.

O
By Orbis AppSec
Published July 6, 2026Reviewed July 6, 2026

Answer Summary

This vulnerability involves hardcoded API key placeholders in Python documentation (CWE-798: Use of Hard-coded Credentials). The `docs/api-guide.mdx` file contained `"Bearer CONTEXT7_API_KEY"` as a static string in code examples, which developers might copy-paste into production without replacing it with actual environment variables. The fix imports Python's `os` module and replaces the hardcoded placeholder with `os.environ['CONTEXT7_API_KEY']`, ensuring credentials are loaded from environment variables at runtime rather than being embedded in source code.

Vulnerability at a Glance

cweCWE-798
fixReplace hardcoded placeholder with `os.environ['CONTEXT7_API_KEY']` pattern
riskDevelopers may copy-paste example code with placeholder credentials into production
languagePython
root causeDocumentation used literal string "CONTEXT7_API_KEY" instead of environment variable pattern
vulnerabilityHardcoded API Key Placeholder in Documentation

Introduction

In the Context7 API documentation repository, we discovered a high-severity security issue in docs/api-guide.mdx at line 67. The "Complete Workflow Example" section contained a Python code snippet that demonstrated API authentication using a hardcoded string "Bearer CONTEXT7_API_KEY" instead of showing developers the proper pattern for loading credentials from environment variables. While this may seem like an innocent documentation example, it creates a dangerous copy-paste vulnerability where developers implementing the API might use this exact code in production without realizing they need to replace the placeholder with actual credential management.

The vulnerability was flagged by the multi_agent_ai scanner using rule V-001, which identified that the documentation pattern could lead to credential exposure in downstream applications. Since Context7 is a Node.js library consumed by other developers, any security education issues in its documentation can propagate to hundreds or thousands of dependent projects.

The Vulnerability Explained

Let's examine the vulnerable code from docs/api-guide.mdx:

import requests

headers = {"Authorization": "Bearer CONTEXT7_API_KEY"}

# Step 1: Search for the library
search_response = requests.get(

The problem here is subtle but critical. The code uses "Bearer CONTEXT7_API_KEY" as a literal string value in the Authorization header. While experienced developers might recognize this as a placeholder, the pattern creates several risks:

  1. Copy-paste vulnerability: Developers following the documentation might copy this code directly into their application without modifying the credential handling
  2. Ambiguous placeholder: The format CONTEXT7_API_KEY looks like a valid environment variable name, but it's being used as a string literal rather than being loaded from the environment
  3. No secure pattern demonstration: The example doesn't teach developers the correct way to handle API credentials in Python

How Could This Be Exploited?

Consider this attack scenario specific to Context7 users:

  1. A developer reads the API guide and copies the example code into their application's api_client.py file
  2. They run the code and it "works" initially because the API endpoint returns a helpful error message about invalid credentials
  3. The developer assumes they need to "activate" their CONTEXT7_API_KEY somehow, not realizing they need to replace the entire credential-loading pattern
  4. They commit this code to their repository with the hardcoded placeholder
  5. An attacker scanning public GitHub repositories searches for the pattern "Bearer CONTEXT7_API_KEY" and finds dozens of projects using this exact string
  6. The attacker can now identify all applications that followed this documentation pattern and likely have credential management issues

Even worse, if a developer does eventually replace CONTEXT7_API_KEY with their actual API key (like "Bearer sk_live_abc123..."), they've now hardcoded real credentials in their source code—exactly the opposite of secure credential management.

Real-World Impact

For Context7 as a Node.js library, this documentation issue affects every downstream consumer. If 1,000 developers use this library and 10% copy-paste the example code without modification, that's 100 applications potentially exposing API credentials. The vulnerability isn't in Context7's code itself, but in how it teaches developers to use the API—a form of "security education debt" that compounds across the ecosystem.

The Fix

The security fix makes three specific changes to docs/api-guide.mdx:

+import os
 import requests

-headers = {"Authorization": "Bearer CONTEXT7_API_KEY"}
+headers = {"Authorization": f"Bearer {os.environ['CONTEXT7_API_KEY']}"}

Let's break down each change:

1. Import the os module

import os

This adds Python's built-in os module, which provides access to environment variables through os.environ.

2. Replace hardcoded string with environment variable lookup

# Before (vulnerable):
headers = {"Authorization": "Bearer CONTEXT7_API_KEY"}

# After (secure):
headers = {"Authorization": f"Bearer {os.environ['CONTEXT7_API_KEY']}"}

The fix uses an f-string (formatted string literal) to dynamically construct the Authorization header by reading the CONTEXT7_API_KEY value from the environment at runtime. This demonstrates the correct pattern: credentials should never be hardcoded as string literals, but should always be loaded from external configuration.

Why This Specific Change Works

The new code provides three security improvements:

  1. Runtime credential loading: The API key is read from os.environ when the code executes, not embedded in the source code
  2. Clear pattern demonstration: Developers copying this example will implement proper environment variable handling by default
  3. Fail-safe behavior: If the environment variable isn't set, Python raises a KeyError immediately, preventing the application from running with missing credentials (rather than silently using a placeholder)

The fix also maintains the educational value of the documentation—developers can still follow the complete workflow example, but now they're learning the secure pattern from the start.

Prevention & Best Practices

1. Always Demonstrate Secure Patterns in Documentation

When writing API documentation with code examples, never use bare string literals for credentials, even as placeholders. Instead, show the actual secure implementation:

# ❌ Bad: Looks like a placeholder but teaches wrong pattern
api_key = "YOUR_API_KEY_HERE"

# ✅ Good: Demonstrates proper environment variable usage
api_key = os.environ['API_KEY']

# ✅ Better: Includes error handling
api_key = os.getenv('API_KEY')
if not api_key:
    raise ValueError("API_KEY environment variable not set")

2. Use Linters to Catch Documentation Issues

Configure security linters to scan documentation files, not just source code. Tools like Semgrep can detect patterns in Markdown code blocks:

rules:
  - id: hardcoded-api-key-in-docs
    pattern: |
      headers = {"Authorization": "Bearer $KEY"}
    message: "Use os.environ['KEY'] instead of hardcoded strings"
    languages: [python]
    severity: WARNING

3. Provide Complete Setup Instructions

Documentation should include a dedicated "Configuration" section that explains how to set environment variables before showing code examples:

## Configuration

Set your API key as an environment variable:

```bash
export CONTEXT7_API_KEY="your_actual_key_here"

Then use it in your code:

import os
headers = {"Authorization": f"Bearer {os.environ['CONTEXT7_API_KEY']}"}
### 4. Consider Secrets Management for Production

For production applications, document integration with secrets management services:

```python
# Using AWS Secrets Manager
import boto3
import json

def get_api_key():
    client = boto3.client('secretsmanager')
    response = client.get_secret_value(SecretId='context7/api-key')
    return json.loads(response['SecretString'])['api_key']

headers = {"Authorization": f"Bearer {get_api_key()}"}

5. Security Standards Reference

This vulnerability maps to several security standards:

  • CWE-798: Use of Hard-coded Credentials
  • OWASP Top 10 2021 - A07: Identification and Authentication Failures
  • NIST SP 800-53: IA-5 (Authenticator Management)

Key Takeaways

  • Documentation code is production code: Examples in docs/api-guide.mdx are copied directly into applications, so they must demonstrate secure patterns, not just functional patterns
  • The placeholder "CONTEXT7_API_KEY" was dangerous: Even though it looks like a placeholder, using it as a string literal teaches developers the wrong credential management pattern
  • Environment variables are the minimum security bar: The fix using os.environ['CONTEXT7_API_KEY'] demonstrates the baseline secure approach that all Python developers should follow
  • Library maintainers have ecosystem responsibility: Since Context7 is a Node.js library used by other developers, its documentation security directly impacts hundreds of downstream applications
  • Static analysis works on documentation: The multi_agent_ai scanner successfully detected this issue in a Markdown file, proving that security scanning should extend beyond just .py or .js files

How Orbis AppSec Detected This

  • Source: The hardcoded string literal "CONTEXT7_API_KEY" in the Python code example within docs/api-guide.mdx
  • Sink: The Authorization header construction at line 67, where the placeholder could be copied into production code without modification
  • Missing control: No demonstration of environment variable loading or secure credential management in the example code
  • CWE: CWE-798 (Use of Hard-coded Credentials)
  • Fix: Added import os and replaced the hardcoded string with os.environ['CONTEXT7_API_KEY'] to demonstrate proper environment variable usage

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

This vulnerability demonstrates that security issues aren't limited to application code—documentation examples can create just as much risk when they teach insecure patterns. The fix to docs/api-guide.mdx was straightforward: replace the hardcoded "Bearer CONTEXT7_API_KEY" string with proper environment variable loading using os.environ. But the broader lesson is that every code example in documentation should be production-ready and demonstrate security best practices by default.

For developers working on libraries and APIs, remember that your documentation is often the first (and sometimes only) security education your users receive. Make sure every example teaches secure coding from the start, not just functional coding that "works" but creates vulnerabilities downstream.

References

Frequently Asked Questions

What is hardcoded API key placeholder vulnerability?

It occurs when documentation or example code contains literal credential placeholders (like "API_KEY" or "CONTEXT7_API_KEY") that developers might accidentally use in production instead of replacing them with actual environment variables or secrets management patterns.

How do you prevent hardcoded API key placeholders in Python?

Always demonstrate proper credential handling in examples using `os.environ['KEY_NAME']`, `os.getenv('KEY_NAME')`, or secrets management libraries. Never use bare string literals that look like valid credentials, even as placeholders.

What CWE is hardcoded API key placeholder vulnerability?

CWE-798 (Use of Hard-coded Credentials) covers this vulnerability type, as it involves credentials embedded directly in source code or documentation rather than being externalized through secure configuration management.

Is using ALL_CAPS placeholder names enough to prevent hardcoded API key issues?

No. While ALL_CAPS suggests a placeholder, developers frequently copy-paste example code without modification. You must demonstrate the actual secure pattern (environment variables, secrets managers) in your examples, not just use a naming convention.

Can static analysis detect hardcoded API key placeholders?

Yes. Modern security scanners can detect patterns like `"Bearer [A-Z_]+"` in documentation and code examples, flagging them as potential security education issues that could lead to credential exposure if copied into production.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #2841

Related Articles

medium

How stack buffer overflow happens in C PMenu_Do_Update() and how to fix it

A stack buffer overflow in `PMenu_Do_Update()` within `src/menu/menu.c` allowed repeated unchecked `sprintf()` calls to overflow a fixed 1400-byte stack buffer when menu entries contained long text strings. The fix replaces every `sprintf(string + strlen(string), ...)` call with `snprintf(string + len, sizeof(string) - len, ...)`, tracking remaining buffer space and preventing writes beyond the buffer boundary.

critical

How out-of-bounds array access happens in C kernel modules and how to fix it

A high-severity out-of-bounds array access vulnerability was discovered in the natflow_conntrack.c kernel module where the `ct->proto.tcp.state` value was used directly as an array index without bounds validation. An attacker capable of manipulating TCP connection state could trigger reads beyond the `tcp_conntrack_names[]` array, potentially leaking kernel memory or causing system crashes. The fix adds a simple bounds check using `ARRAY_SIZE()` before array access.

critical

How argument injection happens in Node.js Copilot tool bridge and how to fix it

A high-severity argument injection vulnerability was discovered in the Copilot tool bridge (`bridge.ts`) where user-controlled `request.args` were passed directly to `tool.execute()` without any validation or sanitization. The fix introduces Zod schema validation at line 108, ensuring that tool arguments are parsed against a declared `inputSchema` before execution. This prevents malformed or malicious payloads — including prototype pollution attempts — from reaching the underlying tool implement

high

How Missing Dependabot Cooldown happens in GitHub Actions and how to fix it

A high-severity supply chain vulnerability was discovered in a Dependabot configuration file that lacked cooldown periods for package updates. Without cooldown settings, Dependabot could propose updates to newly published—and potentially malicious—packages immediately after release. The fix adds a 7-day cooldown period to all three package ecosystems (npm, GitHub Actions, and Maven), giving the community time to identify compromised packages before they're automatically proposed.

critical

How command injection happens in Python os.popen() and how to fix it

A critical command injection vulnerability in `spk/itools/src/mounting.py` allowed arbitrary shell command execution through unsanitized iOS device names passed to `os.popen()` and `os.system()` calls. The fix replaced these dangerous functions with `subprocess.run()` using proper argument escaping, eliminating the shell injection attack vector.

high

How CORS credential reflection happens in Hono middleware and how to fix it

A high-severity CORS misconfiguration in Hono's middleware (CVE-2026-54290) allowed any origin to be reflected with credentials when the `origin` option defaulted to wildcard. This vulnerability in the studio frontend could enable attackers to steal authenticated user data through cross-origin requests. The fix upgrades Hono from 4.12.21 to 4.12.25, which properly handles CORS origin validation.