Hardcoded secrets and policy text (XL-006)
Updated 2026-05-15What this is
A secret in source is not a secret. Git history is permanent. A key that was committed and then deleted is still in the history, still in every clone, still in every fork. The same applies to LLM system prompts and judge policies bundled into a client binary or a shipped front-end: once it is in the artifact the user downloads, it is readable.
What counts as the secret surface differs by language and packaging:
- Every language: provider key literals (OpenAI
sk-, Anthropicsk-ant-, GoogleAIza, xAIxai-, Groqgsk_), connection strings with embedded passwords,api_key="..."in a client constructor. - Mobile (Kotlin/Swift/Dart): keys in
BuildConfig,Info.plist, or Flutterassets/. - Any client bundle:
system_prompt.txt,judge_criteria.md,tool_policy.jsonshipped to the user.
Same family (XL-006), one concept, per-language and per-packaging detectors.
Why AI emits it
"Just hard-code it for now" prototypes get shipped. The vibe tools emit a pasted key inline when the user pastes it; autocomplete fills it from the clipboard; the placeholder that was meant to be replaced before launch never gets replaced because nothing forces the issue.
The mental model that produces the bug
"I will move it to an env var later." Later does not arrive on its own. The prototype works with the literal in place, the demo passes, and the literal ships because nothing in the loop made the env var the path of least resistance.
What the fix looks like
Read the secret from the environment, and store the value in a secret manager.
api_key=os.environ["OPENAI_API_KEY"], never a literal.- Mobile: do not bundle long-lived credentials in a binary at all. Use a backend-mediated signed request, or a short-lived token exchange.
- System prompts: fetch from the server at runtime, do not ship them in the client.
Rotate anything that was ever committed. Deleting the line does not un-leak the value; the only safe assumption is that a committed secret is already compromised, so the fix is always "rotate, then move to env."
Related
- TLS verification disabled is the same "ship the shortcut" reflex applied to transport security.
RELATED PROBES
- · Python Hardcoded Secret
- · JS Secret Scanner (XL-006)