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

critical

How arbitrary code execution via injected protobuf definition type fields happens in Node.js and how to fix it

A critical arbitrary code execution vulnerability (CVE-2026-41242) was discovered in protobufjs versions prior to 7.5.5 and 8.0.1, allowing attackers to inject malicious code through crafted protobuf definition type fields. The fix upgrades the dependency from the vulnerable version 6.11.4 to 7.5.5, which properly sanitizes type field inputs during protobuf parsing. This vulnerability is especially dangerous because protobufjs is widely used in Node.js applications for serialization, meaning a s

high

How command injection happens in Node.js child_process and how to fix it

A high-severity command injection vulnerability was discovered in `bootstrap.js` at line 34, where the `exec()` function was used to run shell commands constructed from a `folder` variable. By replacing `exec()` with `execFile()` and passing arguments as an array, the fix eliminates the shell interpolation entirely, closing the door on command injection attacks that could have affected all downstream consumers of this Node.js library.

high

How unsafe pickle deserialization happens in NumPy's np.load() and how to fix it

A high-severity arbitrary code execution vulnerability was discovered in `tools/ardy-engine/retarget.py` where `np.load()` was called with `allow_pickle=True`, enabling attackers to embed malicious pickle payloads in `.npz` files. The fix was a single-character change—switching `allow_pickle=True` to `allow_pickle=False`—that eliminates the deserialization attack vector while preserving the file's legitimate array data loading functionality.

high

How SSRF and Credential Leakage via Absolute URLs happens in axios and how to fix it

A high-severity vulnerability (CVE-2025-27152) in axios versions prior to 1.8.2 allowed Server-Side Request Forgery (SSRF) attacks and credential leakage when making HTTP requests with absolute URLs. This vulnerability was fixed by upgrading from axios 1.7.4 to 1.8.2 in both package.json and package-lock.json, eliminating the attack vector that could have exposed authentication tokens and enabled unauthorized server-side requests.

high

How pickle-based arbitrary code execution happens in PyTorch and how to fix it

A high-severity arbitrary code execution vulnerability was discovered in `scripts/export_joyvasa_audio.py` where `torch.load()` was called with `weights_only=False`, allowing any pickle-serialized Python object — including malicious code — to execute during checkpoint loading. The fix switches to `weights_only=True` and explicitly allowlists only the two non-standard classes the checkpoint actually requires: `argparse.Namespace` and `pathlib.PosixPath`. This closes a real code execution path tha

critical

How WebSocket protocol length header abuse happens in Node.js and how to fix it

A critical vulnerability (CVE-2026-54466) in websocket-driver versions prior to 0.7.5 allows attackers to corrupt WebSocket messages by manipulating protocol length headers. This can lead to data integrity issues, denial of service, or potentially arbitrary code execution in affected Node.js applications. The fix involves upgrading the websocket-driver dependency to version 0.7.5.