docs/install/architecture/network-security.mdx
Activepieces makes outbound HTTP from two surfaces, and each is hardened separately:
AP_NETWORK_MODE; see User-code egress.AP_SSRF_ALLOW_LIST; see Server-side egress.Both surfaces block the same set of IPs (RFC1918 private, loopback, link-local, cloud-metadata, non-unicast) and share the AP_SSRF_ALLOW_LIST allow-list.
Every flow eventually runs user-supplied code: Code steps, piece actions, HTTP requests. Without an explicit boundary, that code can reach anything the host can reach: 127.0.0.1, Redis, Postgres, the Kubernetes API, cloud-metadata endpoints (169.254.169.254), the VPC. AP_NETWORK_MODE is the switch that controls this boundary.
| Value | Effect |
|---|---|
UNRESTRICTED | No outbound guard. User code can reach any host the worker can reach. |
STRICT | The engine SSRF guard is installed. Outbound connections to private, loopback, link-local, and cloud-metadata IPs are blocked from user code. |
Related env var:
AP_SSRF_ALLOW_LIST: comma-separated IPs/CIDRs that bypass the block (for example an internal DB or sidecar). Shared with server-side egress.In STRICT mode the engine installs an in-process SSRF guard before any user code runs. It monkey-patches Node's dns.lookup and Socket.prototype.connect:
Together these cover axios, fetch, undici, and raw http/net in a single pass. A blocked target throws SSRFBlockedError. The blocklist is every non-unicast range (RFC1918, loopback, link-local, multicast, cloud metadata), minus anything in AP_SSRF_ALLOW_LIST.
For multi-tenant deployments that run untrusted code, enforce the real egress boundary in infrastructure: a VPC firewall, network policy, or egress gateway that blocks the cloud-metadata IP (169.254.169.254) and your private ranges independently of the application. Treat AP_NETWORK_MODE=STRICT as defense-in-depth on top of that, not as a replacement for it.
</Warning>
The guard is independent of the sandbox execution mode. It is installed in every mode when AP_NETWORK_MODE=STRICT. See Sandboxing for what each sandbox mode isolates at the process level. Network security is independent: it constrains what code is allowed to reach, regardless of how it runs.
From a Code step in a test flow, try:
const res = await fetch('http://169.254.169.254/latest/meta-data/')
With AP_NETWORK_MODE=STRICT you should see an SSRFBlockedError. With UNRESTRICTED the request succeeds if the host allows it, confirming the guard is off.
UNRESTRICTED (default) and identify any internal services that legitimate flows need to reach (internal APIs, databases used by Code steps, and so on).AP_SSRF_ALLOW_LIST.AP_NETWORK_MODE=STRICT. Watch worker logs for SSRFBlockedError. Each one is either an attack, a misconfigured flow, or a missing allow-list entry.Separate from flow code, the API server itself makes outbound HTTP on behalf of admins and users: OAuth token claim and refresh, Hashicorp Vault, CyberArk Conjur, event-destination webhooks, on-call pager, MCP tool validation. The URLs come from admin config (Vault server URL) or user input (webhook destination, MCP server URL), so the same SSRF risks apply.
Unlike user-code egress, this layer is always on. It does not require AP_NETWORK_MODE=STRICT. It is implemented as a request-filtering-agent wrapper attached to the shared axios instances in @activepieces/server-utils, and every outbound request flows through it. The blocked ranges are identical to the engine guard (RFC1918, loopback, link-local, cloud metadata, non-unicast).
When a request is blocked, the axios error surfaced in the admin UI includes the AP_SSRF_ALLOW_LIST hint, so operators see the fix directly in connection-test dialogs.
If Vault, Conjur, an on-prem OAuth2 token endpoint, or an internal webhook resolves to a private IP, the server-side filter rejects it until you add the target to AP_SSRF_ALLOW_LIST:
AP_SSRF_ALLOW_LIST=10.0.5.12,192.168.10.0/24
Connectors that accept self-signed certs (for example CyberArk Conjur in a private cluster) use rejectUnauthorized: false. The SSRF filter still applies under this setting: TLS verification is relaxed, SSRF protection is not.