Threat model
What zc-workstation protects against, and what it does not.
What it protects
-
Nothing is applied that was not shown. A saved plan refuses to apply when the machine changed since. The dashboard plans again before applying. The dotfiles provider applies only the planned paths.
-
Deletions need a person. The CLI asks, the dashboard sends you to the terminal, and the MCP server cancels.
-
Nothing is uninstalled. The packages provider only installs.
-
Nothing is upgraded unless a target asks.
upgrade: trueis per target, and each upgrade is a plannedUPDATEyou review first. -
Capture never replaces a file. It writes standard output, or a new file; replacing one needs
-force. -
Untrusted mise configs stay untrusted. Trusting one is a
MANUALstep, never automatic. -
Writes stay inside a target.
localdirwrites throughos.Root: a symlink or..cannot lead a write out of the directory. -
The protocol stream stays clean. Under
mcp, installers get empty input and their output is captured, never written to the protocol stream. -
The dashboard stays local. Loopback only,
Hostchecked against DNS rebinding, cross-site writes refused, strict CSP. -
An agent’s plan goes stale. The MCP server refuses a saved plan older than an hour, and writes every tool call to
mcp-audit.jsonlin its state folder. Every apply, from the terminal, the dashboard or an agent, lands inzc-workstation history.
What doctor checks
zc-workstation doctor reads, and changes nothing. A weak setting is a
warning, not a failure: the choice is yours.
-
macOS: FileVault, the firewall and stealth mode, a password after sleep, Gatekeeper, System Integrity Protection, automatic updates, File Sharing, Remote Login, Screen Sharing, automatic login, AirDrop open to everyone, Touch ID for
sudo, and servers listening on every interface. -
Every system: SSH private keys without a passphrase, git commits left unsigned, and secrets in the shell history.
gitleaksscans~/.zsh_history,~/.bash_history, the fish history and Atuin’s, with--redact: the report names the rule and the count, never the secret. -
AI agents: API keys written in plain text in the MCP configs of Claude Code, Claude Desktop, Cursor, Gemini, Windsurf and Codex; MCP servers that
npx,bunxoruvxstart without a version; Claude Code rules that allow any shell command, andbypassPermissions.
What it does not
-
A config or manifest you did not write. A Brewfile can name any package, a chezmoi source can run scripts, and a mise config can install any tool. Review them as you would a script.
-
The package sources. Homebrew, apt, dnf, winget and mise verify what they download;
zc-workstationadds nothing to that. -
sudo. Installs that runsudoask for your password in the terminal, or, with no terminal, in a macOS dialog that only you can answer. The dialog is a script in the user cache folder; the password goes straight tosudoand is never stored or seen by an agent. -
An attacker who already has your shell.
Verifying a release
Each release is built by GitHub Actions from its tag. checksums.txt lists
every archive and package, carries a keyless cosign signature, and each file
has SLSA build provenance and an SPDX SBOM.
-
Check the signature on the checksums. It proves the release workflow of this repository signed them:
cosign verify-blob checksums.txt --bundle checksums.txt.sigstore.json \ --certificate-identity-regexp '^https://github.com/ZoolCoder/zc-workstation/.github/workflows/release.yml@refs/tags/v' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com -
Check the file you downloaded against the checksums:
shasum -a 256 --ignore-missing -c checksums.txt -
Check its provenance, which names the commit and workflow that built it:
gh attestation verify zc-workstation_darwin_arm64.tar.gz --repo zoolcoder/zc-workstation
The SBOM, <archive>.sbom.json, lists the Go modules built into each binary.
Report a problem through the repository’s security policy, never a public issue.
Edit this page Last updated