Rust port of NewPipeExtractor (YT-only). Plugs into Straw via UniFFI.
Two adversarial bugs surfaced by the round-2 audit on this crate. extract_video_id recursion (linkhandler/stream.rs) /attribution_link?u=<inner> recursed on the inner URL with no depth guard. The comment claimed 'only one level deep' but the call was plain recursion — a pasted URL whose u= param decodes to another /attribution_link would recurse until the JVM stack blew. Wrap the recursion in extract_video_id_inner with an explicit depth counter capped at MAX_ATTRIBUTION_DEPTH = 1. ReqwestDownloader body cap (downloader/default_impl.rs) resp.text() read the entire response body into a String with no upper bound. Player.js is ~1.5 MB, watch HTML ~3 MB, channel responses well under 1 MB. A hostile redirect target (or compromised host) could blast multi-GB and OOM-kill the Android process — there is no headroom on a 1 GB JVM heap ceiling. Cap at 32 MB. Two-stage check: bail fast on a known Content-Length that exceeds the cap, and use Read::take(MAX+1) on the stream so we detect overrun rather than silently truncate. Switched the final decode to from_utf8_lossy so a single mojibake byte doesn't drop the whole response (same fix shape as the wrapper's read_capped_body). |
||
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
strawcore
Rust port of NewPipeExtractor (v0.26.2), YouTube-only. Plugs into Straw via UniFFI.
Why this exists
rustypipe regex-parses YouTube's player.js and reimplements the signature deobfuscator in Rust. Every YT player rotation breaks it. NPE embeds Mozilla Rhino and executes the JS function live — resilient by design, and that's the architecture we're mirroring.
The rustypipe-backed Straw build (vc=15..17) also routed playback through iOS-progressive URLs, which hit a server-side ~917 KiB end-byte cap. NPE uses the Android client + po_token → DASH manifest path, which doesn't see the cap. Same fix, different layer.
See memory/npe-audit-2026-05-24/SPEC.md in the workspace repo for the full plan.
Status
| Phase | Subsystem | Status |
|---|---|---|
| 1 | Foundation (downloader + service spine) | in progress |
| 2 | JS engine (rquickjs + ress) | pending |
| 3 | InnerTube + itag table | pending |
| 4 | Stream extractor + DASH | pending |
| 5 | PoTokenProvider trait + Android JNI bridge | pending |
| 6 | Search + Channel + Playlist + Kiosks | pending |
| 7 | UniFFI surface swap | pending |
| 8 | Delete rustypipe everywhere | pending |
Build + test
cargo build
cargo test --lib # offline unit tests
cargo test --features online-tests # full smoke incl. live httpbin.org
License
GPL-3.0-or-later. NPE is GPL-3.0; this port inherits.