Draft: Bound content-scan memory and regex CPU exposure #13
Loading…
Reference in a new issue
No description provided.
Delete branch "audit/content-resource-bounds"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
regexengine with an explicit failing findingVerification
python -m pytest(41 passed, 98.62% coverage)ruff check .andruff format --check .mypy srcmkdocs build --strictpython -m build --no-isolationandtwine check dist/*content_scan_too_large, max RSS 17,916 KiBcontent_regex_timeout, max RSS 17,740 KiBResiduals
regexengine on Linux/Python 3.13; it bounds each search, not aggregate work across arbitrary files and patterns.ensurepip; the equivalent no-isolation build completed successfully after installing the declared backend.Requires independent security review before merge.
Verdict: CHANGES REQUESTED at exact signed head
05ea9606bff786cfa0be98d25054516f42edd6b3.Important finding
src/policyglass/policy.py:107-111accepts any positive integer for both resource controls, whilesrc/policyglass/scanner.py:167passescontent_scan_max_bytes + 1toread()and line 179 converts the timeout to seconds. An accepted YAML policy with a 101-digitcontent_scan_max_bytescrashesscan_path()withOverflowError: cannot fit 'int' into an index-sized integer; still larger timeout values likewise overflow during conversion. This is neither a controlled validation error nor a fail-closed finding, and an arbitrarily large accepted byte budget also defeats the claimed enforceable memory ceiling. Add documented safe upper bounds (or equivalent safe handling) and reject values outside them during policy validation. Add regression tests for both fields. Remediation is tracked int_f41b078e.Test gap (included in unblock criteria)
src/policyglass/scanner.py:168-169is currently uncovered. Add a deterministic test for growth/change after the stat check and exact-budget boundary behavior so the key TOCTOU resource claim is protected.Verification performed
git diff --checkpassed.regex>=2024.11.6,<2027.(a+)+$probe producedcontent_regex_timeoutin 10/10 runs with a 1 ms policy timeout; the 8 GiB sparse-file path producedcontent_scan_too_largewithout reading the file body.OverflowErrorfrom a YAML 101-digit byte budget.Residual risks after remediation: timeout is per search, not an aggregate scan budget; total work scales with files × patterns. The implementation intentionally retains whole-file decoded matching and ignored invalid UTF-8 bytes.
Exact unblock criteria: constrain or safely handle both resource values so every accepted policy remains bounded and cannot raise conversion/read-size overflow; cover oversized values, exact byte boundary, and post-stat growth; rerun full quality/docs/package/resource verification at a new signed PR head. Do not merge before re-review.
Forgejo would not record a formal REQUEST_CHANGES review because this automation identity is also the PR author (
reject your own pull is not allowed), so this COMMENT review carries the changes-requested verdict.Verdict: CHANGES REQUESTED at exact signed head
b8c325a212afc3d5f799e31b1d1f2a7c1e069f8a.Important finding
Policyis a public dataclass and project tests construct it directly, but the new positive/type/maximum checks run only inload_policy()(src/policyglass/policy.py:56-67,115-123).scan_path()trusts direct instances (src/policyglass/scanner.py:67-73,166-179). Directly constructingPolicy(version=1, content_scan_max_bytes=10**100, forbidden_content_patterns=(ContentPattern("x", "x"),))is accepted, then scanning raises uncontrolledOverflowError: cannot fit 'int' into an index-sized integeratstream.read(max_bytes + 1). This violates the remediation contract that every accepted policy remain operationally bounded and fail closed. Enforce one canonical validation boundary for both YAML-loaded and directly constructed policies (or scanner entry) and add direct-construction regressions for both resource controls. Remediation is tracked int_cb09f182.Verification performed
content_regex_timeoutin 10/10 runs; 8 GiB sparse file producedcontent_scan_too_largewith 37,248 KiB max RSS.Residual risks: timeout is per search rather than aggregate; whole-file decode/search has bounded representation amplification; runtime probes cover Linux/Python 3.13 only.
Exact unblock criteria: enforce consistent bounds for directly constructed and YAML-loaded policies; add direct-construction regressions for byte and regex controls; preserve controlled sparse/timeout outcomes; rerun the full quality/docs/package/resource/secret suite at a new signed pushed head; obtain green CI and fresh independent exact-head review. Do not merge before re-review.
b8c325a212223ebe0b29