---
title: "Stats and consensus sandbox static gates can be bypassed to reach blocked primitives (incomplete fix of #336 / GHSA-6rxr-gq43-694g)"
description: "GHSA-j3x4-v3p2-4mq3: Stats and consensus sandbox static gates can be bypassed to reach blocked primitives (incomplete fix of #336 / GHSA-6rxr-gq43-694g). Affected and fixed versions of qwed."
url: https://qwedai.com/security/advisories/ghsa-j3x4-v3p2-4mq3
---

GHSA-j3x4-v3p2-4mq3

# Stats and consensus sandbox static gates can be bypassed to reach blocked primitives (incomplete fix of #336 / GHSA-6rxr-gq43-694g)

high Published 16 October 2026

### Impact

The code that runs inside the Docker sandbox on the stats and consensus paths is screened by four static gates (a substring scan, an AST call-name matcher, a raw-pattern scan, and the executor's AST matchers). A family of constructs defeats these gates while evaluating, at runtime, to a primitive the gates are meant to block (process execution, or `eval`/`exec` via the interpreter namespace). All are certified "safe" by every static gate.

Verified constructs (described at the gate level; harmless `id`/`true` placeholders, nothing executed):

-   A reference to a blocked callable stored through an assignment, instead of a direct call.
-   A reference to a reflection builtin that yields the builtins namespace.
-   Banned names assembled at runtime from split or repeated string literals, so no banned substring appears in the source.
-   Names carried as string constants into a runtime `getattr`, so no attribute node or blocked call-name appears.
-   The `os`/`subprocess` module re-acquired through `sys.modules[...]` after renaming `sys`, defeating the `sys` allowlist.
-   A call-name denylist gap (`posix_spawn`, `posix_spawnp`, `Popen`).
-   On the consensus expression path, `chr()`\-synthesised names and `vars()`/`dict.get()` chains.

### Affected

All releases through 7.2.3; reproduced at the gate level on `main` @ a4d6714. **Exploitation requires the Docker executor to be enabled** (stock deployments fail closed — without a Docker socket the path returns BLOCKED `runtime_unavailable`). In-container execution and any host-side impact were not reproduced here (no Docker); the control-integrity bypass is unconditional on this path.

### Details

-   `src/qwed_new/core/secure_code_executor.py`: the OS-call denylist and the AST matchers that key on call nodes / name-rooted chains only (around 50-193).
-   `src/qwed_new/core/stats_verifier.py`: the bundled validation and the alias/substring checks (around 333-382, 821-883).
-   `src/qwed_new/core/code_verifier.py`: the substring and AST process-execution checks (the latter resolves import aliases only). This is the same structural class as closed #336 (every added matcher still keys on identifier syntax) and the import-alias-only limit of GHSA-6rxr; it also covers the stats-path analogue of the split-string-literal bypass fixed for `/verify/math` in #329.

### Fix

Stop extending name-set denylists. Isolate the wrapper namespace so the executed code has no access to `eval`/`exec`/`vars`/`getattr`/`__import__`/`sys.modules`/reflection builtins (a capability allowlist for builtins and modules), and reject non-call first-class references to blocked names. Add the missing `posix_spawn`/`posix_spawnp`/`Popen` names as a stopgap only.

### Source

OpenVuln external audit (2026-10), stats and consensus sandbox-gate findings. Reported privately.

Affected and fixed

Package

qwed

Affected

<= 7.2.3

Fixed in

7.3.0

Severity

high

Weakness

CWE-94 Improper Control of Generation of Code ('Code Injection')

CWE-184 Incomplete List of Disallowed Inputs

[View on GitHub](https://github.com/QWED-AI/qwed-verification/security/advisories/GHSA-j3x4-v3p2-4mq3)

[All advisories](https://qwedai.com/security/advisories)
