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.
./build/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.)
./build/scan-for-malware # full scan (YARA + ClamAV)
./build/scan-for-malware --fast # bin/lib64 only (dev tier)
./build/scan-for-malware --no-clamav # YARA only
./build/scan-for-malware --no-cache # force a fresh scan and do not write cache
./build/scan-for-malware --clear-cache # delete cached clean scan results first
./build/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 -- ./build/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 commit-pinned, via
envs/tmux/vendor/plugins.lock (4 plugins). ./build/update tmux-plugins reads that
lock, clones each plugin and checks out the pinned commit, then rewrites the file
with the commits it actually landed on. The plugin list is scraped from the
set -g @plugin lines in envs/tmux/tmux.conf; commented-out entries are
skipped, so a disabled plugin is neither cloned nor pinned.
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.
./build/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.
./build/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. ./build/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 2272.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.