Threat model
Keep credential values out of the agent's reach
Developer tools execute third-party code in a high-trust context. For built-in HTTP and SSH, Sallyport keeps the stored reusable credential out of that ambient context and mediates each invocation locally.
Credential value
Sallyport does not intentionally add resolved credentials to agent results, approvals, audit events, logs, or errors. It does not inspect or rewrite executor responses, which may contain sensitive target-supplied data.
Authorization
Vault state, per-call controls, and live process identity decide whether a tool invocation can start.
Evidence
Every admitted tool invocation needs a durable encrypted intent row first. Catalog discovery does not.
How a compromised dependency reaches credentials
A trusted package or workflow already runs where developers and CI keep reusable credentials. Once that code turns malicious, reading and exporting those credentials can be a single execution path.
Recent incidents used this path
The details vary by campaign. In each case, malicious code executed close to credentials that other systems would accept later.
May 2026
Malicious TanStack packages
Eighty-four malicious versions across 42 @tanstack packages ran an install-time payload that harvested cloud credentials, GitHub tokens, and SSH keys, then attempted to spread through packages maintained by each victim.
TanStack security advisoryLate 2025
Shai-Hulud npm campaigns
Compromised packages used install-time execution to steal secrets and spread with stolen credentials. Later variants added CI-specific behavior and self-hosted runner abuse.
GitHub supply chain reviewAugust 2025
Nx S1ngularity
Malicious Nx package versions ran a post-install script that scanned developer systems for sensitive data, attempted to use local AI tools, and uploaded results through GitHub CLI.
Nx incident postmortem
Remove reusable credentials from the process
A secret in an environment variable or file is data the process can copy. A Sallyport-managed credential is instead an input to a local operation, subject to vault state, approval, target binding, and audit.
Ambient credential
Built-in HTTP / SSH
For built-in HTTP and SSH, a package cannot read the stored credential from the agent's environment. It must request an operation that can be denied, gated per call, constrained to the requested or configured target, and journaled. The target response is returned without content inspection or rewriting.
This does not stop malicious code from running or prove an approved request is benign. HTTP and SSH targets may return sensitive data. Remote MCP servers receive configured authentication; local stdio servers receive bound credentials in their environment. Treat every target and upstream as a trusted credential recipient.
The same checks run on every admitted invocation
The compiled ladder applies to tool invocation. Upstream initialize and tools/list traffic manages the catalog outside this path and receives no invocation intent row.
- 01
Vault ready
Any other state denies agent actions.
deny | next
- 02
Target resolves
Required target and credential metadata must exist.
deny | next
- 03
Per-call check
Flagged keys or upstreams ask every time.
ask | next
- 04
Process admission
Admit the live process by session, allowlist, session card, or observe mode. This does not identify which loaded package or inherited byte source made the request.
ask | next
- 05
Audit intent
The encrypted intent must be durable before execution.
deny | run
- 06
Execute and return the result
Run the channel, append the outcome, and return the bounded executor result without content inspection or rewriting. Results may contain sensitive data.
result
An exact-cdhash allowlist stops matching after a binary update. A publisher entry can keep matching same-identity updates, so a compromised publisher or signing path remains trusted. Either entry skips only the session card.
Controls and residual risk
The model has an explicit boundary. Residual risk is part of it.
| Threat | What Sallyport changes | What remains |
|---|---|---|
| Malicious dependency reads files or environment | For built-in HTTP and SSH, Sallyport does not place the stored credential in the agent environment or intentionally add it to results, logs, approvals, or audit events. Executor results are returned without content inspection or rewriting. | Credentials outside Sallyport remain exposed. Local stdio MCP servers receive bound credentials and inherit Sallyport's environment. |
| Prompt-injected or compromised approved agent | Per-call keys still require a click or Touch ID. Sallyport rechecks live process identity on later invocations. | Admission covers the process, not each package or byte. Loaded code and writers to an inherited socket or pipe inherit that admission. |
| Credential redirected to another host | HTTP credentials attach only for a matching host and path. Credentialed requests do not follow redirects; uncredentialed redirects stay on the same host and port and cannot downgrade HTTPS. | Current DNS validation does not pin the checked address through connection, so a rebinding gap remains. |
| Local audit history is edited | Encrypted rows and the signed ciphertext chain detect edits, reordering, internal gaps, and signer substitution. A separate signed local checkpoint detects rollback behind it. | A post-checkpoint tail can be lost after an unclean shutdown. Complete consistent local rollback needs an off-device witness to distinguish it from restoration. |
| An upstream puts secrets in MCP catalog metadata | Choose and review upstream server code as part of the trust boundary. Sallyport returns tool results, errors, and authenticated catalog metadata without credential-content filtering, subject to documented size and description limits. | Initialize and tools/list are outside invocation audit. Their names, descriptions, and schemas are arbitrary upstream-controlled content and may contain credentials or other sensitive data. |
| Root or code execution inside Sallyport | Secure Enclave gates private key use and the vault remains encrypted at rest. | Root, disabled SIP, or in-process code execution can control an unlocked vault. Sallyport is not a host sandbox or antivirus. |
What this model does not claim
Sallyport reduces credential exposure and adds control around use. It does not turn hostile local code into trusted code.
Approval is not intent analysis
A session card identifies the process and its provenance. It does not determine whether every request inside that session is safe.
Process admission is not component isolation
A session identifies the live process. Code loaded into it, or a component writing through an inherited socket or pipe, receives the same admission.
The operator can approve harm
A click or Touch ID proves the ceremony happened. It cannot make a poorly reviewed operation harmless.
MCP upstreams are trusted recipients
A remote server receives its configured API key or OAuth token. A local stdio child receives bound credentials and the app environment. Sallyport does not sandbox either server.
Catalog metadata is untrusted content
Initialization and tools/list bypass the invocation ladder and intent audit. Tool names, descriptions, and schemas remain arbitrary upstream-controlled content without credential-content filtering; documented size and description limits apply.
Traffic outside Sallyport is outside scope
The app cannot govern direct network calls, shell commands, other credential stores, or tools that bypass its MCP surface.
Executor results may contain sensitive data
HTTP, MCP, and SSH results and errors are not inspected or rewritten. A target can return credentials or other sensitive data, and SSH recordings preserve target output.
Audit previews can contain caller data
Sallyport does not add resolved credentials to approvals or audit rows, but caller-supplied commands and arguments appear in summaries and bounded previews. Treat decrypted audit data as sensitive.
This is an interactive Mac product
The supported deployment is a signed app on Apple Silicon macOS with local UI and Touch ID. There is no Linux, container, server, cloud-runner, or headless CI mode.
Inspect the implementation
The core is open source under Apache-2.0. Read the implementation and the trust model, or build it locally.
View source on GitHub