A CPython sandbox escape lets an attacker hide working code inside an AI model’s own chat template. RunSybil, a security research firm, found a memory-safety bug in CPython that an attacker can trigger through Jinja template rendering.
Template rendering is the step that turns a model’s raw prompt format into text an inference engine can run. RunSybil demonstrated the flaw against vLLM, an open-source inference engine, and says a fix has not reached every supported version of Python.
Security teams that have reviewed only the model file’s weights, and not its template files, have reviewed half the package. The same chat_template.jinja file ships inside the same repository download as the weights themselves.
Why Are Chat Templates a New Kind of Attack Surface?
Inference engines treat a chat template as configuration, not as code that needs review. Hugging Face and other model hosts let any model publisher ship its own chat_template.jinja file alongside the model weights, and most serving stacks render it automatically.
Jinja is a template language, built to format text, not to run arbitrary Python. RunSybil’s finding matters because it turns that formatting step into a path to the interpreter underneath it, through a bug in CPython rather than in Jinja’s own template logic.
How Does the CPython Sandbox Escape Work?
CPython caches a generic type alias’s parameters the first time it needs them, such as the parameters of dict[K, V]. The bug sits in _Py_subs_parameters, the function that substitutes a new value into those cached parameters.
If a parameter gains the ability to be substituted after CPython has already cached the parameter list, a lookup for that parameter returns -1 instead of its real position. In a release build, the code uses that -1 as an array index anyway and reads whatever sits there, which can be the cached hash of an unrelated tuple.
A debug build of CPython catches this with an assertion and stops. RunSybil’s write-up says a release build does not, so the bad read continues and hands the attacker a pointer to a real Python object instead of the number it expected.
RunSybil built a working example around this gap. The firm says it created a version of the small open model Qwen2.5-0.5B-Instruct with a backdoored chat_template.jinja file. It then used the bad pointer to recover real Python objects, such as strings, types and code objects.
With real Python objects in hand, the firm says it could build a working code object and run it. RunSybil frames the result plainly: code hidden inside a chat template can run inside the process that serves the model, with that process’s own privileges.
- Backdoored chat_template.jinjaModel Supply Chainuploaded to a model repository
- Template rendered at load timeServing Processthe inference engine renders it, per RunSybil
- Generic alias substitutionCPython Interpretera cached parameter lookup returns -1
- Arbitrary Python object recoveredCPython Interpreterthe bad read returns a real object, not a number
- Code executes in the processServing Process
Who Is Exposed: vLLM, Bedrock and Other Inference Engines
RunSybil says it demonstrated the issue against vLLM, and that AWS Bedrock applied an expedited mitigation after the firm’s disclosure. DigitalOcean’s bring-your-own-model service is also named as exposed in the write-up.
RunSybil says Jinja, the template project, pointed to CPython rather than treat the gap as its own issue. Hugging Face did not reply during the firm’s 90-day disclosure window, per RunSybil’s account, and vLLM has acknowledged the report but has not committed to a fix of its own.
RunSybil frames the risk as a supply-chain problem more than a single-engine bug. A chat template travels with the model file itself, so any downstream platform that pulls a model from a public hub inherits whatever that template does when it gets rendered.
The pattern is not specific to one engine. Any system that renders a Jinja chat template pulled from a model repository, and runs on an exposed CPython version, takes on the same risk, per RunSybil’s account.
Why Hasn’t CPython Fixed This for Every Version?
The fix itself is public. CPython merged pull request 155761 into its main branch on 14 August 2026. The project describes the change as a check that catches a missing parameter instead of reading past the end of a cached tuple.
We checked the CPython project’s own repository directly. The same fix reached the 3.15 branch the same day, and the 3.14 and 3.13 branches on 8 September 2026. The 3.12 branch has not received the same change.
Python’s own release page lists 3.12 as a security branch, which only takes fixes the project classifies as security issues. RunSybil’s write-up says CPython’s maintainers do not classify this as a vulnerability, because sandboxing untrusted code was never a supported use of the interpreter. That is why an ordinary bug fix does not reach a branch that only takes security fixes.
Python’s own schedule keeps 3.12 in that security-only phase until October 2028. Teams who stay on 3.12 for AI workloads should not expect this fix to arrive through a routine update.
What Should AI Teams Do Now?
RunSybil’s own advice is direct: treat a “security fix only” build of CPython as unsafe for any workload that runs sandboxed code, template engines or expression evaluators. It tells teams to assume an attacker can reach code execution through them.
We recommend three checks. First, find every place a chat template, system prompt file or similar text asset is pulled from a model repository and rendered before a request runs. Second, check whether that rendering step runs on CPython 3.12 or an earlier security-only branch. Third, treat any model file from outside your own pipeline, including its chat template, as untrusted input until it passes review.
On detection, we recommend scanning any chat template file pulled from an external model repository for logic beyond simple text substitution. Watch for code that reads or sets object attributes before the template reaches a production serving stack.
This is not the first sandbox boundary an AI platform has leaned on and lost. Our coverage of Beta9’s own tenant sandbox escape describes the same pattern in a different compute layer. Brandefense’s top threats to AI agents page and our sandbox glossary entry cover the wider concept this flaw sits inside.
