Skip to content

VNX-LLM-003: Hardcoded LLM API key

Reports Anthropic, OpenAI and Groq API keys by their prefixes, and high-entropy literals assigned to LLM-provider key variables or passed to provider clients; placeholders and environment lookups are ignored.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-LLM-003
Severity Critical
SARIF level error
Kind secrets
Languages Any file
CWE CWE-798
CAPEC CAPEC-191
ATT&CK T1552.001
CWSS vector CWSS:1.0/TI:C/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:C/DI:H/EX:H/EC:N/P:W
Tags secrets llm ai-security credentials
Source internal/sast/rules/vnx-llm-003.rego

Overview

An LLM provider API key, such as an OpenAI key (sk-), an Anthropic key (sk-ant-), or a similar credential, is hardcoded as a string literal in source code or configuration. Hardcoded keys are committed to version control and can be exposed through repository leaks, logs, or build artifacts, allowing anyone who discovers the key to consume your quota or access your data.

Why This Matters

LLM API keys are credentials with real monetary value. A leaked OpenAI key can be used to run expensive inference jobs at your cost, access fine-tuned models, retrieve embeddings from your data, or abuse your usage tier. Attackers actively scan GitHub for exposed keys and begin exploiting them within minutes of exposure. Unlike database passwords, API keys for LLM services are often directly monetizable without any further lateral movement.

What Gets Flagged

Anthropic (sk-ant-api03-...), OpenAI project/service-account/admin (sk-proj-, sk-svcacct-, sk-admin-) and classic (sk-...T3BlbkFJ...) keys anywhere in a file, and a high-entropy literal assigned to a provider-named key variable or passed as api_key/apiKey to a provider client.

# FLAGGED: OpenAI project key passed to the client
client = OpenAI(api_key="sk-proj-<64 random characters>")
# FLAGGED: Anthropic key in a committed .env file
ANTHROPIC_API_KEY=sk-ant-api03-<93 random characters>AA
// FLAGGED: provider-named key constant
export const COHERE_API_KEY = "<40 random characters>";

Not flagged: keys read from the environment (os.environ["OPENAI_API_KEY"]), placeholders (sk-your-openai-api-key-here, sk-ant-xxxx..., REPLACE_WITH_...), sk- inside longer identifiers (task-, desk-), and test or fixture paths.

Remediation

  1. Remove hardcoded keys from all source files and git history.
  2. Rotate any exposed keys immediately via the provider’s dashboard.
  3. Load credentials from environment variables or a secrets manager.
  4. Add key patterns to your .gitignore and pre-commit hooks.
# SAFE: load key from environment variable
import os
client = openai.OpenAI(api_key=os.environ["OPENAI_API_KEY"])

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-llm-003
// nosec vnx-llm-003

Or record an ignore rule: vulnetix ignore add --rule vnx-llm-003 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-llm-003.rego, cli/internal/sast/docs/vnx-llm-003.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.