A typed-return secret broker: clients USE secrets over a unix socket, they never SEE the plaintext.
Project description
sandbroker
A typed-return secret executor. Claude Code causes secrets to be used without ever learning what they are.
Full design, runbook, platform matrix, and discoveries log:
~/dotfiles/docs/sandbroker-credential-broker.md
(also on GitHub under GraysonCAdams/dotfiles). This file is the short version.
The claim
No plaintext secret resolved by sandbroker appears in Claude's context, in the Anthropic API request body, in the local session transcript, or in any prompt cache, because no channel exists through which it could travel.
It does not claim anything about secrets arriving through doors sandbroker doesn't mediate. "100% secure" is not on offer; see Known limits in the doc.
Why not a redaction hook
A PostToolUse redaction hook is a filter, and filters fail open: unmatched
pattern, unexpected encoding, or an unanticipated error string, and the raw value
proceeds to the wire. sandbroker is not a filter. The response schema has no field
a secret can occupy.
How it holds
Four structural properties, all asserted in tests/test_guarantee.py (29 tests):
- The child cannot talk to us. Targets spawn with stdout/stderr bound to
/dev/nullat the fd level, so no output on any path reaches the caller. - Secrets never enter
argv. Rejected at registry load, because/proc/PID/cmdlineexposes argv to the same uid. - There is no shell. Argv vectors only, so arguments can never become code.
- Egress is allowlisted. Response keys outside
{ok, error, verb}are dropped and unknown error tokens collapsed.
Install
Two commands on Linux/WSL2 or macOS:
pipx install sandbroker # puts sandbroker, sandbrokerd, and the bin/ helpers on PATH
sandbroker setup # guided wizard: base + daemon, secret store, approver, Claude Code
sandbroker setup runs unprivileged (user mode) by default; add --hardened for
the dedicated-uid /opt/sandbroker system install. See
docs/integration-notes/setup-wizard.md.
Quick start from a checkout (Linux/WSL, systemd)
python3 tests/test_guarantee.py # expect OK
sudo ./install.sh # creates sandbroker uid + claude-broker
install -m 0755 bin/sandbroker ~/.local/bin/sandbroker
install -m 0755 hooks/deny_secret_reads.py ~/.claude/hooks/
# new login session for group membership, then:
sudo ./canary/canary_provision.sh
sandbroker canary.probe --ref file://canary # expect {"ok": true}
sudo ./canary/canary_sweep.sh # expect clean
The hook still needs merging into ~/.claude/settings.json; jq is absent on
WSL, so use the python snippet in the doc.
Ref schemes
| Scheme | Backend |
|---|---|
file://canary |
local 0400 file, verification only |
akv://<vault>/<name> |
Azure Key Vault via az |
op://<vault>/<item>/<field> |
1Password via op (macOS hosts) |
Layout
sandbroker/sandbrokerd.py the daemon: exec core, registry validator, egress filter
sandbroker/verbs.json capability grants; installed root:root 0444
bin/sandbroker the only interface Claude uses
hooks/ PreToolUse deny for doors sandbroker doesn't mediate
canary/ provision + sweep: the leak test that must keep passing
tests/ the guarantee, as executable assertions
install.sh every sudo step (Linux/systemd)
Verification note
A sweep only means something when Claude runs the probe. Running it yourself proves nothing, because the canary was never near the model's context. Have Claude exercise the verbs and attempt extraction, then sweep.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sandbroker-0.1.0.tar.gz.
File metadata
- Download URL: sandbroker-0.1.0.tar.gz
- Upload date:
- Size: 99.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
deea8dfcf9cc573c70acc7ec16f7cc7b472ce1027e2b0452cd2cbc53be7fabdb
|
|
| MD5 |
f832c0a115dda91bf7eb8fccdfe38c39
|
|
| BLAKE2b-256 |
14114fc9f2cb6cb22e87a10fd1e4aa7d828359584ebe6c7f620e0e58f18ad2e6
|
Provenance
The following attestation bundles were made for sandbroker-0.1.0.tar.gz:
Publisher:
release.yml on 312-dev/sandbroker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sandbroker-0.1.0.tar.gz -
Subject digest:
deea8dfcf9cc573c70acc7ec16f7cc7b472ce1027e2b0452cd2cbc53be7fabdb - Sigstore transparency entry: 2309703943
- Sigstore integration time:
-
Permalink:
312-dev/sandbroker@5b8f99943315da09110cc940422cefefa872c4fd -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/312-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5b8f99943315da09110cc940422cefefa872c4fd -
Trigger Event:
push
-
Statement type:
File details
Details for the file sandbroker-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sandbroker-0.1.0-py3-none-any.whl
- Upload date:
- Size: 97.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52e399994b3b3500cf10676c1f1df7b26b2016b5bf320b329965dfe7e0f90586
|
|
| MD5 |
60ba3a3ce050ee75574be915c3379061
|
|
| BLAKE2b-256 |
73e7ddd0d043894d86b9f6df69cae12cc0c6194d308661ef0c091ebbf7b77210
|
Provenance
The following attestation bundles were made for sandbroker-0.1.0-py3-none-any.whl:
Publisher:
release.yml on 312-dev/sandbroker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sandbroker-0.1.0-py3-none-any.whl -
Subject digest:
52e399994b3b3500cf10676c1f1df7b26b2016b5bf320b329965dfe7e0f90586 - Sigstore transparency entry: 2309704011
- Sigstore integration time:
-
Permalink:
312-dev/sandbroker@5b8f99943315da09110cc940422cefefa872c4fd -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/312-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5b8f99943315da09110cc940422cefefa872c4fd -
Trigger Event:
push
-
Statement type: