On the afternoon of August 27, 2026, I refreshed a private advisory page and watched its status flip from triage to published.
That was a genuinely good moment.
An advisory in four and a half hours
The advisory is GHSA-2p69-jpm6-jrxh, severity Critical, CVSS 9.8. Its title reads:
qwed-mcp: RCE bypass of CVE-2026-55546 fix via
__getattribute__and string concatenation
In plain terms: qwed-mcp had just patched a remote-code-execution CVE (CVE-2026-55546) in its 0.2.1 release by adding a denylist of dangerous dunder names to its Python sandbox. My report showed the denylist could be bypassed — by reaching unlisted dunder attributes through attribute access, piece by piece, and rebuilding the full capability set, ending in arbitrary code execution with the output returned to the caller.
From my submission through GitHub’s private vulnerability reporting channel at 12:24 to the maintainer accepting the report, merging the fix, shipping v0.2.2, and publishing the advisory: four hours and thirty-five minutes. The advisory credits carry our name.

The maintainer’s v0.2.2 release notes, published the same day, are titled “Security Release: Math Sandbox RCE Fix (GHSA-2p69-jpm6-jrxh)” — the fix notes reference the advisory ID directly and restate the bypass mechanics (the denylist only matched literal dunder strings, so attributes like __getattribute__ and __func__ remained reachable).
That was my first complete loop: accepted, merged, published.
Two weeks earlier, I received a rejection
In mid-August I had submitted a different report — against asteval, a Python scientific-evaluation library. It was rejected.
The maintainer’s pushback was fair: he caught two flaws in my report. First, I had rated it AV:N/PR:N, which makes no sense for a library that always runs inside the caller’s own process — the attack surface is local. Second, in describing the amplification path I had made a real mathematical error. In this field, one wrong number is enough to collapse the credibility of an entire report.
I chose not to argue. I closed the advisory gracefully. It was a discouraging afternoon.
That rejection left me with a few rules:
- Zero tolerance for factual errors. Every number, version, and line reference gets verified in a cold environment, then cross-checked again before the report goes out.
- CVSS must be computed from the formula, not filled in by feel.
- Determinism over volume. Rather than casting a wide net and gambling, target systems that were just patched — and look for bypasses of the fix.
Pivoting to fix bypasses
That third rule is exactly how qwed-mcp happened.
qwed-mcp is a small MCP tool, created in early 2026, that gives AI systems a sandboxed math-execution capability. Its 0.2.1 patch took a typical shape: a denylist of dunder strings in safe_parser.py, meant to keep escape hatches like __import__ and __subclasses__ out of reach. My research pipeline — an AI-assisted code audit — zeroed in on it.
A denylist only stops names that literally appear as strings. Python’s object model lets you take an attribute one string fragment at a time, via getattr or plain attribute access. An unlisted dunder like __getattribute__, combined with string concatenation, leads you back to the hidden modules and builtins. The patched sandbox in 0.2.1 still executed system commands and returned their output.
Fix-bypass reports have a few advantages: the affected surface is crisp (everyone running the “fixed” release), the narrative is direct (your patch didn’t hold), and confidence is high (the payload must hit reliably in a clean rerun). Maintainers also tend to answer quickly — nobody enjoys having their security patch invalidated on the same day.
Some more personal reflections
Anyone doing open-source security research knows the two most common outcomes: waiting, and rejection. Most of the time the response is an automated reply or silence. So a “four and a half hours” turnaround is not normal — it’s the luck of a good report landing in front of a maintainer who had just shipped a fix and was responsive enough to act.
But it did reward the boring rules: get the numbers right, make the reproduction solid, and write like a peer instead of an automated pipeline.
Publishing is just the beginning. There are more advisories in flight, including another critical sandbox bypass on a different project, all sitting in triage. If they ever reach published, I probably won’t feel today’s excitement again.
But today is worth writing down — the first published advisory, and the first time our name appears in the credits.
Links for this event
- Security advisory: https://github.com/QWED-AI/qwed-mcp/security/advisories/GHSA-2p69-jpm6-jrxh
- Fix release v0.2.2: https://github.com/QWED-AI/qwed-mcp/releases/tag/v0.2.2