Summary
The governance gateway's decision vocabulary makes a false verification claim: when the code-engine's denylist scan finds nothing, the decision is status: "ALLOW_VERIFIED" with message "Python execution request passed deterministic verification." No deterministic verification occurred — a static token scan returned zero matches. This is the semantic half of #24 (which tracks the bypass vectors; executed evidence posted there); filing separately because relabeling and vector-closing are different fixes that must land together to mean anything.
Found in the 2026-08-23 adversarial audit of v0.2.1 @ 518192b.
Location
src/qwed_mcp/security/risk_gateway.py:142-149 — "status": "ALLOW_VERIFIED", "message": "Python execution request passed deterministic verification." on verify_code_safety(...)["verified"] == True, which means only "zero denylist issues found" (engines/code_engine.py:107-111)
src/qwed_mcp/security/risk_gateway.py:135-138 — even the refusal path uses the word: "Python execution was verified, but server policy keeps code execution disabled"
Evidence (CONFIRMED BY EXECUTION)
All ten bypass classes in the #24 comment (pathlib file read, io.open, builtins.eval, from os import remove, socket, urllib, ctypes, shutil, getattr chains) return ALLOW_VERIFIED. An end-to-end run executed an actual file read through the full pipeline. The label is not just cosmetic — any downstream consumer, auditor, or dashboard keying on ALLOW_VERIFIED / "verified" is being told a deterministic QWED verification occurred for code that merely avoided six denylist entries.
Why this matters beyond wording
QWED's ecosystem-wide contract distinguishes deterministic proof from heuristic signal (qwed-a2a's heuristic_pass status is the precedent; the a2a audit explicitly validated that honest labeling is what keeps heuristic results from being admitted as verified). This gateway inverts that: heuristic-clean → claimed-verified → admitted-executed. Same token ("VERIFIED"), two meanings across the ecosystem — the exact vocabulary fracture the Verification Context spec exists to prevent.
Remediation
- Rename the status honestly:
SCAN_CLEAN or HEURISTIC_PASS — never "VERIFIED" for a denylist miss.
- Fix both messages ("passed deterministic verification", "was verified, but server policy...").
- Update the tool description to match the honest status.
- Result-poisoning note (same surface, fold in): executed code's stdout is returned verbatim into the LLM conversation as "Result:" text — content produced by executed (untrusted) code should be documented as untrusted, since it can carry instructions aimed at the hosting model.
Architecture change required: NO — strings and status constants.
Summary
The governance gateway's decision vocabulary makes a false verification claim: when the code-engine's denylist scan finds nothing, the decision is
status: "ALLOW_VERIFIED"with message "Python execution request passed deterministic verification." No deterministic verification occurred — a static token scan returned zero matches. This is the semantic half of #24 (which tracks the bypass vectors; executed evidence posted there); filing separately because relabeling and vector-closing are different fixes that must land together to mean anything.Found in the 2026-08-23 adversarial audit of v0.2.1 @
518192b.Location
src/qwed_mcp/security/risk_gateway.py:142-149—"status": "ALLOW_VERIFIED", "message": "Python execution request passed deterministic verification."onverify_code_safety(...)["verified"] == True, which means only "zero denylist issues found" (engines/code_engine.py:107-111)src/qwed_mcp/security/risk_gateway.py:135-138— even the refusal path uses the word: "Python execution was verified, but server policy keeps code execution disabled"Evidence (CONFIRMED BY EXECUTION)
All ten bypass classes in the #24 comment (pathlib file read,
io.open,builtins.eval,from os import remove, socket, urllib, ctypes, shutil, getattr chains) returnALLOW_VERIFIED. An end-to-end run executed an actual file read through the full pipeline. The label is not just cosmetic — any downstream consumer, auditor, or dashboard keying onALLOW_VERIFIED/ "verified" is being told a deterministic QWED verification occurred for code that merely avoided six denylist entries.Why this matters beyond wording
QWED's ecosystem-wide contract distinguishes deterministic proof from heuristic signal (qwed-a2a's
heuristic_passstatus is the precedent; the a2a audit explicitly validated that honest labeling is what keeps heuristic results from being admitted as verified). This gateway inverts that: heuristic-clean → claimed-verified → admitted-executed. Same token ("VERIFIED"), two meanings across the ecosystem — the exact vocabulary fracture the Verification Context spec exists to prevent.Remediation
SCAN_CLEANorHEURISTIC_PASS— never "VERIFIED" for a denylist miss.Architecture change required: NO — strings and status constants.