Formula sandbox: unbounded ** / << allows DoS from an untrusted profile #6

Closed
opened 2026-07-01 19:22:46 -04:00 by claude · 0 comments

From the Fable security review. obdcore/formula.py runs UNTRUSTED community-profile scaling formulas through an AST evaluator, but _BIN whitelists ast.Pow and ast.LShift/RShift with no magnitude bound. A profile formula like 9**9**9 or 1<<10**9 passes _validate at load and detonates on first decode() — computing a multi-hundred-MB integer that pins a CPU core and OOM-kills the process. It runs on the background scheduler thread; the except Exception in scheduler does NOT catch a runaway/OOM (not a raised exception). A derived PID with empty deps and formula 9**9**9 fires every tick on connect.

Fix: bound eval-time result magnitude (raise FormulaError if an int result .bit_length() > ~512); replace <</>>/** with checked wrappers (cap shift/exponent); cap expression length + AST depth at compile to avoid RecursionError. Add tests with malicious formulas.

From the Fable security review. `obdcore/formula.py` runs UNTRUSTED community-profile scaling formulas through an AST evaluator, but `_BIN` whitelists `ast.Pow` and `ast.LShift`/`RShift` with no magnitude bound. A profile formula like `9**9**9` or `1<<10**9` passes `_validate` at load and detonates on first `decode()` — computing a multi-hundred-MB integer that pins a CPU core and OOM-kills the process. It runs on the **background scheduler thread**; the `except Exception` in scheduler does NOT catch a runaway/OOM (not a raised exception). A derived PID with empty `deps` and formula `9**9**9` fires every tick on connect. **Fix:** bound eval-time result magnitude (raise `FormulaError` if an int result `.bit_length() > ~512`); replace `<<`/`>>`/`**` with checked wrappers (cap shift/exponent); cap expression length + AST depth at compile to avoid RecursionError. Add tests with malicious formulas.
claude added the bugP1security labels 2026-07-01 19:22:46 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: justin/obdash#6