You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
read_score_pdf currently resolves the app-owned score path and then calls std::fs::read(path). The original attach path validates a non-empty regular .pdf, enforces MAX_SCORE_PDF_BYTES = 25 * 1024 * 1024, and checks the %PDF- magic, but the later read path does not repeat a bounded content check before native allocation.
This matters independently of the JavaScript response hardening in #750: a score file that is corrupted or replaced inside app-owned storage after attachment can be read into an unbounded native Vec<u8> before the JS bridge has a chance to reject an oversized response. The read path also does not re-check the %PDF- magic before returning bytes.
apps/desktop/core/src/lib.rs defines MAX_SCORE_PDF_BYTES and PDF_MAGIC; validate_score_pdf_source rejects empty/short/wrong-magic/oversized sources during attach.
apps/desktop/src-tauri/src/main.rs::read_score_pdf validates ids and path containment through resolve_existing_score_pdf, then returns std::fs::read(path) without a bounded read or content revalidation.
Keep ownership in BandScope's native score-storage boundary. Prefer a GUI-independent helper in bandscope-desktop-core and call it from the Tauri command.
Acceptance criteria:
Read through an explicit MAX_SCORE_PDF_BYTES + 1 ceiling so file growth after metadata inspection cannot cause an unbounded native allocation.
Reject empty/short content and bytes that do not begin with PDF_MAGIC before returning them across IPC.
Preserve current project/score id allowlists and canonical app-owned path containment.
Keep errors path/payload-safe and do not expose absolute local paths.
Add realistic Rust tests for valid PDF bytes, empty/short/wrong-magic content, oversized sparse files, and the bounded-read contract.
Maintain 100% owned production statement/branch coverage, rustdoc/docstrings, SAST/security/SBOM/supply-chain gates, and cross-platform builds.
Record the residual local-filesystem TOCTOU boundary honestly; do not claim descriptor/handle-level no-follow guarantees unless actually implemented and tested.
Update CHANGELOG/security doctoring as appropriate.
Relationship
#750 is the canonical JavaScript bridge-response validation slice and should not be expanded by silently weakening or duplicating this native authority. This issue owns the native pre-allocation/read-time validation gap.
Problem
read_score_pdfcurrently resolves the app-owned score path and then callsstd::fs::read(path). The original attach path validates a non-empty regular.pdf, enforcesMAX_SCORE_PDF_BYTES = 25 * 1024 * 1024, and checks the%PDF-magic, but the later read path does not repeat a bounded content check before native allocation.This matters independently of the JavaScript response hardening in #750: a score file that is corrupted or replaced inside app-owned storage after attachment can be read into an unbounded native
Vec<u8>before the JS bridge has a chance to reject an oversized response. The read path also does not re-check the%PDF-magic before returning bytes.Exact evidence
Protected
develop@acdbea6344fe1231c39535b575f4de35e4c607c9:apps/desktop/core/src/lib.rsdefinesMAX_SCORE_PDF_BYTESandPDF_MAGIC;validate_score_pdf_sourcerejects empty/short/wrong-magic/oversized sources during attach.apps/desktop/src-tauri/src/main.rs::read_score_pdfvalidates ids and path containment throughresolve_existing_score_pdf, then returnsstd::fs::read(path)without a bounded read or content revalidation.Required repair
Keep ownership in BandScope's native score-storage boundary. Prefer a GUI-independent helper in
bandscope-desktop-coreand call it from the Tauri command.Acceptance criteria:
MAX_SCORE_PDF_BYTES + 1ceiling so file growth after metadata inspection cannot cause an unbounded native allocation.PDF_MAGICbefore returning them across IPC.Relationship
#750 is the canonical JavaScript bridge-response validation slice and should not be expanded by silently weakening or duplicating this native authority. This issue owns the native pre-allocation/read-time validation gap.