[BUG] Cyber-safeguard false positive silently switches the model mid-session, defeating a deliberate model selection

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 6, 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?

Summary

A cyber-safeguard false positive did not block my request — it silently
switched the session to a different model and let the work run to completion.
I discovered the substitution only after the fact. This differs from the
existing false-positive reports (#72256, #61646), which describe hard
refusals with no model change.

What happened

I ran /code-review at xhigh effort on a personal project: a PyQt6 desktop
app that extracts EXIF/XMP/IPTC/PNG-text metadata from image files. The
review prompt asked for a routine defensive-parser checklist — malformed
chunk lengths and offsets past EOF, decompression bombs on zlib paths, XML
entity expansion, EXIF IFD pointer loops, safe display of untrusted strings.

An in-app banner appeared:

Fable 5's safeguards flagged this message. The safeguards are intentionally broad right now and may flag safe and routine coding, cybersecurity, or biology work. These measures let us bring you Mythos-level capabilities sooner, and we're working to refine them. Switched to Opus 5.

No confirmation was requested. The session continued on Opus 5.

Why the fallback is worse than the false positive

  1. The model choice was methodological, not cosmetic. Opus 5 wrote

roughly half of the code under review. Selecting a different model as the
reviewer was the entire point — an author auditing its own work shares its
own blind spots. The silent switch invalidated that design.

  1. It happened on the turn that started the review, so all 18 subagents

(10 finder angles, 7 verifiers, 1 gap sweep) ran on the fallback model.
Not partial degradation — roughly 2M tokens of output that now needs a
provenance caveat.

  1. No prompt, no opt-out, no retry. I had Fable quota remaining (44% of

the weekly bucket used). Had I been asked, I would have rephrased and
resubmitted.

  1. The assistant could not tell it had been switched. Its system context

still identified it as Fable 5 while the UI showed Opus 5. When I asked
directly which model I was talking to, it confidently gave the wrong
answer and speculated about quota limits. Model provenance is not visible
to the model itself.

Expected behavior

Notify before falling back and offer a choice: rephrase, proceed on the
fallback, or cancel. At minimum, expose the active model to the assistant so
it can report its own provenance accurately, and surface the substitution in
the session UI persistently rather than as a single inline banner that is
easy to scroll past.

When model selection is methodological, a silent substitution is not graceful
degradation — it invalidates the work product.

Environment

  • Claude Code desktop app (Windows 11 Pro 10.0.26200)
  • Claude 1.25927.0 (003700) 2026-08-04T05:34:55.000Z
  • Plan: Max (5x)
  • Selected model: Fable 5, xhigh effort
  • Fell back to: Opus 5

Related

  • #72256 — false positive on security code review via subagents (refusal, no switch)
  • #61646 — false-positive cyber-safeguard on systems-engineering work (refusal, no switch)

What Should Happen?

Fable 5 extra high should complete code-review without switching to Opus, model the code is reviewing.

Error Messages/Logs

Steps to Reproduce

Prompt in Claude Code Desktop on Windows 11:

/code-review the whole app in this directory.

Context: Python desktop app (PyQt) that loads image files and extracts every
piece of embedded/hidden text information it can find — technical metadata,
EXIF incl. GPS, XMP, IPTC, PNG text chunks (AI-generation prompts and
workflows), and anything else present. 50/50 local-35B + Opus 5
authorship split . No human
review pass yet; treat all of it as unreviewed AI code.

The critical difference from a typical desktop app: this one parses
UNTRUSTED input. Any image from any source must be safe to open. Review
with that lens first.

Untrusted-input robustness:

  • malformed/adversarial files: chunk or IFD lengths and offsets pointing

past EOF, integer overflow on offsets, EXIF IFD pointer loops (incl.
maker notes), truncated and zero-byte files — nothing may crash, hang,
or allocate unbounded memory

  • decompression bombs on any zlib path (zTXt/iTXt, extended XMP): cap

decompressed output size

  • XMP is XML: entity-expansion attacks if parsed with stdlib xml — require

defusedxml or explicitly disabled entities

  • if exiftool or any external binary is invoked: no shell=True, filename

passed as argv (never string-interpolated), missing-binary handled

  • byte→text decoding: EXIF byte order (II/MM), UserComment encoding

prefix, tEXt Latin-1 vs iTXt UTF-8, any .decode() without errors=
handling

Extraction correctness and completeness (the app's whole point):

  • GPS math: DMS rationals + N/S/E/W refs (southern/western hemisphere

signs), zero-denominator rationals, altitude ref

  • every metadata home actually checked: EXIF sub-IFDs and thumbnail IFD,

multiple APP1 segments, XMP incl. extended XMP, IPTC, ICC, PNG
tEXt/zTXt/iTXt, trailing bytes after JPEG EOI / PNG IEND

  • embedded thumbnails surfaced explicitly — they can contain the

uncropped/unedited original

  • formats claimed vs silently skipped (WebP, TIFF, HEIC?) — a format that

opens but yields nothing without warning is a wrong-data bug

  • parallel extraction paths: a hand-rolled parser living next to a library

doing the same job — flag it and pick one source of truth per metadata
family

Safe display, and the tool must not leak what it extracts:

  • extracted strings into Qt widgets as PLAIN TEXT only (QLabel

auto-detects rich text), huge blobs must not freeze the UI, control and
RTL-override characters neutralized before display

  • no extracted metadata in log files, temp files, or crash output; flag

any network call made with extracted data (e.g. reverse geocoding of
GPS) as a finding

Plus the standard mixed-AI-authorship hunt:

  • hallucinated or wrong API usage, imports that don't exist, deprecated

calls

  • duplicated or near-duplicated logic where the two authors solved the

same problem differently

  • inconsistent conventions between sections: error handling, naming,

state management, logging

  • GUI-thread violations: parsing/decoding on the main loop, widget

updates from worker threads

  • resource leaks: unclosed file handles, missing cleanup on exit
  • silently swallowed exceptions and dead/unreachable code
  • Windows path/encoding issues, incl. non-ASCII image filenames and long

paths

If a test suite exists, run it; if not, do not assume one — instead end
the plan with a "fixtures to build" list for the fix phase: the crafted
files that would pin each parser fix (truncated JPEG, IFD-loop EXIF, zTXt
bomb, southern-hemisphere GPS, AI-prompt PNG, file with trailing data,
etc.).

Output: findings grouped blocker / should-fix / nice-to-have with
file:line references and a concrete fix for each, then a short refactor
plan to unify everything into one consistent style.

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude 1.25927.0 (003700) 2026-08-04T05:34:55.000Z

Platform

Other

Operating System

Windows

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗