Skip to content

fix(deps): clear 13 Dependabot advisories in engine/Cargo.lock - #220

Merged
xerj-org merged 1 commit into
mainfrom
fix/cargo-security-advisories
Aug 8, 2026
Merged

fix(deps): clear 13 Dependabot advisories in engine/Cargo.lock#220
xerj-org merged 1 commit into
mainfrom
fix/cargo-security-advisories

Conversation

@xerj-org

@xerj-org xerj-org commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Closes every open Dependabot alert against engine/Cargo.lock — the manifest whose contents are compiled into all 8 released binaries. Twelve are closed by version bumps that touch the lockfile only; the thirteenth is closed by removing the vulnerable crate from the graph entirely. Zero lines of XERJ logic change; the only source-adjacent edit is a Cargo feature flag.

The npm alerts (basic-ftp, ip-address, js-yaml, ws — all transitive from puppeteer, developer tooling that never reaches a released artifact) are PR #194's scope and are deliberately untouched.

What each change closes

crate change severity advisories
openssl / openssl-sys 0.10.77 → 0.10.81 / 0.9.113 → 0.9.117 5 high, 2 medium, 1 low GHSA-8c75-8mhr-p7r9, GHSA-ghm9-cr32-g9qj, GHSA-hppc-g8h3-xhp3, GHSA-pqf5-4pqq-29f5, GHSA-xp3w-r5p5-63rr, GHSA-phqj-4mhp-q6mq, GHSA-xv59-967r-8726, GHSA-xmgf-hq76-4vx2
rustls-webpki 0.103.12 → 0.103.13 high GHSA-82j2-j2ch-gfr8 (DoS panic parsing a malformed CRL BIT STRING)
quinn-proto 0.11.14 → 0.11.16 high GHSA-4w2j-m93h-cj5j (remote memory exhaustion)
rand 0.8.5 → 0.8.7 low GHSA-cq8v-f236-94qc
webauthn-rs 0.5.4 → 0.5.5 low GHSA-22w3-693w-x895 (origin-validation mismatch in webauthn-rs-core)
protobuf 2.28.0 → REMOVED medium GHSA-2gh3-rmm4-6rq5 (uncontrolled recursion when parsing)

Notes on the non-obvious ones:

  • openssl: the advisories require ≥ 0.10.80. Vendored openssl-src deliberately stays at 300.6.1+3.6.3, so the OpenSSL C library version does not move and the Windows Perl/NASM vendored-build path in release.yml is untouched — that is what keeps the 8-target cross-compile low-risk.
  • quinn-proto is a lockfile ghost: it enters only through reqwest's optional http3 feature, which we never enable, so it compiles to nothing. Bumped anyway so the alert closes rather than being argued with.
  • webauthn-rs: the fix lives in webauthn-rs-core, but 0.5.4 pins webauthn-rs-core = "=0.5.4" exactly, so the parent must be the carrier. Still inside the existing webauthn-rs = "0.5" requirement — no manifest edit needed.

protobuf: removed, not upgraded

protobuf 2.28.0 entered through exactly one edge: prometheus 0.13.4's protobuf feature, on by default. XERJ only ever encodes metrics, and only to the text exposition format — there is no protobuf ingest surface anywhere in the tree. engine/Cargo.toml now sets prometheus = { version = "0.13", default-features = false }; everything the two consumers (xerj-common, xerj-api) touch is unconditional (Registry, Opts, counter/gauge/histogram types, Encoder, TextEncoder, proto::MetricFamily — backed by prometheus's pure-Rust plain_model with the feature off). Only ProtobufEncoder/PROTOBUF_FORMAT are gated away, and nothing referenced them.

Removing the parser beats upgrading it: there is no protobuf parser left in the binary to be recursed into. It also avoids the prometheus 0.13 → 0.14 major bump (protobuf 3.x codegen, changed public type behind MetricsRegistry::gather()). cargo tree -p xerj-server -i protobuf now reports no such package.

Because this one is potentially behavioural — /metrics is a public scrape surface and the backing proto model changes underneath it — the commit adds two tests in crates/xerj-common/src/metrics.rs that pin the Prometheus text exposition format directly: the # HELP line, the # TYPE ... counter line, the unlabelled sample, and a labelled series (xerj_docs_indexed_by_index_total{index="my-index"} 2). The pre-existing test only asserted the metric name appeared somewhere in the output, which would not have caught a malformed scrape.

Reachability: hygiene, not emergency

For the record, and so the release notes can be honest: none of the 13 advisories was reachable in a default XERJ deployment.

  • quinn-proto is not even compiled (http3 off);
  • the specific openssl functions named in all 8 advisories are called by nothing in the tree — XERJ makes zero openssl:: calls; the dependency exists only to force vendored for cross-compilation;
  • rustls-webpki's defect is in CRL parsing and XERJ configures no CRLs;
  • protobuf was encode-only;
  • rand's unsoundness needs a logger that calls rand, and XERJ logs through tracing-subscriber;
  • webauthn's advisory needs allow_subdomains(true), which our webauthn setup never sets.

This is a dependency refresh, not an emergency. It is worth taking anyway: the openssl crate sits directly behind unauthenticated attacker-controlled input via the pre-auth passkey login path (/_xerj-console/api/v1/auth/login/*), so the blast radius of a future advisory landing in a function that path does call is large enough that staying current is cheap insurance.

Verification

cargo fmt --all --check                          clean
cargo build --release -j 32 -p xerj-server       ok
cargo build --release --locked -p xerj-server    ok (the mode release.yml uses)
cargo test --release -j 32 --workspace           84 suites: 1995 passed / 0 failed / 30 ignored (exit 0)
ES-YAML conformance (fresh data dir, :9400)      1365 passed · 0 failed · 3 skipped · 1368 total

Closes every open Dependabot alert against `engine/Cargo.lock` — the manifest
whose contents are compiled into all 8 released binaries. Twelve are closed by
version bumps that touch the lockfile only; the thirteenth is closed by
*removing* the vulnerable crate from the graph entirely.

Motivation: these ship to users. The npm alerts (PR #194) are developer tooling
and never reach a released artifact, but everything in `engine/Cargo.lock` does.

## What each change closes

openssl 0.10.77 -> 0.10.81, openssl-sys 0.9.113 -> 0.9.117 (8 advisories)
    GHSA-8c75-8mhr-p7r9, GHSA-ghm9-cr32-g9qj, GHSA-hppc-g8h3-xhp3,
    GHSA-pqf5-4pqq-29f5, GHSA-xp3w-r5p5-63rr  (high)
    GHSA-phqj-4mhp-q6mq, GHSA-xv59-967r-8726  (medium)
    GHSA-xmgf-hq76-4vx2                       (low)
    Advisories require >= 0.10.80. Critically, vendored `openssl-src` stays at
    300.6.1+3.6.3, so the OpenSSL C library version does NOT move and the
    Windows Perl/NASM vendored-build path in release.yml is untouched. That is
    what keeps the 8-target cross-compile low-risk.

rustls-webpki 0.103.12 -> 0.103.13 (high)
    GHSA-82j2-j2ch-gfr8 — DoS panic parsing a malformed CRL BIT STRING.

quinn-proto 0.11.14 -> 0.11.16 (high)
    GHSA-4w2j-m93h-cj5j — remote memory exhaustion via unbounded out-of-order
    ranges. Lockfile ghost: it enters only through reqwest's optional `http3`
    feature, which Cargo.toml:99 does not enable, so it compiles to nothing.
    Bumped anyway so the alert closes rather than being argued with.

rand 0.8.5 -> 0.8.7 (low)
    GHSA-cq8v-f236-94qc.

webauthn-rs 0.5.4 -> 0.5.5 (low)
    GHSA-22w3-693w-x895 — origin-validation mismatch in webauthn-rs-core.
    The parent is the required carrier: webauthn-rs 0.5.4 pins
    `webauthn-rs-core = "=0.5.4"` exactly, so updating the core alone hard-fails
    resolution. Still inside the `webauthn-rs = "0.5"` requirement at
    crates/xerj-console-api/Cargo.toml:64, so no manifest edit is needed.
    Pulls base64urlsafedata, webauthn-attestation-ca and webauthn-rs-proto to
    0.5.5 with it.

protobuf 2.28.0 — REMOVED, not upgraded (medium)
    GHSA-2gh3-rmm4-6rq5 — uncontrolled recursion when PARSING protobuf.
    This is the one place the change is more than a lockfile bump.

    protobuf entered through exactly one edge: prometheus 0.13.4's `protobuf`
    feature, which is optional but on by default. XERJ only ever ENCODES, and
    only to the text exposition format (`TextEncoder` at
    crates/xerj-common/src/metrics.rs:326) — there is no protobuf ingest surface
    anywhere in the tree.

    So engine/Cargo.toml:84 now sets `default-features = false`. Everything the
    two consumers (xerj-common, xerj-api) actually touch is unconditional:
    `Registry`, `Opts`, the counter/gauge/histogram types, `Encoder`,
    `TextEncoder`, and `proto::MetricFamily` — with the feature off, `proto` is
    backed by prometheus's pure-Rust `src/plain_model.rs` instead of generated
    protobuf code. Only `ProtobufEncoder` and `PROTOBUF_FORMAT` are gated away,
    and nothing here referenced them. Same feature-minimisation reasoning as the
    `tonic` line directly below it.

    Removing the parser beats upgrading it: there is no protobuf parser left in
    the binary to be recursed into. It also avoids the prometheus 0.13 -> 0.14
    major bump, which would have dragged in protobuf 3.x codegen and changed the
    public type behind `MetricsRegistry::gather()`.

    `cargo tree -p xerj-server -i protobuf` now reports no such package, and the
    crate is gone from Cargo.lock.

    Because this one IS potentially behavioural — `/metrics` is a public scrape
    surface and the backing `proto` model changes underneath it — it comes with
    two new tests in crates/xerj-common/src/metrics.rs that pin the Prometheus
    text exposition format directly: the `# HELP` line, the `# TYPE ... counter`
    line, the unlabelled sample, and a labelled series
    (`xerj_docs_indexed_by_index_total{index="my-index"} 2`). The pre-existing
    test only asserted that the metric name appeared somewhere in the output,
    which would not have caught a malformed scrape. Verified passing:
    7 passed / 0 failed in xerj-common metrics::.

## Reachability

For the record, and so the release notes can be honest: none of the 13 was
reachable in a default deployment. quinn-proto is not compiled; the specific
openssl functions named in all 8 advisories are called by nothing in the tree
(XERJ makes zero `openssl::` calls — the dependency exists only to force
`vendored` for cross-compilation); rustls-webpki's defect is in CRL parsing and
XERJ configures no CRLs; protobuf was encode-only; rand's unsoundness needs a
logger that calls rand, and XERJ logs through tracing-subscriber; webauthn's
advisory needs `allow_subdomains(true)`, which webauthn_setup.rs:15 never sets.

This is a dependency refresh, not an emergency. It is worth taking anyway: the
openssl crate sits directly behind unauthenticated attacker-controlled input via
the pre-auth passkey login path (`/_xerj-console/api/v1/auth/login/*`), so the
blast radius of a future advisory landing in a function that path DOES call is
large enough that staying current is cheap insurance.

## Not fixed here

Nothing in engine/Cargo.lock remains open. The 9 package-lock.json alerts
(basic-ftp, ip-address, js-yaml, ws — all transitive from puppeteer, developer
tooling only) are PR #194's scope and are deliberately untouched.

## Verification

Zero lines of XERJ logic change; the only source-adjacent edit is a Cargo
feature flag.

    cargo fmt --all --check          clean
    cargo build --release -j 32 -p xerj-server
    cargo build --release --locked -p xerj-server   (the mode release.yml uses)
    cargo test --release -j 32 -p xerj-engine -p xerj-fts -p xerj-api --no-run
    cargo test --release -j 32 --workspace
    es-yaml-runner conformance gate
@cla-bot cla-bot Bot added the cla-signed label Aug 8, 2026
@xerj-org
xerj-org merged commit 684c92a into main Aug 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant