Architecture¶
SHADI (Secure Host Agentic AI Dynamic Instantiation) is a secure host runtime for interactive, autonomous agents. It combines secure secret storage, verified identity, and kernel-enforced sandboxing to reduce the blast radius of agent actions and prevent unauthorized data access or exfiltration.
Goals¶
- Run dynamic, interactive agents with least-privilege access.
- Protect secrets at rest and limit access to verified sessions.
- Enforce kernel-level restrictions so unauthorized operations are blocked by the OS.
- Provide secure, low-latency agent-to-agent messaging via MLS.
- Keep platform support across macOS, Windows, and mobile targets.
Non-goals¶
- Protect against a fully compromised host OS or kernel.
- Provide complete metadata privacy for network traffic in v1.
- Replace upstream MLS or OS keystore implementations.
Architecture overview¶
flowchart TB
subgraph Experience[Experience and Control]
Operator[Operators and platform teams]
Configuration[Policies, profiles, and workload configuration]
Launch[Secure launch orchestration]
end
subgraph Platform[SHADI secure runtime]
Identity[Identity and session trust]
SecretControl[Secret control plane]
Delivery[Trusted secret delivery]
Enforcement[OS sandbox enforcement]
Memory[Encrypted local memory]
Transport[Secure agent transport]
end
subgraph Workloads[Protected workloads]
Agents[Agents, tools, and automations]
end
subgraph Services[External systems]
Repos[GitHub and developer systems]
Models[Model providers]
Peers[SLIM and A2A peers]
end
Operator --> Configuration
Configuration --> Launch
Launch --> Identity
Launch --> SecretControl
Launch --> Enforcement
Identity --> SecretControl
SecretControl --> Delivery
SecretControl --> Memory
Enforcement --> Agents
Delivery -. scoped secret access .-> Agents
Memory -. encrypted state .-> Agents
Transport --> Agents
Agents --> Repos
Agents --> Models
Agents --> Peers
The system can be read as four presentation layers:
- Experience and control: operators, policies, profiles, and
shadictldefine the launch contract before a process starts. - Secure runtime: identity, secret control, trusted delivery, sandboxing, transport, and encrypted memory enforce that contract during execution.
- Protected workloads: agents, tools, and automations run inside the approved runtime boundary.
- External systems: workloads connect to GitHub, model providers, and SLIM/A2A peers only after policy and trust checks are in place.
Core components¶
1) Secrets layer¶
- OS keystores: Keychain (macOS/iOS), DPAPI/CNG (Windows), Keystore (Android), Secret Service (Linux).
- 1Password backend (optional): Cross-platform secret storage via the
opCLI. Enabled with theonepasswordCargo feature andSHADI_SECRET_BACKEND=onepassword. Supports team/shared vaults and headless CI viaOP_SERVICE_ACCOUNT_TOKEN. - Access control: Secrets are accessed only after DID/VC verification.
- Memory safety: Secrets are wrapped in
SecretBytesand zeroized on drop. - OpenPGP parsing:
shadictlusessequoia-openpgpto ingest keys without calling OSgpg.
Key modules¶
crates/agent_secrets/src/lib.rs:SecretStoretrait, errors, and default store.crates/agent_secrets/src/agent.rs:AgentSecretAccessgates reads/writes on verification.crates/agent_secrets/src/memory.rs:SecretByteszeroization wrapper.crates/agent_secrets/src/platform: platform keychain backends.crates/agent_secrets/src/platform/macos.rs: Keychain storage + key registry for listing.crates/agent_secrets/src/platform/onepassword.rs: 1Password backend viaopCLI.crates/shadictl/src/main.rs: OpenPGP ingestion, DID derivation, and secret store helpers.
1b) Identity derivation and provenance¶
- Deterministic derivation: Agent keys are derived from human identity material through a fixed KDF pipeline.
- KDF details: HKDF-SHA256 with salt
shadi-agent-derive, IKM from human source bytes (gpgorseed), andagent_nameas HKDF info. - Output model: 32-byte Ed25519 seed -> local agent keypair ->
did:keyDID document. - Provenance binding: Optional
{prefix}/{agent}/human_didbinding allows explicit linkage from derived agent identity back to a stored human DID. - Verification command:
verify-agent-identityrecomputes derived key + DID and compares with stored values; can also enforce human DID binding checks.
Key modules¶
crates/shadictl/src/main.rs:derive-agent-did,derive-agent-identity,verify-agent-identity, and derivation helpers.
2) Sandbox layer¶
- macOS: Seatbelt profile enforcement for filesystem and network policies.
- Windows: AppContainer + ACL allowlists + Job Objects (kill-on-close).
- CLI:
shadiprovides JSON policy loading, profile defaults, optional command blocklists, process-scoped secret disclosure, and trusted secret delivery. - Portable launcher model:
shadisupports built-in profiles (strict,balanced,connected) for portable secure launch defaults. - Launch-time enforcement: Policy is resolved before the agent process starts, so the sandbox is not a prompt-level suggestion that the agent can rewrite from inside the session.
- Operational hardening: macOS launcher support now resolves relative paths before emitting Seatbelt rules and accounts for required local IPC paths such as 1Password, SLIM runtime state, and temporary trusted-secret broker endpoints.
Key modules¶
crates/shadi_sandbox/src/policy.rs: policy model and helpers.crates/shadi_sandbox/src/platform: OS-specific sandbox enforcement.crates/shadictl/src/main.rs: CLI parsing, policy resolution, and key listing.
3) Memory layer¶
- Local encrypted store: SQLCipher-backed SQLite for portable, on-device memory.
- Key management: Encryption keys live in SHADI secrets (keychain backed).
- Agent usage: workloads running on SHADI can persist local state in the encrypted store; the SecOps demo writes summaries there, while ADK memory remains in-process unless configured for persistent backends.
Key modules¶
crates/shadi_memory/src/lib.rs: SQLCipher store and query helpers.crates/shadictl/src/main.rs:shadictl memoryhelper.crates/shadi_py/src/lib.rs: SQLCipher bindings.agents/secops/skills.py: example summary persistence used by the SecOps demo.
4) Transport layer¶
- SLIM/A2A: MLS provides confidentiality and integrity between agents.
- Verified sessions: Messages are only sent/received after DID/VC checks.
Key modules¶
crates/agent_transport_slim/src/lib.rs: transport adapter and verifier gating.
5) Secret delivery and policy framework¶
SHADI now has a launch-time secret-delivery framework with exact executable matching. The important distinction is not just what secret is being requested, but which process may receive it and whether the secret is being disclosed or trusted-delivered.
Current rule types¶
process_inject_keychain: explicit env disclosure to the exact launched executable.process_trusted_secret: process-scoped direct trusted-secret delivery to the exact launched executable.process_secret_policy: action-based rules for a launched executable, including delegated child delivery on Unix/macOS.
CLI compatibility flags exist for the same concepts:
--inject-keychain KEY=ENV--trusted-secret KEY=NAME--trusted-secret-exec NAME=PROGRAM--trusted-secret-fd-env NAME=ENV
Current delivery modes¶
-
Explicit disclosure SHADI reads the secret before launch and injects it into the target process environment. This is compatibility-oriented and should be treated as intentional disclosure.
-
Process-scoped trusted delivery The launched executable receives a protocol-specific endpoint reference rather than a broad ambient secret. On Unix/macOS the current implementation is a one-shot brokered fetch with a launch-scoped nonce companion env.
-
Delegated child delivery A launched parent process can be allowed to request delivery of a secret to a specific child executable. On Unix/macOS, SHADI verifies the child process, optional child SHA-256 constraints, and the presented nonce before releasing the secret. The parent process does not receive the secret itself.
Key modules¶
crates/shadictl/src/trusted_secret_delivery.rs: secret resolution, exact-program matching, broker lifecycle, and delegated child verification.crates/shadictl/src/sandbox_snapshot.rs: launch orchestration, runtime policy augmentation for broker endpoints, and trusted-secret post-spawn delivery.crates/shadictl/src/policy_helpers.rs: env disclosure helpers for explicit inject-keychain behavior.crates/shadi_sandbox/src/policy.rs: minimal-profile and local Unix socket opt-in controls.
Secret delivery security model¶
The current implementation distinguishes explicit disclosure from final-consumer delivery. The important distinction is not only what secret is being requested, but which process may receive it and whether that process needs raw disclosure at all.
Problem statement¶
Two different risks need different controls:
- Wrong-process disclosure: a secret is placed in a parent process or its ambient environment and becomes available to unrelated descendants.
- Prompt-injection misuse: an LLM-driven process that legitimately sees a secret is induced to exfiltrate it.
The current trusted-secret path improves the first risk on Unix/macOS. The current model is based on these security properties:
- SHADI remains the delivery authority until the final authorized consumer process exists.
- A parent process may request or authorize a child tool launch, but the parent does not become the carrier of the secret.
- Environment injection is treated as explicit disclosure, not as the default secure path.
Secret actions¶
Policy should be expressed in terms of actions on a secret rather than a coarse secret category.
disclose: the process may read the secret value directly.use: the policy may represent a narrower operation that depends on the secret without implying ambient plaintext disclosure.delegate-to-child: the process may request that SHADI deliver the secret to a specific child process, but the parent does not receive the secret.signorauthenticate: the process may invoke a narrower operation backed by the secret without receiving the raw secret when the platform integration supports that shape.
Final-consumer delivery rule¶
The core enforcement rule is:
A secret must be delivered by SHADI directly to the final authorized consumer process, not inherited through a parent process and not placed into a general environment visible to unrelated descendants.
This rule applies even when the process tree is parent-driven:
- An agent or parent tool requests launch of child tool
T. - SHADI validates that
Tis allowed to receive actionAon secretS. - SHADI verifies the exact executable identity for
T. - SHADI launches or mediates the final consumer boundary.
- SHADI delivers the secret to
Tone time. - The parent does not receive the secret as an env var, inherited fd, handle, or reusable fetch token.
Prompt-injection boundary¶
Prompt injection is a separate concern from wrong-process delivery.
- Process-boundary controls decide which process can receive a secret.
- Prompt-injection controls decide whether that process should ever receive a raw secret at all.
This means LLM-driven executables should default away from disclose whenever a
safer action is available.
- Deterministic or tightly scoped tools may receive
disclosewhen necessary. - LLM-driven agents should more commonly receive
delegate-to-childor a narrowerusecapability. - High-value provider credentials should prefer mediation patterns where SHADI or a trusted adapter performs the authenticated action and returns only the result.
Current cross-platform behavior¶
The common security property is:
SHADI delivers the secret to the final authorized consumer process after that process exists and has been verified, without requiring the parent process to carry the secret.
The transport can be platform-specific, but the policy and trust boundary should stay the same.
- macOS / Linux: local broker endpoint after spawn, with peer PID and executable verification before one-shot delivery.
- Windows: direct trusted-secret delivery currently uses a compatibility inherited-handle transport. The final-consumer delegated path described above is documented for Unix/macOS.
Compatibility mode¶
The existing env-injection and inherited-handle paths may still be kept as explicit compatibility mechanisms, but they should be documented as disclosure mode rather than the target secure design.
- env injection: explicit
discloseto the target process, - inherited Windows handles: compatibility path for direct trusted delivery,
- brokered final-consumer delivery: preferred secure path.
Python bindings¶
SHADI exposes a Python extension for secrets, SQLCipher memory, and sandbox execution.
Key modules¶
crates/shadi_py/src/lib.rs:ShadiStore,PySessionContext,SqlCipherMemoryStore,SandboxPolicyHandle, andrun_sandboxedbindings.
Python API surface¶
ShadiStore.set_verifier(callable)to supply DID/VC verification logic.ShadiStore.verify_session(session, presentation)to set verified sessions.ShadiStore.get/put/deletefor secret access.ShadiStore.list_keysto enumerate stored keys (backed by key registry on macOS).SqlCipherMemoryStorefor encrypted local memory.SandboxPolicyHandle+run_sandboxedfor sandbox execution.
CLI policy resolution¶
The CLI combines profile defaults, policy file settings, and explicit flags:
- Profile defaults are loaded first (balanced by default).
- Policy file values are merged next.
- CLI flags override or extend resulting policy.
- The effective policy can be printed with --print-policy.
Demo workload: SecOps agent¶
The SecOps agent is an example workload that runs on top of SHADI. It uses the Python bindings for secrets plus GitHub APIs for security signals, but it is not part of the core runtime itself.
Key modules¶
agents/secops/skills.py: skills to collect alerts and issues.agents/secops/secops.py: runner invoking the skill.agents/secops/adk_agent/agent.py: Google ADK agent.agents/secops/SKILL.md: Agent Skills spec metadata and runbook.
SecOps flow¶
- Read config from secops.toml.
- Fetch GitHub token and workspace path from SHADI.
- Collect Dependabot alerts and security-labeled issues.
- Collect code-scanning alerts for container findings via GitHub code scanning.
- For dependency alerts, patch supported manifests and stage repo-relative changes.
- For container CVEs, locate the authoritative Dockerfile from GitHub workflow metadata when possible and recommend image rebuilds or base-image refreshes instead of ad-hoc package-install edits.
- Create remediation issues and optional PRs, then write
secops_security_report.jsonto the workspace.
Detailed flow diagrams¶
The overview diagram above shows the main blocks. The following diagrams zoom in on the paths that matter most when reading or operating the system.
1) Identity, secret storage, and memory bootstrap¶
flowchart LR
Source[Human identity source] --> Derive[Derive agent identity]
Derive --> Register[Register trusted secrets]
Register --> Verify[Verify session and operator context]
Verify --> Access[Authorize secret access]
Access --> Protect[Release memory key]
Protect --> Persist[Persist encrypted state]
This is the trust bootstrap path:
- Human identity material is imported or derived.
- SHADI stores agent keys, DIDs, and optional provenance bindings in the secret store.
- Session verification gates later reads.
- The SQLCipher memory key is retrieved through the same secret-control path rather than living in plaintext config.
2) Policy resolution and sandbox launch¶
flowchart LR
Profiles[Launcher profiles] --> Resolve[Resolve effective policy]
Policy[Policy file] --> Resolve
Overrides[CLI overrides] --> Resolve
Resolve --> SecretPolicy[Resolve secret delivery intent]
SecretPolicy --> Runtime[Prepare runtime guardrails]
Runtime --> Launch[Launch protected process]
This launch path matters because the agent does not get to reinterpret the policy from inside the session.
- Profile defaults establish the baseline (
strict,balanced, orconnected). - Policy JSON adds exact executable rules and file/network allowances.
- CLI flags override or extend the result.
- Secret rules are resolved before spawn so SHADI knows whether a secret is being disclosed, directly trusted-delivered, or delegated to a child.
- Runtime policy is expanded only as needed, for example to allow a temporary broker endpoint or local Unix socket transport.
3) Trusted secret delivery and delegated child flow¶
sequenceDiagram
participant SHADI as SHADI runtime
participant Parent as Parent workload
participant Broker as Delivery broker
participant Child as Authorized child tool
participant Store as Secret store
SHADI->>Store: Resolve secret rule and target identity
SHADI->>Parent: Launch protected parent process
SHADI->>Broker: Create launch-scoped delivery channel
Broker-->>Parent: Endpoint reference and nonce
Parent->>Child: Start authorized tool
Child->>Broker: Request secret delivery
Broker->>Broker: Verify process identity, executable path, and optional hash
Broker->>Store: Read approved secret payload
Store-->>Broker: Secret bytes
Broker-->>Child: Release one-time secret payload
Broker-->>Broker: Close channel and revoke reuse
This is the main architecture change in the PR series:
process_inject_keychainremains explicit disclosure.process_trusted_secretprovides direct process-scoped trusted delivery.process_secret_policyadds action-based rules such asdelegate-to-child.- On Unix/macOS, SHADI verifies the final child consumer before releasing the secret.
4) Runtime workload flow¶
flowchart LR
Workload[Protected workload] --> Secrets[Verified secret access]
Workload --> Memory[Encrypted memory]
Workload --> Transport[Secure transport]
Workload --> GitHub[GitHub and developer systems]
Workload --> Models[Model providers]
Workload --> Outcomes[Reports, issues, PRs, or actions]
Example workloads such as SecOps or Avatar sit on top of the same runtime contract:
- secret reads are still gated by verification,
- local persistence still flows through encrypted memory,
- network access still depends on the resolved sandbox policy,
- and transport still uses SLIM/A2A when agents communicate with each other.
5) SecOps remediation flow¶
flowchart TD
Inputs[Configuration and approved credentials] --> Collect[Collect security signals]
Collect --> Triage[Classify remediation path]
Triage --> Dependency[Patch supported dependencies]
Triage --> Container[Recommend rebuild or base-image refresh]
Dependency --> Publish[Create reports, issues, or PRs]
Container --> Publish
Publish --> Learn[Persist remediation memory]
SecOps behavior stays intentionally split by remediation type:
- Dependency remediation can edit supported manifests directly.
- Container CVEs are handled as rebuild guidance rather than ad-hoc Dockerfile package-install edits.
- Dockerfile discovery prefers authoritative workflow definitions before falling back to repository scanning.
Threats addressed¶
Secrets and credential theft¶
- Stopped: Reading secrets without verification.
- Stopped: Exfiltration of secrets from disk when keystore access is denied.
- Stopped: Accidental logging of secrets by non-verified sessions.
- Mitigated: In-memory exposure via zeroization and limited lifetime.
Identity spoofing / provenance ambiguity¶
- Stopped: Undetected key substitution when
verify-agent-identityis used. - Mitigated: Agent ownership ambiguity via stored
human_didbinding + verification.
Filesystem abuse¶
- Stopped: Accessing paths outside allowlists (kernel enforcement).
- Stopped: Writing to disallowed paths in sandboxed processes.
- Mitigated: Destructive commands via CLI blocklist.
Network abuse¶
- Stopped: Network access when
net_blockis enabled. - Mitigated: Unapproved endpoints with best-effort
net_allowguard for Python sandbox runners.
Agent-to-agent data leakage¶
- Stopped: Unauthorized peers reading messages; MLS provides confidentiality.
- Stopped: Message tampering; MLS provides integrity/authentication.
Privilege escalation¶
- Mitigated: Prompt-level or path-level agent reasoning by applying sandbox policy before launch.
- Mitigated: Running blocked commands via CLI blocklist when that feature is used.
- Mitigated: Kernel-level constraints remain even if the agent tries to evade application-layer logic.
Threat-to-control mapping¶
| Threat | Control | Outcome |
|---|---|---|
| Unverified secret access | DID/VC verifier + AgentSecretAccess |
Blocked |
| Secret theft at rest | OS keystore storage | Blocked |
| Secret exfiltration in sandbox | OS sandbox + net block | Blocked |
| Unauthorized file access | Seatbelt/AppContainer allowlists | Blocked |
| Destructive commands | CLI blocklist | Mitigated |
| Message interception | MLS in SLIM | Blocked |
| Message tampering | MLS integrity | Blocked |
| Agent identity substitution | HKDF derivation + verify-agent-identity | Blocked (with verification) |
| Process escape | Kernel enforcement | Mitigated |
Residual risks¶
- Host OS compromise or kernel-level malware can bypass sandbox controls.
- Metadata leakage (timing, sizes, endpoints) is not fully addressed in v1.
- ACL changes on Windows could be interrupted before rollback in a crash.
- Application-level path deny rules are weaker than OS-enforced sandbox restrictions; do not rely on path matching alone for high-assurance policy.
Deployment guidance¶
- Prefer running agents under the sandbox with a JSON policy file.
- Use explicit disclosure only when a demo or workload truly needs the secret in the parent process, and prefer process-scoped or delegated trusted delivery where possible.
- Rotate secrets and use short-lived tokens whenever possible.
Policy examples¶
Minimal sandbox¶
{
"allow": ["."],
"net_block": true
}
Read-only project¶
{
"read": ["./src"],
"net_block": true
}