Skip to content

fix(osv): avoid panic in rustsec_refs_imported on malformed refs - #1686

Closed
li-jin-quan wants to merge 1 commit into
rustsec:mainfrom
li-jin-quan:fix-rustsec-panic
Closed

fix(osv): avoid panic in rustsec_refs_imported on malformed refs#1686
li-jin-quan wants to merge 1 commit into
rustsec:mainfrom
li-jin-quan:fix-rustsec-panic

Conversation

@li-jin-quan

Copy link
Copy Markdown

Fixes #1681

Summary

OsvAdvisory::rustsec_refs_imported() previously hard-coded a byte slice ([31..48]) on each reference URL, and used .expect() after stripping the https://rustsec.org/advisories/ prefix. Any advisory with a malformed reference URL (wrong path, empty id, URL outside the expected host) caused a panic, crashing cargo-audit / cargo-deny runs.

This is reachable in real-world data because the OSV ecosystem has historical advisories from before the URL scheme was canonicalised, and imports from upstream sources (Rust advisory DB, OSV.dev) regularly surface entries with non-conforming URLs.

Repro (panic)

use rustsec::osv::{OsvAdvisory, OsvAdvisoryIterator, osv_references};
use url::Url;
use rustsec::advisory::Id;

let raw = r#"{
  "id": "RUSTSEC-2099-9999",
  "summary": "x",
  "details": "x",
  "references": [
    {"type": "ADVISORY", "url": "https://rustsec.org/advisories/"},         // empty id
    {"type": "ADVISORY", "url": "https://example.com/not-rustsec/RUSTSEC-2099-9999"}, // wrong host
    {"type": "ADVISORY", "url": "https://rustsec.org/advisories/RUSTSEC-2099-9999"}
  ],
  "affected": []
}"#;
let adv = OsvAdvisoryIterator::new(raw.as_bytes()).unwrap().next().unwrap().unwrap();
let _ = adv.rustsec_refs_imported(); // panics

Changes

  • Replace byte-slice + .expect() with strip_prefix("https://rustsec.org/advisories/") + filter_map + Id::from_str(...).ok().
  • Malformed URLs (wrong host, empty id, non-ASCII-id garbage, query strings, fragments) are now silently skipped — matching the spirit of upstream advisory parsers.
  • Added unit tests covering: valid ref only, short URL, malformed id, and mixed valid/invalid.

Notes

  • Patch is minimal: only rustsec/src/osv/advisory.rs, +79/-5.
  • No behavioural change for valid input (sorted+deduped Vec<Id> preserved).
  • Same hardening pattern (filter_map instead of expect) is used elsewhere in the crate; aligning this function reduces attack surface for downstream scanners.

Replace the hardcoded byte-range slice [31..48] and .expect() in
OsvAdvisory::rustsec_refs_imported with a strip_prefix-based parse that
skips malformed references instead of panicking.

Previously, a reference URL matching the https://rustsec.org/advisories/
prefix but shorter than 48 bytes caused an out-of-bounds slice panic,
and a URL that was long enough but did not contain a valid advisory ID
caused a panic via .expect(). Both inputs now result in the reference
being ignored.

Fixes: rustsec#1681
@djc

djc commented Aug 31, 2026

Copy link
Copy Markdown
Member

@djc djc closed this Aug 31, 2026
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.

rustsec_refs_imported() could possibly panic on short or malformed rustsec.org URLs

2 participants