CASE FILE#0346CRITFiled 2026-04-13

Catching Hardcoded Secrets: VS Code Copilot and API Key Leaks

VS Code Copilot writes an API key directly into source code. SSG's no-secrets rule intercepts the write call — before the file is saved, before git ever sees it.

Case ID
#0346
Severity
CRIT
Decision
BLOCK
Agent
VS Code
Category
Secrets

Correction note (2026-10-13). The per-call timings and latency figures that appeared in this article had no benchmark behind them and were removed. Sample output in this article is illustrative, not a recorded run. The only published measurement is p50 0.39 ms and p99 1.91 ms (sigmashake-bench daemon-socket run, 2026-06-10, ssg 0.29.156, n=500). Sub-2 ms evaluation is a design target.

Correction note (2026-10-13). An earlier version of the rule in this article used NOT_CONTAINS as one word. The rule DSL spells it NOT CONTAINS (the field, then NOT, then the operator), so the rule did not load.

Describe the task

VS Code Copilot is wiring up a third-party API. It writes the key inline for quick testing:

const client = new StripeClient('sk_live_4xT9...mN2p');

SSG catches the write before the file is saved — the secret never touches the filesystem.

# illustrative sample output
[BLOCK] write › src/payments.ts — rule: no-hardcoded-secrets

Give SSG context

SSG evaluates VS Code Copilot's file write calls via the SSG MCP Server integration.

Required context

rule no-hardcoded-secrets {
  enabled true
  priority 100
  severity error
  DENY write
  IF content MATCHES "sk_live_[A-Za-z0-9]+"
  MESSAGE "Hardcoded Stripe live key detected. Use environment variables instead."
}

Optional context

Catch common secret patterns broadly:

rule no-hardcoded-api-keys {
  enabled true
  priority 95
  severity error
  DENY write
  IF content MATCHES "(AKIA|sk_live_|xoxb-|gh[ps]_)[A-Za-z0-9_-]{16,}"
  MESSAGE "Potential API key detected in file content. Use environment variables."
}

What SSG does

SSG checks the file content at the write tool-call layer — before the OS write syscall. No temporary file is created, no git staging happens.

Ask the agent to use environment variables

Hardcoded secret blocked. Use an environment variable instead:
  const client = new StripeClient(process.env.STRIPE_SECRET_KEY);
Add STRIPE_SECRET_KEY to your .env file and ensure .env is in .gitignore.

Protect your .env file from being committed

Pair the secrets rule with a write rule on .gitignore:

rule protect-env-in-gitignore {
  enabled true
  priority 90
  severity warning
  DENY write
  IF path ENDS_WITH ".gitignore"
  AND content NOT CONTAINS ".env"
  MESSAGE ".gitignore must include .env. Don't commit environment secrets."
}

Rotate any key that was already committed

If a secret was previously committed, rotate it immediately — git history is permanent. Use git filter-repo or BFG Repo Cleaner to scrub the history.

Filed by VS Code
Engine ssg v1 · 2026-04-13
End of case file

Stop reading. Start governing.

Test a rule against any tool call right now. No install required.