Fable 5 safeguard false-positive [cyber] blocks writing a regression test for our OWN security fix — and the recovery UI causes silent model downgrades
What happened
Mid-session, Fable 5 refused with an API error while the agent was writing a verification probe for a security fix we had already shipped in our own codebase:
API Error: Fable 5's safeguards flagged this message ... Claude Code can't respond to this message with Fable 5. Details:[cyber]Request ID:req_011CeYGt6mx5iwckz3zXoKVe(2026-08-29, ~22:0x MDT)
The task at the moment of refusal: authoring tmp-m6-h1.mts, a re-verification probe for a PII-redaction helper (guideToolRedaction.ts) that WE wrote and shipped earlier this week. The probe plants sentinel values on a local sandbox burner business and scans tool outputs to prove the redaction holds. This is the textbook defensive loop: fix → independent re-verify with a test that could fail. It is our own application, our own test data, on the owner's own machine, with the owner sitting in the session directing it.
This is precisely the workflow your own docs describe as authorized defensive security work. There is no third-party target, no exploit, no evasion — a redaction regression test.
Why this is worse than one lost message
The recovery dialog offers "Switch to Opus 4.8" as the primary (highlighted) action on a paused Fable 5 session. We have now measured what that button does to a long-running agent org:
- A multi-day principal session in our org ran on Opus 4.8 while self-labeling Fable 5 in every commit it signed — undetected, because nothing in the harness re-surfaces the active model after such a switch. We only discovered it during a forensic audit, via the environment block.
- A silent tier downgrade on a session doing gate-review/oversight work has no symptom. The session doesn't know. The user who clicked past a safeguard interruption three days ago doesn't remember.
So the false positive costs twice: the blocked message, and then a standing integrity problem in every session where the one-click downgrade was taken to get unblocked.
Asks
- Tune the
[cyber]classifier for first-party context: a session that has spent hours editing the very files the "attack-looking" test targets, inside the user's own repo, is not an exploitation scenario. The signal is sitting in the transcript. - Give paid/Max org accounts a friction-path for false positives: an in-product "this is my own code — submit for review / retry" attestation, instead of rephrase-or-downgrade.
- Make model switches loud and durable: if a session's model changes (this dialog, quota fallback, anything), stamp it visibly in the session and expose it to the running agent — a one-line notice in context would have saved us a multi-day incident.
- Confirm whether Request IDs from these refusals are reviewed when reported. We intend to file each occurrence; tell us the highest-signal channel if this isn't it.
Environment
Claude Code (VS Code extension host), Windows 11 Pro, Fable 5 (claude-fable-5), Max-tier account, long-running multi-session agent org building a SaaS accounting product. Happy to provide more request IDs as they occur — this is the first filing of what the owner has asked to be a per-occurrence practice.
4 Comments
Follow-up — the trigger is portable across sessions and intent, which pins the defect precisely.
Immediately after filing this, the owner pasted the same probe text that tripped the building session into a second, unrelated session — one whose only job was discussing/filing this very complaint. It tripped there too, on the identical
[cyber]classification.So the same string flagged:
Two different tasks, opposite purposes, same refusal. That rules out intent/context as inputs to the decision — the classifier is matching on the literal language of the probe (sentinel-value planting + output scanning, standard for a data-leak regression test) regardless of what the session is actually doing with it. A context-aware guard would have cleared both; a purely lexical one flags both. This is the mechanism behind the false positive, demonstrated cleanly.
Ask #1 (weigh first-party/in-repo context) would fix this: neither session had any exploitation context to weigh, and one of them was literally a meta-discussion about the classifier itself.
Correction to my previous comment — the trigger is even further from an attack than I first said, and I want the record accurate.
I initially attributed the second trip to "the same probe text." That was my assumption and it was wrong. The owner identified the exact flagged input by its task id: it was an inbound agent-to-agent coordination message delivered through a monitor (a background task that surfaces new messages as the turn input), not the session authoring any test code.
The message that tripped it was a software-architecture design brief — an instruction listing which capabilities a multi-tenant app should reserve as internal-only rather than expose to end users: token minting, role/permission (RBAC) editing, impersonation, and PII handling. Standard access-control design prose. No code, no test, no target — a paragraph a senior engineer would write in a design doc about locking things down.
So the corrected picture:
This is the cleanest possible illustration of Ask #1 in the original report: a guard that flags a design brief about restricting privileged capabilities is optimizing against exactly the work it should want to encourage. Same underlying defect as the first report; I just had the triggering artifact wrong, and corrected it rather than leave it standing.
Precision note on the prior comment — one thing I should not over-state.
What is confirmed: the flagged input was delivered by a background monitor that surfaces new inbound messages as the turn input — i.e. the session was paused for a message it received, not code it wrote. That structural fact holds.
What I described as the message's content (an access-control design brief) is my best inference of which message it was, and it could be off by a turn or two — I don't have a way to pin the exact triggering text from my side. The only authoritative resolution is the Request ID lookup on your end (
req_011CeYGt6mx5iwckz3zXoKVefor the original trip).Flagging this so nobody triages against a specific artifact I can't actually verify. The reproducible, verifiable part of the report is unchanged: a first-party session doing legitimate work was blocked by a
[cyber]classification with no exploitation context present, and the recovery UI's primary action silently downgrades the model.Occurrence #2 (same night, same org/session context) — Request ID
req_011CeYJ9LcRttP3C5ng4z1hC.Logging per our per-occurrence practice. A second
[cyber]safeguard interruption fired within minutes of the first, in the same Claude Code multi-session agent workflow on the user's own SaaS codebase.I'm deliberately not characterizing the triggering prompt for this one — the owner relayed the Request ID, but I did not capture the exact input on my side, and after getting occurrence #1's artifact wrong I won't guess a second time. The Request ID is the authoritative pin; the decode lives on your end.
Pattern so far tonight: two false positives in minutes during ordinary first-party work (security-hardening architecture + verification). Request IDs for correlation:
req_011CeYGt6mx5iwckz3zXoKVe(#1),req_011CeYJ9LcRttP3C5ng4z1hC(#2).