The Sourcemap Slip: Deconstructing the Claude Code Leak and the Rise of Shadow Agents

When an npm configuration error inadvertently open-sourced Anthropic’s state-of-the-art AI coding CLI

Agentic-AI
Security
Author

Renan Monteiro Barbosa

Published

April 1, 2026

In the rapidly evolving world of agentic AI, Anthropic’s release of “Claude Code” was meant to be a landmark moment for proprietary coding tools. However, what followed was a masterclass in how a single configuration oversight—and perhaps a runtime bug—can alter the trajectory of a product launch. This article explores the recent leak of Claude Code’s source code, the emergence of community projects like clawd-code, and the profound questions this event raises for the future of AI development.

1. The Incident: A Sourcemap in the Wild

In late March 2026, Anthropic released Claude Code, a highly anticipated agentic CLI tool designed to allow developers to build and refactor codebases using Claude 3.7 Sonnet. Within hours of its release on the npm registry, security researchers discovered that the production package contained a massive 60MB sourcemap.[1]

While initially blamed on a CI/CD packaging error, some researchers pointed to a potential production sourcemap bug in Bun, the runtime Anthropic recently acquired.[2] This irony wasn’t lost on the community: the very toolchain Anthropic purchased to build their “walled garden” was the one that accidentally opened the gates.

2. Under the Hood: The “Secret Sauce” Revealed

The leaked source code (v2.1.88) provided a rare, unfiltered glimpse into Anthropic’s agentic reasoning and their commercial defensive strategies.[2]

KAIROS: The Autonomous Ghost in the Machine

Perhaps the most significant discovery was KAIROS, an unreleased autonomous agent mode. Unlike the standard interactive CLI, KAIROS appears designed to run as a background daemon, featuring:

  • Nightly Memory Distillation: A process where the agent summarizes its daily learnings into a persistent long-term memory buffer.
  • Background Workers: The ability to execute long-running tasks without blocking the user’s terminal.

Anti-Distillation: Poisoning the Well

To protect their intellectual property, the leak revealed that Anthropic implemented “Anti-Distillation” measures. These are decoy tool definitions and synthetic reasoning traces designed to “poison” the training data of any competitor attempting to scrape or “distill” Claude’s output to train their own models.[2]

This can be found in claude.ts (line 301-313), there’s a flag called ANTI_DISTILLATION_CC. When enabled, Claude Code sends anti_distillation: [‘fake_tools’] in its API requests. This tells the server to silently inject decoy tool definitions into the system prompt.

  // Anti-distillation: send fake_tools opt-in for 1P CLI only
  if (
    feature('ANTI_DISTILLATION_CC')
      ? process.env.CLAUDE_CODE_ENTRYPOINT === 'cli' &&
        shouldIncludeFirstPartyOnlyBetas() &&
        getFeatureValue_CACHED_MAY_BE_STALE(
          'tengu_anti_distill_fake_tool_injection',
          false,
        )
      : false
  ) {
    result.anti_distillation = ['fake_tools']
  }

This is done so in theory if someone is recording Code’s API traffic to train a competing model, the fake tools pollute that training data. It’s gated behind a GrowthBook feature flag (tengu_anti_distill_fake_tool_injection) and only active for first-party CLI sessions.

There is also another mechanism in betas.ts (lines 279-298), server-side connector-text summarization. This tool, when enabled, the API buffers the assistant’s text between tool calls, summarizes it, and returns the summary with a cryptographic signature. On subsequent turns, the original text can be restored from the signature. If you’re recording API traffic, you only get the summaries, not the full reasoning chain.

  // POC: server-side connector-text summarization (anti-distillation). The
  // API buffers assistant text between tool calls, summarizes it, and returns
  // the summary with a signature so the original can be restored on subsequent
  // turns — same mechanism as thinking blocks. Ant-only while we measure
  // TTFT/TTLT/capacity; betas already flow to tengu_api_success for splitting.
  // Backend independently requires Capability.ANTHROPIC_INTERNAL_RESEARCH.
  //
  // USE_CONNECTOR_TEXT_SUMMARIZATION is tri-state: =1 forces on (opt-in even
  // if GB is off), =0 forces off (opt-out of a GB rollout you were bucketed
  // into), unset defers to GB.
  if (
    SUMMARIZE_CONNECTOR_TEXT_BETA_HEADER &&
    process.env.USER_TYPE === 'ant' &&
    includeFirstPartyOnlyBetas &&
    !isEnvDefinedFalsy(process.env.USE_CONNECTOR_TEXT_SUMMARIZATION) &&
    (isEnvTruthy(process.env.USE_CONNECTOR_TEXT_SUMMARIZATION) ||
      getFeatureValue_CACHED_MAY_BE_STALE('tengu_slate_prism', false))
  ) {
    betaHeaders.push(SUMMARIZE_CONNECTOR_TEXT_BETA_HEADER)
  }

Eventought these mechanisms exist, circumventing them is fairly easy. The activation logic in claude.ts, the fake tools injection requires all four conditions to be true:

The ANTI_DISTILLATION_CC compile-time flag, the cli entrypoint, a first-party API provider, and the tengu_anti_distill_fake_tool_injection GrowthBook flag returning true.

A MITM proxy that strips the anti_distillation field from request bodies before they reach the API would bypass it entirely, since the injection is server-side and opt-in.

  • The shouldIncludeFirstPartyOnlyBetas() function also checks for CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS, so setting that env var to a truthy value disables the whole thing.

  • And if you’re using a third-party API provider or the SDK entrypoint instead of the CLI, the check never fires at all.

The connector-text summarization is even more narrowly scoped, Anthropic-internal-only (USER_TYPE === 'ant'), so external users won’t encounter it regardless.

With very little effort one can find the workarounds in about an hour of reading the source. The real protection is probably legal, not technical. But that there are issues too regarding legal protection as we will see later.

Provider-Aware thinking

We can see in the thinking.ts (lines 88-110) that there is logic to detect the model provider and ANthropic even has work in progress towards strategies like probing unknown models via API error detection.

// TODO(inigo): add support for probing unknown models via API error detection
// Provider-aware thinking support detection (aligns with modelSupportsISP in betas.ts)
export function modelSupportsThinking(model: string): boolean {
  const supported3P = get3PModelCapabilityOverride(model, 'thinking')
  if (supported3P !== undefined) {
    return supported3P
  }
  if (process.env.USER_TYPE === 'ant') {
    if (resolveAntModel(model.toLowerCase())) {
      return true
    }
  }
  // IMPORTANT: Do not change thinking support without notifying the model
  // launch DRI and research. This can greatly affect model quality and bashing.
  const canonical = getCanonicalName(model)
  const provider = getAPIProvider()
  // 1P and Foundry: all Claude 4+ models (including Haiku 4.5)
  if (provider === 'foundry' || provider === 'firstParty') {
    return !canonical.includes('claude-3-')
  }
  // 3P (Bedrock/Vertex): only Opus 4+ and Sonnet 4+
  return canonical.includes('sonnet-4') || canonical.includes('opus-4')
}

This is interesting find, because allows them to control the performance of other models using their tool. Even they allegedly support using custom models Add a custom model option by using environment variables (ANTHROPIC_CUSTOM_MODEL_OPTION) to configure custom endpoints, or by using tools like LiteLLM or Claudish to route requests to OpenAI, Gemini, or local models via Ollama. The /model command allows switching within the terminal. They have code in place to detect the model and more logic in place to gatekeep its performance.

The “Frustration” Regex

One of the top LLM companies using regex for sentiment analysis is nothing short of hilarious, of all things—specifically designed to detect user frustration. If a user’s prompt matches certain patterns of anger or disappointment, the agent is instructed to shift into a more conciliatory “recovery mode.”

userPromptKeywords.ts contains a regex pattern that detects user frustration:

/\b(wtf|wth|ffs|omfg|shit(ty|tiest)?|dumbass|horrible|awful|
piss(ed|ing)? off|piece of (shit|crap|junk)|what the (fuck|hell)|
fucking? (broken|useless|terrible|awful|horrible)|fuck you|
screw (this|you)|so frustrating|this sucks|damn it)\b/

3. The DRM Layer: Native Client Attestation

The leak confirmed a controversial theory regarding Anthropic’s “technical warfare” against third-party tools. Inside the Bun/Zig layer, Anthropic implemented Native Client Attestation.[3]

This can be found in system.ts (lines 59-95), API requests include a cch=00000 placeholder.

/**
 * Get attribution header for API requests.
 * Returns a header string with cc_version (including fingerprint) and cc_entrypoint.
 * Enabled by default, can be disabled via env var or GrowthBook killswitch.
 *
 * When NATIVE_CLIENT_ATTESTATION is enabled, includes a `cch=00000` placeholder.
 * Before the request is sent, Bun's native HTTP stack finds this placeholder
 * in the request body and overwrites the zeros with a computed hash. The
 * server verifies this token to confirm the request came from a real Claude
 * Code client. See bun-anthropic/src/http/Attestation.zig for implementation.
 *
 * We use a placeholder (instead of injecting from Zig) because same-length
 * replacement avoids Content-Length changes and buffer reallocation.
 */
export function getAttributionHeader(fingerprint: string): string {
  if (!isAttributionHeaderEnabled()) {
    return ''
  }

  const version = `${MACRO.VERSION}.${fingerprint}`
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? 'unknown'

  // cch=00000 placeholder is overwritten by Bun's HTTP stack with attestation token
  const cch = feature('NATIVE_CLIENT_ATTESTATION') ? ' cch=00000;' : ''
  // cc_workload: turn-scoped hint so the API can route e.g. cron-initiated
  // requests to a lower QoS pool. Absent = interactive default. Safe re:
  // fingerprint (computed from msg chars + version only, line 78 above) and
  // cch attestation (placeholder overwritten in serialized body bytes after
  // this string is built). Server _parse_cc_header tolerates unknown extra
  // fields so old API deploys silently ignore this.
  const workload = getWorkload()
  const workloadPair = workload ? ` cc_workload=${workload};` : ''
  const header = `x-anthropic-billing-header: cc_version=${version}; cc_entrypoint=${entrypoint};${cch}${workloadPair}`

  logForDebugging(`attribution header ${header}`)
  return header
}

This system works by injecting a cryptographic hash (the cch header) into outgoing API requests directly at the HTTP stack level, below the reach of JavaScript. This ensures that only the official, unmodified Claude Code binary can access specific high-end models at subscription-based rates, effectively blocking third-party open-source tools from “spoofing” the client to avoid expensive per-token API costs.

This is the technical enforcement behind the OpenCode legal fight. Anthropic doesn’t just ask third-party tools not to use their APIs; the binary itself cryptographically proves it’s the real Claude Code client. Now that this mechanism has been uncovered it seems great.

4. The Irony: Anthropic on the Other Side of the Fence

For a company that built its brand on AI safety, transparency, and “Constitutional AI,” this incident has sparked intense debate. Anthropic now finds itself on the “other side of the fence,” employing the very tactics—obfuscation, DRM-like enforcement, and legal threats—that many in the open-source community criticize.

The OpenCode Crackdown

Just weeks before the leak, Anthropic issued legal threats to the maintainers of OpenCode, a popular open-source alternative.[3] OpenCode was forced to remove features that allowed users to use their Claude Pro subscriptions instead of official API keys. The leak has now exposed the exact technical mechanisms Anthropic used to enforce this “walled garden,” turning their secret enforcement code into public knowledge.

5. Conclusion: A New Paradigm for Open-Source Agents

The leak of Claude Code via an npm sourcemap may be remembered as a turning point in the AI era. It has accelerated the development of open-source agentic tools and forced a reckoning with the fragility of proprietary software in the age of LLMs.

As projects like clawd-code continue to evolve by leveraging these leaked insights, the line between proprietary and open-source AI is blurring. For developers, this means more choices and greater transparency. For AI labs, it’s a stark reminder that in the world of software, the “vibes” are only as strong as your build configuration—and your commitment to the community you serve.


Stay Updated

This is a rapidly evolving story. I will continue to update this post as new information about the clawd-code project and Anthropic’s response becomes available.

1. Kuber. (2026). Claude code’s entire source code got leaked via a sourcemap in npm, let’s talk about it. https://kuber.studio/blog/AI/Claude-Code's-Entire-Source-Code-Got-Leaked-via-a-Sourcemap-in-npm,-Let's-Talk-About-it
2. Kim, A. (2026). The claude code source leak: Fake tools, frustration regexes, and bun’s hidden zig layers. https://alex000kim.com/posts/2026-03-31-claude-code-source-leak/
3. WinBuzzer. (2026). Anthropic crackdown on OpenCode: Legal threats and zig-level DRM. https://winbuzzer.com/2026/03/anthropic-opencode-legal-threats/