Skip to the content.

ucbepic/docetl — security scan

Repository: ucbepic/docetl Commit scanned: ae7f10f1ba35 Scan date: 2026-07-21 Disclosure status: disclosed — filed ucbepic/docetl#505

Summary

Severity Count
Critical 1
High 55
Medium 68
Low 0
Info 0

Total findings: 124 (1 real, and the scanner didn’t rank it)

Top findings

1. Unauthenticated arbitrary file read/write in the /fs filesystem router — scanner-silent

2. SSRF in /fs/upload-file (URL ingest)

3. Dependency drift across two lockfiles, no Dependabot

Patterns observed

DocETL is a declarative + agentic map-reduce engine — its whole reason to exist is running LLM-authored data-processing pipelines, so the exec(code) in code_operations.py:158 and the asteval/eval fallback in validation.py:132 read as alarms but are the documented programming model: a pipeline author writes a transform function or a filter expression and the engine runs it. That’s the same “the dangerous call is the product” shape as ag2 and datachain — by-design for a trusted local user, and not a finding on its own.

What makes docetl different is that the trust assumption is quietly broken by how it ships. The /fs router assumes it’s talking to a friendly localhost browser, so it never confines a path or checks a caller. On bare metal that assumption mostly holds — .env.example binds BACKEND_HOST=localhost and the CORS default is a tight localhost:3000 allowlist (both worth crediting). But the recommended DocWrangler deployment is the shipped docker-compose.yml, and there BACKEND_HOST=0.0.0.0 with no authentication anywhere in the server. At that point read-file, the pipeline-execution route (pipeline.py drives DSLRunner straight from a request-supplied yaml_config, and a pipeline can carry code operators), and the SSRF ingest are all reachable from the network — and the docetl-aws compose profile bind-mounts ~/.aws:ro into the container, so an unauthenticated file read is a cloud-credential read. The file-read is the floor here; the code-operator model is the ceiling.

This is the optillm / zotero-mcp egress-and-exposure lesson pointed inward: the finding that matters isn’t in the AI machinery the scanner obsesses over, it’s in the mundane file/URL plumbing bolted onto the side of it. Reachability discipline cuts both ways — it demoted the nltk “critical” to a footnote and promoted a zero-tool-hits file-read to the headline.

Notes on the tool

Disclosure timeline

Reproduce

git clone https://github.com/ucbepic/docetl /tmp/scan-target
python scanner/run_scan.py --repo /tmp/scan-target --reports-dir ./reports/ucbepic-docetl --min-severity medium