Forge is designed with security as a foundational principle, not an afterthought. This document describes the complete security architecture — from network-level egress controls to encrypted secrets, build signing, execution sandboxing, and runtime guardrails.
Forge's security is organized in layers, each addressing a different threat surface:
┌──────────────────────────────────────────────────────────────┐
│ Guardrails │
│ (content filtering, PII, jailbreak) │
├──────────────────────────────────────────────────────────────┤
│ Egress Enforcement │
│ (EgressEnforcer + EgressProxy + NetworkPolicy) │
├──────────────────────────────────────────────────────────────┤
│ Execution Sandboxing │
│ (env isolation, binary allowlists, arg validation) │
├──────────────────────────────────────────────────────────────┤
│ Secrets Management │
│ (AES-256-GCM, Argon2id, per-agent isolation) │
├──────────────────────────────────────────────────────────────┤
│ Build Integrity │
│ (Ed25519 signing, SHA-256 checksums) │
├──────────────────────────────────────────────────────────────┤
│ Network Posture │
│ (outbound-only connections, no public listeners) │
└──────────────────────────────────────────────────────────────┘
- Network Posture
- Egress Enforcement
- Execution Sandboxing
- Secrets Management
- Build Integrity
- Guardrails
- Audit Logging
- Container Security
- Related Documentation
Forge agents are designed to never expose inbound listeners to the public internet:
- No public tunnels — Forge does not create ngrok, Cloudflare, or similar tunnels
- No inbound webhooks — Channels use outbound-only connections
- Slack: Socket Mode (outbound WebSocket via
apps.connections.open) - Telegram: Long-polling via
getUpdates
- Slack: Socket Mode (outbound WebSocket via
- Local-only HTTP server — The A2A dev server binds to
localhostby default - No hidden listeners — Every network binding is explicit and logged
This means a running Forge agent has zero inbound attack surface by default.
Forge restricts outbound network access at three levels:
The EgressEnforcer is a Go http.RoundTripper that wraps every outbound HTTP request from in-process tools (http_request, web_search, LLM API calls). It validates the destination domain against a resolved allowlist before forwarding.
Skill scripts and cli_execute subprocesses bypass Go-level enforcement. A local EgressProxy on 127.0.0.1:<random-port> validates domains for subprocess HTTP traffic via HTTP_PROXY/HTTPS_PROXY env var injection.
In containerized deployments, generated Kubernetes NetworkPolicy manifests enforce egress at the pod level, restricting traffic to allowed domains on ports 80/443.
| Mode | Behavior |
|---|---|
deny-all |
All non-localhost outbound traffic blocked |
allowlist |
Only explicitly allowed domains (exact + wildcard) |
dev-open |
All traffic allowed (development only) |
Allowed domains are resolved from three sources:
- Explicit domains — Listed in
forge.yamlunderegress.allowed_domains - Tool domains — Automatically inferred from registered tool names (e.g.,
web_search→api.tavily.com) - Capability bundles — Pre-defined domain sets for common services (e.g.,
slack→slack.com,hooks.slack.com,api.slack.com)
Localhost (127.0.0.1, ::1, localhost) is always allowed in all modes.
For full details on egress enforcement, see Egress Security.
Forge agents execute external code through two sandboxed executors, both designed to minimize the attack surface of subprocess execution.
Skill scripts run via SkillCommandExecutor (forge-cli/tools/exec.go):
| Control | Detail |
|---|---|
| Environment isolation | Only PATH, HOME, and explicitly declared env vars are passed through |
| Egress proxy injection | HTTP_PROXY/HTTPS_PROXY env vars route subprocess HTTP through the egress proxy |
| Configurable timeout | Per-skill timeout_hint in YAML frontmatter (default: 120s) |
| No shell | Runs bash <script> <json-input>, not through a shell interpreter |
| Scoped env vars | Only env vars declared in the skill's requires.env section are passed |
The cli_execute tool (forge-cli/tools/cli_execute.go) provides 7 security layers:
| # | Layer | Detail |
|---|---|---|
| 1 | Binary allowlist | Only pre-approved binaries can execute |
| 2 | Binary resolution | Binaries are resolved to absolute paths via exec.LookPath at startup |
| 3 | Argument validation | Rejects arguments containing $(, backticks, or newlines |
| 4 | Timeout | Configurable per-command timeout (default: 120s) |
| 5 | No shell | Uses exec.CommandContext directly — no shell expansion |
| 6 | Environment isolation | Only PATH, HOME, LANG, explicit passthrough vars, and proxy vars |
| 7 | Output limits | Configurable max output size (default: 1MB) to prevent memory exhaustion |
tools:
- name: cli_execute
config:
allowed_binaries: ["git", "curl", "jq", "python3"]
env_passthrough: ["GITHUB_TOKEN"]
timeout: 120
max_output_bytes: 1048576Forge provides AES-256-GCM encrypted secret storage with Argon2id key derivation, per-agent isolation, and a three-tier resolution hierarchy (agent-local -> global -> environment). Secrets are managed via forge secret set|get|list|delete.
For full details, see Secrets Management.
Forge supports Ed25519 signing and SHA-256 checksumming of build artifacts for supply chain integrity. At runtime, forge run can verify artifacts against trusted keys before execution.
For full details, see Build Signing & Verification.
The guardrail engine checks inbound and outbound messages against policy rules including content filtering, PII detection, and jailbreak protection. Guardrails run in enforce (blocking) or warn (logging) mode.
For full details, see Content Guardrails.
All runtime security events are emitted as structured NDJSON to stderr with correlation IDs for end-to-end tracing.
| Event | Description |
|---|---|
session_start |
New task session begins |
session_end |
Task session completes (with final state) |
tool_exec |
Tool execution start/end (with tool name) |
egress_allowed |
Outbound request allowed (with domain, mode) |
egress_blocked |
Outbound request blocked (with domain, mode) |
llm_call |
LLM API call completed (with token count) |
guardrail_check |
Guardrail evaluation result |
{"ts":"2026-02-28T10:00:00Z","event":"session_start","correlation_id":"a1b2c3d4","task_id":"task-1"}
{"ts":"2026-02-28T10:00:01Z","event":"tool_exec","correlation_id":"a1b2c3d4","fields":{"tool":"tavily_research","phase":"start"}}
{"ts":"2026-02-28T10:00:01Z","event":"egress_allowed","correlation_id":"a1b2c3d4","fields":{"domain":"api.tavily.com","mode":"allowlist","source":"proxy"}}
{"ts":"2026-02-28T10:00:05Z","event":"tool_exec","correlation_id":"a1b2c3d4","fields":{"tool":"tavily_research","phase":"end"}}
{"ts":"2026-02-28T10:00:06Z","event":"session_end","correlation_id":"a1b2c3d4","fields":{"state":"completed"}}The source field distinguishes in-process enforcer events from subprocess proxy events.
Every forge build generates container-ready security artifacts:
| Artifact | Purpose |
|---|---|
egress_allowlist.json |
Machine-readable domain allowlist |
network-policy.yaml |
Kubernetes NetworkPolicy restricting pod egress |
Dockerfile |
Container image with minimal attack surface |
checksums.json |
SHA-256 checksums + Ed25519 signature |
When Forge detects it's running inside a container (via KUBERNETES_SERVICE_HOST or /.dockerenv):
- The local
EgressProxyis not started —NetworkPolicyhandles egress enforcement at the infrastructure level - All other security controls (guardrails, execution sandboxing, audit logging) remain active
- Secrets must use the
envprovider (encrypted files can't be decrypted without a passphrase)
forge package --prodProduction builds enforce:
- No
dev-openegress mode - No dev-only tools (
local_shell,local_file_browser) - Secret provider chain must include
env(not justencrypted-file) .dockerignoremust exist if a Dockerfile is generated
| Document | Description |
|---|---|
| Egress Security | Deep dive into egress enforcement: profiles, modes, domain matching, proxy architecture, NetworkPolicy |
| Secrets Management | Encrypted storage, per-agent secrets, passphrase handling |
| Build Signing & Verification | Key management, build signing, runtime verification |
| Content Guardrails | PII detection, jailbreak protection, custom rules |
| Architecture | System design, module layout, and data flows |
| Tools | Tool system including cli_execute security layers |
| Skills | Skill definitions and runtime execution |
| Commands | CLI reference including security-related flags |
← Channels | Back to README | Egress Security →