Skip to content

fix(airflow-dag-parser): close FP5 parser stack-overflow DoS (v1.0.1)#2

Merged
masumi-ryugo merged 1 commit into
mainfrom
fix/fp5-airflow-dag-parser-recursion-guard
Jun 16, 2026
Merged

fix(airflow-dag-parser): close FP5 parser stack-overflow DoS (v1.0.1)#2
masumi-ryugo merged 1 commit into
mainfrom
fix/fp5-airflow-dag-parser-recursion-guard

Conversation

@masumi-ryugo

Copy link
Copy Markdown
Contributor

Closes FP5 — the parser stack-overflow DoS in the crates.io-published ferro-airflow-dag-parser. Published as v1.0.1.

What

Parsing attacker-controlled Python could overflow the vendored littrs-ruff-python-parser 0.6.2 recursive descent and abort the host process with a SIGSEGV (catch_unwind cannot intercept a guard-page fault). Ports FerroAir's complete three-layer recursion guard and hardens it via an adversarial convergence loop.

Guard (panic_safe.rs)

  • Layer 1 — iterative bracket pre-scan (cap 256).
  • Layer 1b — single real-tokenizer pass bounding brackets + op_run + line_right_rec + indent (cap 1024); rejects PEP-750 t-strings. Counted run covers the non-bracket vectors: not/await/~/-/+ prefix, a**b**c, a if b else/lambda, mixed prefix, yield/yield from, and async error-recovery chains.
  • Layer 2 — parse and AST walk run on a dedicated 128 MiB stack; thread-join folds any unwinding panic into ParseError::Internal.
  • Recursive AST walkers (stringify_expr, collect_shift_edges, resolve_to_task_id, decorator helpers) truncate past depth 1024.

Convergence (Codex DD + Claude-critic)

10 Codex rounds + 10 empirical passes (~240 shapes) + full 110-variant TokenKind classification + fuzz ~2.66M runs / 0 crash. 5 fixes: stringify walker, yield/from, async, NonLogicalNewline/Comment trivia-reset (a latent bug shared with ferro-air's lex_reject), marker decorator-chain. R9+R10 NO FINDINGS.

Honest residual

A single left-leaning trailer chain in a multi-MB file can still overflow on recursive AST construction/drop (Rust Drop, shared with ferro-air, 128 MiB-bounded; not closable pre-parse without false-positives). Realistic FP5 shapes (<4 KiB) are fully closed. See dd-pack/11-known-limitations.md.

Quality

No public-API change; additive, semver-compatible. clippy -D warnings clean, 170 tests, fmt/deny/SPDX/MSRV 1.88/forbid(unsafe_code) green.

🤖 Generated with Claude Code

Port FerroAir's complete recursion guard into the crates.io-published
`ferro-airflow-dag-parser` and harden it via a Codex DD + Claude-critic
convergence loop. Parsing attacker-controlled Python could overflow the
vendored `littrs-ruff-python-parser` 0.6.2 recursive descent and abort the
process with a SIGSEGV (`catch_unwind` cannot intercept a guard-page fault).

Three-layer guard in panic_safe.rs:
- Layer 1: iterative bracket pre-scan (cap 256).
- Layer 1b: single real-tokenizer pass bounding
  `brackets + op_run + line_right_rec + indent` (cap 1024); rejects PEP-750
  t-strings. Counted run includes the non-bracket recursion vectors:
  not/await/~/-/+ prefix, a**b**c, a if b else / lambda, mixed prefix chains,
  yield/yield-from, and async error-recovery chains.
- Layer 2: parse AND AST walk run on a dedicated 128 MiB stack; thread-join
  folds any unwinding panic into ParseError::Internal.

Recursive AST walkers (collect_shift_edges, stringify_expr, resolve_to_task_id,
inner_name, marker decorator helpers) additionally truncate past depth 1024 so
a deep left-leaning >>/attr/call chain that survives the parser cannot overflow
the walk either.

Adversarial convergence (Codex DD 10 rounds + 10 Claude-critic empirical passes,
~240 shapes; full 110-variant TokenKind classification; fuzz 1.15M runs / 0
crash): fixed stringify-walker, yield/from, async, NonLogicalNewline/Comment
trivia-reset, and marker decorator-chain recursion; R9+R10 NO FINDINGS.

Honest residual (dd-pack/11-known-limitations.md): a single left-leaning
trailer chain in a multi-MB file can still overflow on recursive AST
construction/drop (Rust Drop, shared with ferro-air, 128 MiB-bounded); not
closable pre-parse without false-positives. Realistic FP5 shapes (<4 KiB) are
fully closed.

No public-API change; additive, semver-compatible. clippy -D warnings clean,
170 tests, fmt/deny/SPDX/MSRV 1.88/forbid(unsafe_code) green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@masumi-ryugo masumi-ryugo merged commit a275776 into main Jun 16, 2026
0 of 10 checks passed
@masumi-ryugo masumi-ryugo deleted the fix/fp5-airflow-dag-parser-recursion-guard branch June 16, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant