docs/documentation/platform/agent-proxy/security.mdx
This page covers what is happening under the hood of the agent proxy: how every request is authenticated, how agents stay isolated from each other and from real credentials, how TLS interception works, and how the proxy behaves at scale. You do not need any of this to get started (see the Quickstart), but it is worth reading before running the proxy in production.
The proxy is pinned to one organization, the one its own machine identity belongs to, but nothing narrower: no project, environment, path, or services are configured on it. It discovers those per agent. When an agent connects, the proxy uses the agent's token to look up which proxied services that agent may use in the agent's folder scope, then fetches the real secret values with its own machine identity. This means one proxy instance can serve many agents across projects and environments in the org while keeping them isolated: an agent can never receive credentials it was not granted Proxy access to, even on a shared proxy.
The agent proxy is built for private-network deployment. A well-placed proxy looks like this:
Outbound, the proxy only needs to reach your Infisical instance and the APIs your proxied services define.
The security boundary of the agent proxy is identity, not certificates. Certificates only make TLS interception possible; what an agent can reach is decided entirely by machine identity permissions:
407) before anything else happens.Agents do not talk to the proxy directly; they are launched through infisical secrets agent-proxy connect -- <agent command>, which prepares the environment. Each proxied request carries the agent's Infisical token and folder scope in the standard proxy authorization mechanism, which is how the proxy knows which agent is asking and which folder's services apply.
A few connection-level behaviors to be aware of:
CONNECT tunnels; plain http:// traffic arrives as regular forward-proxy requests (useful for internal services without TLS). Requests for https:// URLs sent as plain forward-proxy requests are rejected so the proxy can never be used to downgrade TLS.NO_PROXY in the agent's environment always includes localhost,127.0.0.1, so local traffic bypasses the proxy. Additional bypass hosts can be added via the --no-proxy flag on connect or an existing NO_PROXY variable.For the proxy to read and modify HTTPS requests, agents must trust the certificates it presents. This is trust plumbing rather than access control: the chain exists so the proxy can open TLS traffic that agents deliberately send it, and holding a certificate grants no access to any secret. It has three tiers, and the sensitive part never leaves Infisical:
flowchart LR
A["Root CA
(in Infisical, per org)"] -->|signs| B["Intermediate CA
(in agent proxy memory)"]
B -->|signs| C["Leaf certificates
(one per hostname)"]
The root CA is generated automatically per organization and stored encrypted in Infisical; its private key never leaves the server, and all signing happens server-side. At startup, the proxy generates a keypair locally and has Infisical sign it into a short-lived intermediate certificate (7 days, re-signed automatically before expiry) that can mint leaf certificates but no further CAs. Leaf certificates (valid 24 hours, cached in memory) are minted locally per hostname, for the exact hostname the agent requested, with no Infisical round-trip.
On the agent machine, the connect wrapper downloads the root CA to ~/.infisical/agent-proxy/mitm-ca.pem and points the standard trust environment variables (SSL_CERT_FILE, NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, GIT_SSL_CAINFO, DENO_CERT) at it. The proxy's connection to the real service is standard HTTPS with normal certificate verification, so real credentials always travel encrypted.
Proxied services have their own project-level permission subject, with five actions:
| Action | What it allows |
|---|---|
| Read | View proxied services and their configuration |
| Create | Create new proxied services |
| Edit | Update a service's host patterns, secrets, or enabled state |
| Delete | Delete proxied services |
| Proxy | Route traffic through the service and have secrets applied |
Proxy is meant for agent machine identities: an identity with Proxy gets a service's secrets applied to its traffic without ever being able to read the values.
Grant each identity the minimum permissions it needs with a custom role or an additional privilege, scoped to the environments and paths its services live in. This is the minimum each identity needs:
| Identity | Minimum permissions | Notes |
|---|---|---|
| Agent | Proxy on Proxied Services, scoped to the environments and paths where its services live | This alone lets it route traffic and have credentials applied. It does not need to read any secret. Add Read Value on Secrets only for values the agent uses directly (not brokered ones). |
| Agent Proxy | Read Value and Describe Secret on Secrets, covering every secret the services reference | This is the identity that actually fetches the real values. Both actions are required: Describe Secret determines whether a secret is visible to the identity at all, and Read Value reveals its value. It needs no proxied-service permission. |
The key thing to get right for the agent proxy: it needs Read Value on every secret referenced by every service any of its agents use, across the relevant environments and paths. If a referenced secret comes from a secret import, the read permission has to cover the secret's real location (the import source), not just the folder it is imported into. If a grant is missing, that credential is skipped.
A machine identity is how Infisical knows who is asking and what they are allowed to access. So the number you need is not a technical limit; it follows from how you want access divided:
Sharing one identity between agents that need different access also works, but it means granting that identity the union of everything any of them needs: each agent then carries access it does not use, a compromised agent exposes the whole union, revoking the identity cuts off every agent at once, and audit logs cannot tell the agents apart.
The proxy keeps everything it needs in memory, so steady-state requests involve no Infisical calls:
--poll-interval), the proxy re-fetches services, permissions, and secret values for active agents. Changes such as a rotated secret, an edited service, or a revoked permission take effect within one poll interval, with no agent restart.--poll-interval, factor in your instance's API rate limits; a longer interval reduces load at the cost of slower propagation.When an agent requests a host no proxied service matches, the --unmatched-host flag decides what happens:
allow (default): the request is forwarded untouched, with no credentials applied. This is the normal mode, because much of an agent's traffic does not need a brokered credential at all: reading documentation, cloning public repos, installing packages, or calling services the agent legitimately authenticates to itself (for example, with a real secret in its environment because its identity has Read Value on it). All of that flows through untouched, while matched hosts still get credentials applied.block: the request is rejected with 403. Use this to restrict agents to an allowlist of exactly the services you have defined.Run multiple proxy instances with the same machine identity behind a TCP load balancer. Instances coordinate through Infisical rather than with each other: