Skip to content

fix(score): bound native PDF reads before allocation - #865

Draft
seonghobae wants to merge 10 commits into
developfrom
fix/bounded-score-pdf-read-864
Draft

fix(score): bound native PDF reads before allocation#865
seonghobae wants to merge 10 commits into
developfrom
fix/bounded-score-pdf-read-864

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Security gap

Closes #864 after protected merge. Protected develop resolves the app-owned score path and then uses unbounded std::fs::read, so a stored PDF that grows after attachment can allocate beyond the 25 MiB product ceiling before the JavaScript bridge can reject it.

Protected base: develop@acdbea6344fe1231c39535b575f4de35e4c607c9.
Exact current head: f86e266b2ab2dc5a95e6b4a484e777b29f0feeaf.

Regression-first repair

RED head f83a1baebc793658c4d1805be00f11238f09ceac committed GUI-independent integration tests before production changes. They require the missing read_validated_score_pdf boundary to return valid bytes unchanged, reject invalid/truncated/oversized inputs with payload-safe errors, and enforce the 25 MiB ceiling. Historical RED workflow state is not used as current success.

The production repair now:

  • opens the already-authorized canonical stored-score path once;
  • reads descriptor metadata and rejects a non-file or a size above MAX_SCORE_PDF_BYTES before heap allocation;
  • allocates exactly the bounded metadata snapshot, reads exactly that amount, then probes one extra byte on the same descriptor so growth after the metadata snapshot fails closed without growing the heap buffer;
  • revalidates %PDF- magic on the bytes actually returned to IPC;
  • keeps local path/content out of errors; and
  • routes Tauri read_score_pdf through the bounded core helper instead of std::fs::read.

A deterministic unit regression supplies a stream whose bytes exceed the metadata-length snapshot, proving the one-byte growth probe rejects the race; a truncation-after-snapshot regression proves a short read fails closed. The integration suite also covers valid content, empty/short/wrong-magic content, a sparse MAX_SCORE_PDF_BYTES + 1 file, missing paths, and a non-file descriptor on Unix.

Scope and ownership

This PR owns only the native read-time allocation/content boundary. resolve_existing_score_pdf remains the path-authority owner; #858 owns broader filesystem path-authority hardening. #750 remains the separate JavaScript bridge-response validation slice. #783 remains the canonical JavaScript dependency-security baseline. No JavaScript dependency/root-lock, network, database, model, review credential, or new IPC command authority is added.

The desktop-core crate keeps its existing package/dependency/lint contract; only its library entry path changes to a thin root module so the new bounded reader can be isolated without rewriting the historical core implementation. The historical public crate-root API is re-exported unchanged. CHANGELOG.md records the buyer-visible resource-boundary fix. No temporary/self-modifying workflow is used.

Exact-current-head verification

Repository-owned exact-head workflow state for f86e266b2ab2dc5a95e6b4a484e777b29f0feeaf:

  • terminal-success: ci, release, build-baseline, sbom, SAST Semgrep, bandit, and secret-scan-gate;
  • terminal-failure: security-audit and aggregate Security Scan.

The failures were inspected at exact job/log level before classification:

  • security-audit run 31945502301, job 95160728823, fails at the npm audit stage on the protected-base JavaScript set: nanoid, pdfjs-dist, and undici; Python/Rust audit stages are skipped only because npm exits first and skipped evidence is not success.
  • aggregate Security Scan run 31945502360 has successful Dependency Review, OSV base-vs-head comparison, and Scorecard; its only failed job is trivy-fs job 95160730223, which reports the protected-base pdfjs-dist CVE-2026-16633 finding and directs remediation to the shared base.

This branch changes no JavaScript dependency/root lock or vulnerability-suppression policy. Those failures remain inherited #783 evidence and are not copied or suppressed here.

Current inline review-thread inspection returns zero threads, but there is also no qualifying independent non-author formal approval for this exact head.

Merge gate

Keep Draft until the unchanged exact head has all applicable repository and central gates terminal-success, including realistic Rust tests, cross-platform build, 100% owned statement+branch coverage where exposed, rustdoc/docstrings, SAST/security/SBOM/supply-chain/release evidence; #783 has reached protected develop and the security gates are regenerated cleanly; #861/central branch-coverage evidence is inherited and revalidated; current actionable threads remain zero; a qualifying independent non-author last-push approval exists; and branch protection permits merge without bypass.

Protected central .github/main is now b71a02a310e77f70c1e59f4719f6857cb33ca886 and includes merged .github#1124, so the former relative-include materialization prerequisite is no longer pending. The remaining read-only central trusted-uv version-output failure is owned by open .github#1117 at 428d6eb13e1355d4304b207b3721c376fe768c66; no BandScope-local coverage workaround is valid for that pre-test control-plane failure.

Queued, skipped, failed, predecessor-head, inherited protected-base, self/author, or administrative-bypass evidence is not success.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f7b7eda-4bf8-441e-9521-20bffd26fb9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

security(score): bound and revalidate native PDF reads before allocation

1 participant