This project deploys into chip-design environments where TSMC infosec mandates
no project backups -- ransomware or a wiper inside a bundled tool would be
unrecoverable. Assurance is therefore treated as a first-class deliverable, with
a per-package framework combining supply-chain provenance (pin + hash + scan
everything that ships) and behavioral analysis (canary/strace detonation in a
network-isolated container). The source of truth is the machine-checkable
ledger under assurance/.
Every claim below is reproducible by running the named command.
.content-manifest records the SHA-256 of every shipped payload file, as
stored on disk (per .part-NNN chunk). It is generated by
build/gen-content-manifest and regenerated automatically by
strip-all-elf-binaries after any payload change.
loadout installverifies each payload archive against the manifest before extracting it (default-on;--no-verifyescapes). A byte mismatch, or a payload file not listed in the manifest, aborts the install.loadout doctor --verifyre-hashes every manifest entry.tests/content-verifyand thecontent-manifest in synccheck (build/gen-content-manifest --check) run intests/run-allTier 1.
Trust chain: the manifest lives in git; the release tag is SSH-signed (see §6), so tampering with a shipped payload requires the signing key, not just a file drop.
Two engines; the scan fails if either detects:
- YARA-Forge full ruleset (vendored
yara+payload/yara/), one--scan-listinvocation over all files. - ClamAV (
clamscan) when present; degrades to YARA-only with a warning if absent. Refresh signatures withfreshclamon the build box.
./release runs it as a mandatory Step 0 in parallel with the other
pre-release gates. The final tag/release step waits and aborts on detection.
Coverage is the whole shipped tree -- ~69,000 files: bin/lib64, runtime
archives, wheels, typelibs, treesitter parsers, fonts, the tldr cache, the
Windows payload, the crate store, portable-python, and the Neovim + tmux plugin
bundles. (Historically only bin/lib64/runtime were effectively scanned; the
crate store scanned a dead path and portable-python was skipped entirely --
both fixed.)
./scan-for-malware # full scan (YARA + ClamAV)
./scan-for-malware --fast # bin/lib64 only (dev tier)
./scan-for-malware --no-clamav # YARA only
./scan-for-malware --no-cache # force a fresh scan and do not write cache
./scan-for-malware --clear-cache # delete cached clean scan results first
./scan-for-malware --path DIR # scan an arbitrary staging tree (pre-pack)Clean-result cache. Clean scan results are cached under
${XDG_CACHE_HOME:-~/.cache}/engineering-loadout/malware-scan-v1/. Only clean
verdicts are cached; detections are never cached. The cache key hashes the
source scan corpus (compressed payloads plus vendored plugin trees, or the
explicit --path tree), scan-for-malware itself, vendored YARA binary/rules,
the YARA release tag, scan mode flags, and the ClamAV engine/signature
fingerprint from clamscan --version. Any payload byte change, rule update,
allowlist/script edit, or ClamAV signature update misses the cache and performs
a full scan. --verbose bypasses the cache so raw YARA output is available.
False-positive allowlist. _YARA_ALLOWLIST in scan-for-malware excuses a
short, audited set of (rule, path) pairs, each with a written justification;
any other rule on the same file, or that rule on any other file, still fails.
Currently one entry: Firefox's omni.ja (its own resource zip trips a
structural APPX/MSIX heuristic). The offensive-security tldr pages
(mimikatz/certutil/msfvenom) that used to trip keyword rules are not
allowlisted -- ./update tldr-data prunes them from the bundled cache
entirely (_TLDR_OFFENSIVE_GLOBS).
The Neovim plugin bundle is the largest third-party attack surface. It is now
commit-pinned in envs/nvim/lazy-lock.json (24 plugins), and env-nvim ships
that lockfile so :Lazy restore reproduces the exact vetted commits.
- Install-time online plugin sync is default-off.
--allow-online-plugin-syncopts in and runsLazy! restoreagainst the committed lockfile (pinned commits), never a baresyncto upstream HEAD. build/build-nvim-pluginsrebuilds the bundle from the lockfile in a clean staging directory (never the maintainer's live~/.local/share/nvim/lazy), scans it withscan-for-malware --path, and packs deterministically.
The tmux plugin bundle is likewise pinned via envs/tmux/vendor/plugins.lock
(./update tmux-plugins clones + checks out the pinned commit and records it).
A tool is "detonated" in a mock chip-design HOME (canary .v/.lib/.sdc
files + docs + a binary blob), wrapped in strace, inside the clean AlmaLinux
8.10 container under docker run --network none. The tool FAILS if it behaves
like ransomware/a wiper: any canary modified, an entropy spike (encryption), a
write/unlink/rename to project data outside the profile's allowlist, a real
AF_INET/AF_INET6 network attempt (local AF_UNIX IPC is ignored), or a
mass-unlink. Profiles live in assurance/profiles/<pkg>.toml.
tests/prebuilt-binaries-almalinux8 --dynamic # container, network isolated
tests/run-all --container # includes --full and --dynamicnvim (the pilot) passes with zero out-of-allowlist mutations and no network.
For tools with an official upstream binary release, downloads it, reproduces the bundling transform (strip -> patchelf RPATH), and SHA-256 compares against the bundled binary.
build/verify-binaries # all
build/verify-binaries rg uv # spot-checkOutcomes: PASS (byte match), PASS (patchelf layout delta) (identical NEEDED libs + near-identical size), SKIP (EL8 source build / no upstream binary), FAIL (differing deps or size -- investigate). Most tools (bash, rg, bat, jq, eza, fd, tmux, vim, gnuplot, nvim, etc.) are intentionally source-built on EL8, so they SKIP here and are covered by the scan + content manifest + per-package assurance record instead.
./updatehashes every download (_download_file) and appendsdate url sha256toassurance/downloads.log(TOFU provenance);expected_sha256can pin a download and abort on mismatch.- The nodejs bundle is fetched via
nvm, which verifies against nodejs.orgSHASUMS256.txt.
./release runs the malware scan, binary smoke, version table, and checksum
generation as independent parallel gates, then signs the tag with git tag -s
and attaches sha256sums.txt plus the .content-manifest asset. The trust
chain (manifest in git -> signed tag) is tamper-evident. Verify with
git tag -v <tag>; GitHub shows the tag as Verified. The notes carry an
on-page SHA-256 table of the integrity-critical files (§1) for at-a-glance
checking without a download.
EL8 signer requirement. git SSH signing shells out to ssh-keygen -Y sign,
added in OpenSSH 8.2. Stock EL8 ships 8.0p1, whose ssh-keygen has no
-Y subcommand -- git tag -s there dies with unknown option -- Y. The
bundled openssh package (OpenSSH 10.4p1, ./loadout install openssh)
provides a signer that works; it is also how the maintainer's own build box
signs. It intentionally does not install bare ssh, scp, or sftp, because
mainline OpenSSH cannot parse some Red Hat crypto-policy directives that stock
RHEL OpenSSH accepts. Normal ssh stays host-integrated; use ssh10 only when
an explicit 10.x client is needed. Configure signing once:
git config gpg.format ssh
git config user.signingkey ~/.ssh/<key>.pub
git config gpg.ssh.program ~/.local/bin/ssh-keygen # the bundled 10.4p1, not stock 8.0p1For one-off GitHub transport with the bundled client, use
GIT_SSH_COMMAND=ssh10 git fetch or git config core.sshCommand ssh10.
A passphrase-protected key must be unlocked in an ssh-agent first
(ssh-add ~/.ssh/<key>) -- otherwise ssh-keygen -Y sign falls back to a GUI
askpass and fails on a headless box. ./release inherits SSH_AUTH_SOCK from
its environment.
Alternative signer sources (documented for reproducibility): build from the
official openssh/openssh-portable tag with build/build-openssh.sh
(provenance preferred), or a third-party EL8 OpenSSH RPM
(github.com/Nugent1a/OpenSSH-rpms/releases -- unvetted; using an unvetted RPM
to build the signer itself is a provenance hole, so the source build is
primary).
assurance/records/<pkg>.toml records, per package: source/build provenance,
artifact SHA-256s, scan result, dynamic-analysis result, and package-specific
pins:
- nvim -- per-plugin commit pins (
envs/nvim/lazy-lock.json). - rust-crate-store -- the full
name version cksumclosure inassurance/crate-store.lock.build/verify-crate-storere-hashes every one of the 2101.cratefiles against the crates.io SHA-256 embedded in the store's own registry index (run in Tier 2 as--check-lock), so a tampered crate fails against both the store index and the signed-tag'd lock. - treesitter-parsers -- per-grammar
url + revision + shipped-.so sha256for 318 grammars inassurance/treesitter-parser-locks.json(build/gen-parser-locks, checked in Tier 1). Grammars are already commit-pinned by the vendoredparsers.lua; this records the pin -> shipped bytes mapping.
tests/assurance-check re-hashes each record's artifacts against disk and
validates these pins, so a record cannot silently drift from reality. nvim,
rust, rust-crate-store, and treesitter-parsers are status = verified;
coverage rolls out package-by-package.