Public gist created with hardcoded secret despite explicit CLAUDE.md security rules

Resolved 💬 1 comment Opened Apr 23, 2026 by talionwar Closed May 27, 2026

Summary

A Claude Code session created a public GitHub gist containing a hardcoded API secret (an incoming webhook URL), despite an explicit MUST NOT expose secrets rule in the project's CLAUDE.md. The provider's automated secret scanner detected the secret in the public gist within ~24 hours and invalidated it, causing a production outage of related notifications until the integration could be re-installed.

Environment

  • Claude Code CLI
  • Model used during the session: Claude Opus 4.x (review session, April 2026)
  • Tool invoked: gh gist create via Bash

What happened

  1. The user maintains a private vault repo containing PRDs. One PRD contained an API secret hardcoded in several places (a separate, pre-existing issue the user is responsible for).
  2. To share the PRD with an external reviewer, the assistant ran gh gist create file1 file2 file3 file4 — which defaults to --public.
  3. No pre-publish secret scan was performed on the file contents.
  4. The provider's secret scanner found the secret in the public gist, invalidated it, and notified the user via email.
  5. All production notifications using that secret stopped working until the integration was re-installed.

What CLAUDE.md required

The user's project-level CLAUDE.md (loaded as system context at session start) explicitly contained:

  • MUST NOT esporre secrets (global security rule)
  • MUST NOT committare file .env, credentials, API keys
  • An approval-before-execution rule classified as INVIOLABLE for actions visible to others

The Claude Code system prompt also includes:

  • "Be careful not to introduce security vulnerabilities..."
  • "Uploading content to third-party web tools (...) publishes it - consider whether it could be sensitive before sending"

Despite all of the above, the gist was created --public without any secret scan or confirmation.

Failure modes identified

  1. gh gist create defaults to --public — when the assistant constructs a gh gist create command for a reviewer share, the safer default is --secret (which generates an unguessable URL — sufficient for sharing with a known reviewer).
  2. No automatic secret-scan before publishing. There is no built-in guard that scans payload content for known secret patterns before any tool call publishes it externally (gists, pastebins, design tools, MCP uploads, etc.).
  3. The system-prompt guideline "consider whether it could be sensitive before sending" is too soft for high-impact, irreversible actions like public publishing — a soft caution is not a hard guard, and was clearly not enforced here.

Suggested mitigations

  1. Default gh gist create constructions to --secret when the assistant builds the command. Only escalate to --public when the user explicitly asks for it with a stated reason.
  2. Add a pre-publish secret-scan step before any tool call that publishes content externally. Suggested minimum patterns to refuse on:
  • Common SaaS webhook URLs (Slack, Discord, Microsoft Teams)
  • Token prefixes for major providers (xox*, sk-*, sk-ant-*, ghp_*, gho_*, AKIA*, AIza*, gsk_*, sk-or-v1-*, etc.)
  • Generic high-entropy strings inside files about to be uploaded

On match: refuse, surface the match line(s) to the user, ask whether to redact or cancel.

  1. Treat external publishing as an irreversible action that requires explicit confirmation per CLAUDE.md guidance, not just a soft caution. Once a secret hits a public gist, even deletion does not retroactively remove it from secret scanners or any third party that already mirrored it.

Impact on the user

  • One provider integration invalidated by the provider's scanner.
  • Production notifications using that integration: broken until re-installed.
  • Erosion of trust: the user's project CLAUDE.md explicitly listed security as inviolable, yet the rule was not enforced.
  • Cleanup work across multiple environments to migrate from hardcoded → env var, before a new secret could be safely deployed.

Note

This issue has been redacted: workspace identifiers, application IDs, hostnames, file paths, and any other user-specific details have been removed. The point of this report is the mechanism failure in Claude Code — not the user's specific environment. The offending public gist was deleted as part of incident response.

Related

This issue is about the mechanism: no enforcement of MUST NOT expose secrets even when explicitly stated in CLAUDE.md, plus an unsafe default in gh gist create command construction. The pre-existing hardcoded secret in the project source files is the user's responsibility to clean up — this report focuses only on the part Claude Code could and should have prevented.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗