Skip to content

fix(security): clear 20 advisories (yara-x 1.7, sevenz-rust2, lru 0.18.2) and repin fleet-ci - #17

Merged
h4x0r merged 5 commits into
mainfrom
chore/repin-fleet-ci
Aug 15, 2026
Merged

fix(security): clear 20 advisories (yara-x 1.7, sevenz-rust2, lru 0.18.2) and repin fleet-ci#17
h4x0r merged 5 commits into
mainfrom
chore/repin-fleet-ci

Conversation

@h4x0r

@h4x0r h4x0r commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Repins the shared workflow to 9234e1fa9f85b14a8d6fddc7a8f7378f7e30b183, which
makes this repo publish a stable, requirable check context.

Two defects in fleet-ci blocked required status checks fleet-wide:

  1. The coverage job's name: was an expression. GitHub does not evaluate a
    job's name: when the job is skipped — it publishes the raw expression
    text as the check name, newlines and all. Repos that skip coverage were
    therefore publishing a check named after the ternary that computed it, which
    no branch-protection rule can name. The job is now statically Coverage.

  2. There was no single invariant context to require. The remaining checks
    are matrix jobs (MSRV (<crate>, <ver>), Test (<os>)), whose published
    names vary per repo and per matrix entry. A new aggregate job, All checks, needs: every other job with if: always() and fails unless each
    one succeeded or was deliberately skipped — so ci / All checks is one
    context every consumer publishes identically.

The gate refuses an empty result set and refuses an all-skipped run: an empty
check list means not run, never passed.

No behaviour change to this repo's own CI configuration — only the pinned
revision moves. Nothing is required yet; branch protection is left untouched
until every consumer carries this pin, because requiring a context before it
exists everywhere would block merges.

Verified end-to-end on sqlite-forensic before this sweep: the pre-change
commit published the expression-named check run, the post-change commit
publishes ci / Coverage (skipped) plus ci / All checks (success), with the
gate's own log listing twelve results matching its twelve needs:.

h4x0r added 2 commits August 13, 2026 05:51
…sion

Picks up SecurityRonin/fleet-ci#9. Repin only -- no gate behaviour changes.

Two fixes, both of which only matter when a check context is REQUIRED:

  - A skipped job publishes its `name:` EXPRESSION, not the evaluated value.
    The coverage job's name was a multi-line ternary, so any repo turning the
    coverage gate off published a check named with the raw expression source,
    newlines included. That name is now the constant `Coverage`.

  - Matrix jobs cannot serve as required contexts, because GitHub appends the
    matrix values -- `MSRV (<crate>, <floor>)`, `Test (<os>)` -- so the context
    name moves whenever a crate is added or a floor is raised, and a required
    context that stops reporting makes every PR unmergeable with no
    explanation. The workflow now publishes an aggregate `All checks` job that
    needs all twelve others and whose name never varies.

`ci / All checks` becomes requirable once every repo carries this pin.
`LruCache::pop()` was not panic-safe: if a stored key's `Drop` panicked
during `pop()`, `self.detach()` never ran, leaving dangling pointers in the
internal doubly-linked list. A later insertion that triggers eviction then
writes through them.

  CWE-416 use-after-free, CWE-415 double free, both reachable from safe Rust
  when unwinding panics are enabled and `catch_unwind` is used with a key type
  whose `Drop` can panic.

  https://rustsec.org/advisories/RUSTSEC-2026-0253
  patched = [">= 0.18.2"]

The declared requirement was `lru = "0.16"`, which a caret bump cannot cross,
so the manifest moves to "0.18" as well as the lock -- layer 1 of the caret
staleness modes, not merely a stale lock. `cargo check --workspace
--all-features` is clean across all members: 0.16 -> 0.18 touches no API this
workspace uses.

Found by cargo-deny going red on the fleet-ci repin branch while `main` sat
green: the advisory postdates main's last CI run, and cargo-deny re-reads the
advisory database every run. Main is not green because it is clean; it is
green because nothing has re-asked the question since 2026-05-12.
…ories

cargo-deny on this tree went from 23 advisory errors to 3, and the three that
remain fail identically on `main` -- they are pre-existing, not introduced here.

Cleared:

  - 18 wasmtime vulnerabilities, including four sandbox escapes and several
    host panics, reached through yara-x 0.12 -> wasmtime 26.0.1
  - RUSTSEC-2026-0253, the `LruCache::pop()` use-after-free (carried from the
    previous commit, still verified here)
  - RUSTSEC-2026-0246, `sevenz-rust` unmaintained, plus the path-traversal
    arbitrary-file-write it carries
  - `paste` unmaintained, dropped incidentally with the yara-x graph

yara-x is pinned with a TILDE, and the pin is the load-bearing part. yara-x
1.8+ moves to wasmtime 43.x, and NO 43.x release is patched for
GHSA-hgjw-h833-99q9 or its five siblings -- the fixed ranges are 24.0.12,
36.0.13, 46.0.2+ and 47.0.3+. Only the 1.7 line resolves wasmtime ^36.0.2, and
so reaches the patched 36.0.13. Upgrading to the newest yara-x therefore looks
like the safer move and silently reinstates all six; a plain `cargo update`
during this work did exactly that, which is why the constraint lives in the
manifest rather than only in the lock. Remove the pin once yara-x depends on a
patched wasmtime range.

sevenz-rust has no safe upgrade, so the 7z path moves to the maintained fork
sevenz-rust2: `SevenZReader`/`SevenZWriter`/`SevenZArchiveEntry` become
`ArchiveReader`/`ArchiveWriter`/`ArchiveEntry`, and `Error::io` is `pub(crate)`
there so the io error is built from the public `Error::Io` variant. No
behaviour change in the extraction path.

`MIT-0` joins the licence allow-list for ppmd-rust, which arrives via
sevenz-rust2 and via zip inside yara-x. It is "CC0-1.0 OR MIT-0"; MIT-0 is
OSI-approved and satisfies the OR alone, so CC0-1.0 stays off the list.

Verified: `cargo check --workspace --all-features --all-targets` clean, and
`cargo deny check` reports licenses/bans/sources ok.
@h4x0r h4x0r changed the title ci: repin fleet-ci to the stable check-context revision fix(security): clear 20 advisories (yara-x 1.7, sevenz-rust2, lru 0.18.2) and repin fleet-ci Aug 14, 2026
@socket-security

socket-security Bot commented Aug 14, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: cargo lzma-rust2 is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?cargo/zip@5.1.1cargo/lzma-rust2@0.13.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore cargo/lzma-rust2@0.13.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

h4x0r added 2 commits August 14, 2026 08:44
…two advisories

Takes `cargo deny check` on this repo to `advisories ok, bans ok, licenses ok,
sources ok`. The three advisories left after the yara-x work all predate it —
they fail identically on `main` — and they are resolved in the order the policy
demands, real fix first and suppression only where no fix exists.

  - number_prefix (RUSTSEC-2025-0119, unmaintained) is reached only through
    indicatif 0.17. indicatif 0.18 drops the dependency outright, so this is a
    genuine remediation: the crate leaves the graph. Requirement moves 0.17 ->
    0.18; the workspace compiles unchanged on all targets.

The remaining two carry `patched = []` upstream — there is no release to move
to, no maintained replacement, and both are pulled by yara-x, which is itself
pinned to ~1.7 because every later line depends on an unpatched wasmtime. Each
is ignored individually with a reason and a removal condition:

  - RUSTSEC-2023-0071, rsa Marvin Attack. The advisory is a timing sidechannel
    in private-key DECRYPTION. That it is unreachable here was checked, not
    assumed: yara-x touches rsa in exactly one file, and only through
    `DecodePublicKey`, `RsaPublicKey` and `Pkcs1v15Sign::verify` for PE
    authenticode signatures. `RsaPrivateKey`, `.decrypt(` and Oaep appear
    nowhere in the crate. The comment carries a RE-CHECK instruction, because
    that reachability claim expires the moment yara-x is upgraded.

  - RUSTSEC-2025-0141, bincode unmaintained. A maintenance-status advisory
    rather than a defect; yara-x pins it for rule serialisation.

Both live in this repo's own deny.toml, not an inherited shared list. That is
the point of the local config: a suppression has to be argued for in the repo
that carries the risk.

Verified the ignores are load-bearing rather than decorative by deleting them
and confirming `cargo deny check advisories` goes red — with the deletion
asserted to have applied first, since a mutation that silently no-ops reports
green while testing nothing.
…tion

The yara-x/sevenz-rust2/indicatif work moved 36 crate names into the graph and
31 out, which left `cargo vet` with 138 missing audits. `main` vets clean, so
this gap is introduced here rather than inherited — it is the migration's cost,
and it is paid with the strongest mechanism that applies rather than the
cheapest.

Order of resolution, per the supply-chain policy:

  - 65 crates are now TRUSTED BY PUBLISHER, not exempted: dtolnay, kennykerr,
    BurntSushi, epage, sunfishcode, cuviper, philipc, seanmonstar, fitzgen,
    Amanieu and alexcrichton, each already trusted by the imported mozilla and
    bytecode-alliance audit sets. `--allow-multiple-publishers` was deliberately
    NOT passed: where a crate has several publishers, trusting it on one name is
    a weaker claim than the flag makes it look.
  - the remainder are exemptions, which honestly assert "nobody audited this".

Net effect is a BETTER posture than before the migration, not merely a restored
one: exemptions fall 302 -> 242 and fully-audited crates rise 111 -> 189.

25 crates are newly exempted, i.e. genuinely new unaudited surface. Most are
successors or renames of crates leaving in the same change — sevenz-rust2 for
sevenz-rust, lzma-rust2 for lzma-rust, wasmtime-internal-asm-macros for
wasmtime-asm-macros — and the rest are bincode 2.x internals and compression
codecs reached through the 7z path:

  android_system_properties, base64, bincode_derive, cpubits, either, ipnet,
  jobserver, lzma-rust2, nom, pkg-config, ppmd-rust, psl, psl-types,
  sevenz-rust2, strum_macros, unit-prefix, unty, virtue,
  wasmtime-internal-asm-macros, zeroize_derive, zip, zlib-rs, zstd, zstd-safe,
  zstd-sys

Listed rather than summarised on purpose: a count is not reviewable, and this
is the one part of the change that adds trust surface instead of removing it.

`cargo vet --locked` reports Vetting Succeeded.
@h4x0r
h4x0r merged commit 55e385c into main Aug 15, 2026
26 checks passed
h4x0r added a commit that referenced this pull request Aug 16, 2026
…security fixes (#18)

PR #17 fixed this repo's tree but published nothing, and the reason is
structural rather than a mistake in the commit subject: the squash touched 8
files, none of them under `crates/`, and release-plz runs with
`dependencies_update = false`. So no library package changed by its own
reckoning, and it correctly declined — logging `no commit matches the
release_commits regex` for every member.

The consequence is that downstream is still exposed. The PUBLISHED crates
declare the old requirements:

    memf-windows 0.4.4   yara-x ^0.12   -> wasmtime 26.0.1, 18 advisories
    memf-strings 0.2.2   yara-x ^0.12   -> same
    memf-core    0.2.5   lru    ^0.16   -> below the patched 0.18.2
    memf-format  0.3.1   lru    ^0.16   -> same

`4n6mount` and `issen` consume those published crates, so nothing reaches them
until these four are republished. This bump is what makes release-plz's
`release` job publish them: it ships any library whose version is ahead of
crates.io, regardless of commit type.

Bump levels are chosen from whether the dependency is reachable through each
crate's PUBLIC API, checked by reading every occurrence rather than by a
pattern match:

  - memf-windows 0.4.4 -> 0.5.0 (MINOR — breaking under 0.x).
    `pub fn scan_yara(reader, ps_head_vaddr, rules: &yara_x::Rules, ...)` takes
    a yara-x type across the API boundary. A caller holding a `Rules` built by
    yara-x 0.12 cannot pass it to a signature expecting 1.7, so this is a
    breaking change and a patch bump would have shipped it silently.
  - memf-core 0.2.5 -> 0.2.6, memf-format 0.3.1 -> 0.3.2,
    memf-strings 0.2.2 -> 0.2.3 (PATCH). In each, the dependency is held behind
    a private field — `tlb_cache`, `cache`, `rules` — and no public signature
    mentions it. The compiled dependency set changes; the API does not.

The workspace's path-dep declarations move with them: they pin exact versions
(`memf-windows = { version = "0.4.4", path = ... }`), and `^0.4.4` cannot match
0.5.0, so leaving them would break the build rather than merely lag.

`chore(release):` is deliberate. `release_commits` excludes chore, so this does
not trigger a second version bump on top of this one, while the `release` job
still publishes on the version-ahead-of-crates.io rule.

Verified: `cargo update -w` moves all four in the lock, and
`cargo check --workspace --all-features --all-targets` is clean.

KNOWN GAP, deliberately not fixed here: published `memf-carve 0.1.5` requires
`memf-windows ^0.4` and so cannot resolve 0.5.0. Nothing downstream of this
repo currently consumes memf-carve, so it is left for its own release rather
than widened blind in a security bump.

Co-authored-by: h4x0r <h4x0r@github.com>
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.

1 participant