Why minimal dependencies matter for security tools
“Zero dependencies” sounds like a developer boast — a packaging convenience, a claim about download size. For a security tool, minimizing dependencies is actually a security property, and it deserves to be treated as one.
The supply chain is part of the threat model
A credential tool is the piece of software on your machine that handles the most sensitive material. Its integrity story has two halves: what the binary contains, and what it can reach at runtime.
What it contains. Every dependency is code you didn’t write and haven’t fully read, pulled through a supply chain you don’t control. A tool that handles secrets with a hundred transitive dependencies is a tool whose integrity you can’t personally verify — you’re trusting the entire tree. A tool built on the Go standard library plus one vetted module has a reviewable surface: the binary is nearly the source, compiled.
What it reaches at runtime. Runtime dependencies — a Python interpreter, a Node runtime, a plugin system — are an attack surface. If the tool can’t run without a host runtime, then anything that compromises that runtime compromises the tool. A static binary brings its own world with it; there’s nothing underneath to attack.
What a single static binary gives you
- Reviewable artifacts. One file,
go build, no lockfile archaeology. You can read the source, build it yourself, and diff your binary against the release. - Portable deployment. The same binary runs on any matching architecture — copy it to a server, a container, a fresh machine.
- No runtime drift. The tool behaves identically everywhere, because there’s no runtime version to drift.
- Small attack surface. No plugins, no extensions, no dynamic loading — nothing to hijack at runtime.
The one exception: TOML
“Minimal” doesn’t mean “hand-roll everything.” The Go standard library has
no TOML parser, and the config format needs one. A hand-written parser is
unvetted code — a bigger supply-chain risk than a vetted module. So trustless
keeps exactly one external dependency: github.com/pelletier/go-toml/v2,
pure Go (no cgo, links statically like the rest of the binary), fuzz-tested,
pinned via go.sum, and watched by Dependabot and govulncheck. One module is
a reviewable surface. A hundred is not.
The integrity stack on top
Minimal dependencies is table stakes; the verification layer is what makes it meaningful:
- Signing. Every release artifact signed (cosign, keyless) so you can verify the binary you downloaded is the binary the maintainer built.
- SBOM. A software bill of materials — for a single-module binary it’s a short document, but it makes the “nothing in here but the standard library plus one pinned module” claim auditable.
- Tests. The threat model exercised, not assumed: race-enabled test suites, failure-path tests for the parts that matter (fail-closed behavior, session handling, redaction completeness).
- A single version string. Version injected at build time via ldflags, so the binary tells you exactly what it is — and what you’re auditing.
The bar for a credential tool
The argument for minimal dependencies gets stronger as the tool’s privilege grows. A static site generator with dependencies is fine. A tool that reads your password store, proxies your API traffic, and scrubs your session databases is not the place for an npm dependency tree.
trustless is built to that bar:
one Go binary, one external module in the whole project, cosign-signed
releases with SBOMs, version injected at build time, and 321 tests with
-race. The release verification process is documented in the
installation guide.
The next time you install a security tool, ask two questions: what’s in the binary, and what can it reach at runtime? If the answer involves a dependency tree, you’ve just inherited its threat model too.