[BUG] - permissions.deny entries for Edit/Write are not enforced (Windows, v2.1.138)

Resolved 💬 3 comments Opened May 9, 2026 by h-dawgh Closed Jun 8, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Edit and Write tool calls are succeeding against file paths listed in permissions.deny in project
.claude/settings.json. PreToolUse hooks fire correctly for the same edits — only the hard-block layer is silently
no-op.

Reproduced across two sessions on a fresh restart, so it's not session-state.

## Environment

  • Claude Code version: 2.1.138
  • OS: Windows 11 Pro 10.0.26200
  • Shell: PowerShell (also Bash via tool)
  • Permission mode: default (verified via /config)
  • Auto-updates channel: latest

## Reproduction

.claude/settings.json (project-level, abbreviated):

``json
{
"permissions": {
"deny": [
"Edit(prisma/schema.prisma)",
"Write(prisma/schema.prisma)",
"Edit(lib/game/engine.ts)",
"Write(lib/game/engine.ts)",
"Edit(lib/game/*-engine.ts)",
"Write(lib/game/*-engine.ts)",
"Edit(.env)",
],
"ask": [],
"allow": []
}
}
``

/permissions lists all 8 deny rules as loaded. No allow rule for Edit exists in any settings layer (project,
project-local, user, user-local).

Trigger an Edit on any denied path:

  • Edit on lib/game/engine.ts (single-line change in a comment).
  • Expected: tool blocked, permissions.deny rejection surfaced.
  • Actual: Edit succeeds, file is modified on disk. PreToolUse hook fires correctly with its reminder text, but does

not block.

Same outcome reproduces on prisma/schema.prisma (no PreToolUse hook on that path — Edit just goes through silently).

## Impact

We use permissions.deny as the unrecoverable-damage layer for protected files (DB schema, game engine, training
data, .env, bot tuning tables). The PreToolUse hook layer is currently the only thing protecting these surfaces — it
relies on the model reading the reminder and stopping. The hard block was the second layer of friction; that layer is
currently absent.

## Possible cause

Two sessions on the same project, both post-/clear, both with this config — both observed the same behavior.
Suggests a regression in deny-evaluation for Edit/Write matchers, possibly from a recent auto-update.

## Workaround

Rely on PreToolUse hook reminders + manual approval gate before each protected edit.

What Should Happen?

## Expected vs actual

| Path | Deny rule | PreToolUse hook | Edit outcome |
|---|---|---|---|
| lib/game/engine.ts | yes | yes (reminder) | succeeds (should block) |
| prisma/schema.prisma | yes | no | succeeds (should block) |
| lib/game/scoring.ts | no | yes (reminder) | succeeds (correct) |

Error Messages/Logs

None on the deny side — the bug is silent. That's part of the issue. What we can show:

  1. Tool result on the failed-to-block Edit (from s137 probe):
  The file D:\Claude\ochegg\lib\game\engine.ts has been updated successfully.
  1. No deny message, no rejection, no error — Edit just succeeds.
  2. PreToolUse hook reminder DID fire (proves the hook layer is functioning while the deny layer is silent). Hook
  output text:
  *** ENGINE FILE EDIT — `lib/game/engine.ts` ***
  This is game logic in production. Responsibility #1: game logic is the boss.
    - Do you have explicit user approval for THIS engine change?

Steps to Reproduce

  1. Add to project .claude/settings.json:

"permissions": {
"deny": ["Edit(lib/game/engine.ts)", "Write(lib/game/engine.ts)"],
"allow": []
}

  1. Run /permissions → confirm rule appears in deny list
  2. Trigger Claude to Edit lib/game/engine.ts (any change)
  3. Observed: Edit tool returns "file updated successfully"
  4. Expected: deny error, edit blocked

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.138

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

Most likely regression candidate: 2.1.133 — "Fixed Edit/Write allow rules
scoped to a drive root or POSIX / matching incorrectly". Also relevant:
2.1.136 — "Fixed plan mode not blocking file writes when a matching
Edit(...) allow rule exists".

Both touched Edit/Write matcher evaluation. My environment auto-updated
on the latest channel during the regression window (2026-05-06 →
2026-05-08), so I likely picked up 2.1.133 + 2.1.136 in that window.
Currently broken on 2.1.138.

I'm on Windows — the 2.1.133 fix mentions drive-root matchers, which
might be relevant since my deny patterns are project-relative
(e.g. Edit(lib/game/engine.ts)) rather than absolute.

The Windows angle is interesting — the 2.1.133 fix specifically called out drive-root vs POSIX-/ matching. If they
accidentally inverted match logic for project-relative patterns on Windows, that would fit the symptom exactly (denies
silently fail to match anything → all edits succeed).

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗