Skip to main content

Security Model

Applies to SDK 0.19+ · Last updated: 2026-07-06

AgentNode is local-first by design. All tools run on your machine. The registry never sees what you do with them.

AgentNode runs third-party tool code on your machine. This page explains exactly what is enforced, what is declared but not enforced, and what you can do to stay safe.

Enforcement is trust-tiered

What gets enforced depends on the package's trust level:

Trusted / curated packages

Run on the host with subprocess isolation, environment filtering, and timeouts under the default host-trust policy. Their network/filesystem declarations are policy-checked, not OS-enforced — that's the trade these tiers earn through review. You stay in control: the sandbox.host_trust_policy setting can sandbox trusted (curated_only) or everything (none), with a reinstall to build the sealed volume.

Verified / unverified community packages

Run inside a hardened container sandbox — or not at all. If no container runtime or pinned sandbox image is available, execution is blocked (fail-closed). There is no silent fallback to host execution.

Community agents

Community-agent sandboxing is gated behind an explicit opt-in flag (default OFF). When enabled, community agents run sandbox-or-fail-closed with a host-side LLM broker — provider API keys never enter the container. When disabled, community agents are refused entirely. Trusted and curated agents run on the host like other trusted/curated code, so not every agent is sandboxed.

What is enforced

EnforcedContainer sandbox

Community-tier code (toolpack builds, toolpack runs, MCP servers, opt-in community agents) executes in a hardened container: read-only filesystem, non-root user, all capabilities dropped, no host mounts, no secrets. Networking is off by default across the board (unknown = deny); a community MCP must be pinned and preinstalled and gets network access only through a sealed egress allowlist it declares, while non-preinstalled MCP servers are refused. If the sandbox is unavailable, execution is denied — never downgraded to the host.

EnforcedNetwork allowlist

Community toolpack and agent-sandbox containers get a network only when the package declares a recognized network level; unknown, missing, or 'none' values mean the container runs with networking fully disabled (--network none, unknown = deny). Community MCP servers follow the same default-deny rule: they run with no network unless they declare a sealed egress allowlist (mcp_allowed_domains), and non-preinstalled MCP servers are refused.

EnforcedPinned sandbox image

The sandbox image is referenced by immutable digest, never by tag, and is never pulled automatically. You fetch it explicitly with 'agentnode sandbox pull'; 'agentnode sandbox doctor' explains the current state.

EnforcedPublisher signatures

Packages are signed with publisher Ed25519 keys. An invalid signature blocks install — no override, no force flag. Missing signatures warn (publisher adoption is gradual) but are never silent.

EnforcedLockfile integrity

Every lockfile entry carries a SHA-256 integrity hash over its security-critical fields ('agentnode lock seal' / 'lock verify'). Tampered entries are warned on by default and denied before execution in strict mode.

EnforcedLLM keys stay host-side

Sandboxed agents request completions through a host-side broker. Provider API keys never enter the sandbox container, audit records, manifests, or lockfiles.

EnforcedCredential storage

'agentnode auth set' stores keys in the OS keychain (Windows Credential Manager, macOS Keychain, Linux Secret Service). Where no keychain is available (e.g. headless Linux), storage honestly falls back to a plaintext file with 0600 permissions — and tells you so.

EnforcedPolicy gate

Every run_tool() call passes through check_run() which evaluates trust level, permissions, and environment context. Returns allow, deny, or prompt. Fail-closed when config is missing.

EnforcedEnv filtering

Host subprocess mode (trusted/curated tiers) strips API keys (AWS_*, OPENAI_*, STRIPE_*, etc.) from the child process environment. Only PATH, HOME, PYTHON*, and TEMP are passed through.

EnforcedSubprocess timeout

Tools running in subprocess mode are killed after a configurable timeout (default 30 seconds).

EnforcedTrust minimum

Your local config sets a minimum trust level (default: verified). Packages below this threshold are denied before execution.

EnforcedCI/non-interactive deny

In CI environments or when AGENTNODE_NON_INTERACTIVE is set, any 'prompt' decision escalates to 'deny'. No silent approvals in automation.

EnforcedAudit trail

All policy decisions are logged to ~/.agentnode/audit.jsonl. Append-only, rotated, local-only. Never contains secrets or tool inputs/outputs. Sandboxed agent runs write one aggregated, sanitized record per run.

EnforcedCredential domain lock

CredentialHandle validates the target domain against allowed_domains before attaching credentials, and refuses non-HTTPS targets. Secrets are never exposed via properties.

EnforcedAgent tool allowlist

Agent packages can only invoke tools explicitly listed in their manifest. Attempts to call unlisted tools are blocked — on the host and across the sandbox RPC boundary.

Honest limits — trusted/curated host execution

These limits apply to packages that run on the host because they earned trusted/curated status. Community-tier code does not have these gaps — it runs in the container sandbox or not at all. And you can remove the gaps yourself: set sandbox.host_trust_policy to curated_only or none to sandbox the trusted/curated tiers too (fail-closed; may require a reinstall).

Not enforcedNetwork access

For trusted/curated host execution, 'network: none' declarations are policy-checked but not OS-enforced — a trusted tool could still make HTTP requests. For community toolpacks, MCP servers, and agent sandboxes this IS enforced: the container runs with networking disabled unless a sealed egress allowlist is declared.

Not enforcedFilesystem access

Same scope: trusted/curated host tools are policy-checked, not OS-restricted. Community packages run on a read-only container filesystem with no host mounts.

Not enforcedDirect mode isolation

mode='direct' runs tool code in your process with full environment access. This is opt-in only — mode='auto' (the default) always uses subprocess isolation.

PartialInput validation

The input guard inspects tool arguments. Path-traversal and URL-anomaly findings require interactive confirmation — and are denied outright in non-interactive/CI contexts. Lower-severity findings (oversized inputs) remain non-blocking warnings.

Privacy

All execution is local. Tool inputs, outputs, and logs never leave your machine.

What the registry sees: Install events, search queries, and periodic trust-level refresh requests.

Audit logs: Stored at ~/.agentnode/audit.jsonl. Never transmitted. Contains only policy decisions (action, source, reason, trust level).

Recommendations

Questions or concerns? See our FAQ or reach out on GitHub.