Threat model
What Secretariat protects, and what it doesn't
Secretariat is built against accidents: a key landing in an agent's context, a log or a commit. It is not a sandbox. This page says where the line is, so you can decide what else you need.
Applies to Secretariat 1.7.
Protects against
- Keys in plain
.env files that an agent reads, greps or summarizes
- Values printed by a program and pulled into the agent's context
- Values in tool output that ends up in logs or transcripts
- Committing a value you have stored in Secretariat
- Forgotten copies in Cloudflare, Supabase, GitHub or on servers after you rotate a key
Does not protect against
- An agent that deliberately extracts a value it is allowed to run with
- Values written to files instead of printed
- Malware running with your user rights
- A compromised Apple Account or iCloud keychain
- Secrets Secretariat doesn't know about
How each layer works
No plain files
Values live in your iCloud keychain, not in your project folders. secretariat run hands them to the program as environment variables; key files become temporary files with mode 0600. An agent that reads your project finds profile and item names, not values. Fields marked only-for-me never reach any program.
Output masking
When stdout or stderr is not a terminal, which is the case when an agent or a pipe reads it, Secretariat replaces every value it handed to the program with [masked path/field]. This catches the common accident: a debug print, a stack trace with the config, a verbose CLI.
Limits you should know:
- It only covers stdout and stderr of the program started by
run. A value the program writes to a file, sends over the network or passes on in another form is not masked.
- It matches the exact value. An encoded or transformed value (base64, split across lines by the program, URL-encoded) is not recognized. Very short values (under 6 characters) are not masked.
- Whoever calls
run can pass --no-mask. Masking prevents accidents; it is not a lock.
Touch ID approval per item: the hard boundary
For an item with approval switched on, every run, push or inject that needs it waits for your fingerprint. An agent can switch approval on for an item, never off; that is only possible in the app.
This is the one layer that holds against an agent that is trying. Without it, the reality is simple: an agent running as your user can call secretariat run PROFILE -- env > values.txt itself, or any program that writes its environment to a file, and then read the file. No tool can fully hide a secret from a process that runs as the same user and is allowed to use it.
Approval only helps if you read the prompt. Approve when you started the command or expected it, and decline otherwise.
Commit guard
The git pre-commit hook compares staged changes with the values Secretariat knows and refuses the commit if one appears. It catches your real values, including ones no pattern scanner would recognize. It does not catch secrets you never stored in Secretariat, values shorter than 8 characters, or commits made with git commit --no-verify, which skips all hooks.
Targets and rotation
Secretariat remembers where it pushed each value: Cloudflare Workers, Supabase, GitHub, Linux env files over ssh. After a rotation, secretariat targets lists every copy that is now stale. It knows only the copies it pushed itself, not ones you placed by hand.
Out of scope
Malware with your user rights
Software that runs as you can do what you can do: start programs through Secretariat, read their environment, wait for you to approve a prompt. Secretariat doesn't defend against a compromised user account.
Your Apple Account and iCloud keychain
Sync is Apple's iCloud keychain. Whoever controls your Apple Account and can add a device to your keychain can read what is in it. Secretariat has no server of its own, so there is nothing else to break into, and nothing else to rely on.
The services your keys belong to
Once a program has a key, it can do whatever the key allows. Secretariat doesn't limit what a key can do at the provider.
Recommendations
- Switch on Touch ID approval for everything that would hurt: production databases, payment providers, deploy tokens, signing keys. Leave it off for test keys you use a hundred times a day.
- Install the commit guard everywhere:
secretariat guard install --all ~/work. Don't bypass it with --no-verify unless you know why.
- Import, then delete the plain files. Bulk-import your
.env files, check the review list, and remove the originals so there is nothing left to read.
- Use scoped keys. Prefer test-mode and restricted keys for agent work. A masked full-access key is still a full-access key.
- Rotate after an incident and follow the list. Run
secretariat targets and push until no copy is stale.
- Secure your Apple Account with a strong password and two-factor authentication, and keep macOS up to date.
- Use your agent's own restrictions as well. Permission prompts and sandbox modes add to Secretariat; they don't compete with it.
Reporting a problem
If you find a way around a boundary described here, please email business@moinsen.dev. The source is available on GitHub, so you can check these claims against the code.