Skip to content

Most CLAUDE.md Security Rules Have No Built-In Control That Matches Them

Johannes KeienburgJohannes Keienburg, CEO & Founder
Published August 26, 2026
View as MarkdownView this page as plain textOpen in ChatGPTAsk ChatGPT about this pageOpen in ClaudeAsk Claude about this page
Copied

1Only 4.4% of the Rules Had a Control Covering the Whole Rule

Developers write security rules into the CLAUDE.md files their coding agents read: never commit secrets, ask before deleting production data. Ting Yan's paper When "Do Not" Is Not Deny, posted to arXiv on August 24, 2026, read 481 public CLAUDE.md files. It checked how many of those rules a coding agent could apply through a built-in control, one of its own allow and deny permission settings. For most rules it could not, and the file does not say which ones.

This is a usable security problem: CLAUDE.md is a write-only channel. A developer writes a security rule but gets no feedback on whether a control will enforce it.

Ting Yan, arXiv, August 24, 2026

A parser keyed on rule words like must, never and ask before pulled 4,661 candidate segments out of those files, and an LLM classifier marked 870 as security-related. How many had a matching control depends on how much of a rule the control must cover, so the paper reports a range of roughly 4% to 16% instead of one figure. Its strictest adjudicated standard puts the number at 4.4%, with a 95% confidence interval of 2.6 to 6.7.

2A Built-In Control Cannot Express the Condition That Makes an Action Wrong

Where the classifier wrongly credited a control, the paper's error analysis found four recurring kinds of rule a built-in control cannot express. One is a condition, such as running a publish command only when cutting a release. Another is content rather than location, which is what never commit secrets asks for, because built-in controls match commands and paths while none reads what a commit contains. A third is access control that turns on meaning or system state. The fourth is a data-flow requirement, such as allowing only model API calls out to the network.

a built-in control matches a written rule only when it covers the whole rule: the same action, the same target, the condition that makes the action wrong, and who must approve it.

Ting Yan, arXiv, August 24, 2026

That last clause is where an approval rule sits, which is why a written "ask before" rule does not on its own put a person in the loop. The extractor caught 66.3% of the security rules in a file, so every rate above describes only the rules it found, and the paper calls its per-category breakdown exploratory. The corpus is a capped, relevance-ranked slice of GitHub code search rather than a random sample, and it skews new and low-visibility: 93% of the segments come from repositories created in 2025 and 2026, and 58% of those repositories have no stars. The authors do not extend the rate to large, established projects. They also do not measure whether a team enforces a rule some other way, through continuous integration, hooks or its own tooling, so a rule with no matching control is not automatically unprotected.

The Model Context Protocol (MCP) ran into the same split in July. Its revision left no field on a tool call for the person who decided it should happen.

Source: Ting Yan, When "Do Not" Is Not Deny: Security Rules in CLAUDE.md vs Built-In Controls, arXiv:2608.23550, August 24, 2026.