# AI agent action gateway vs MITM proxy: control points

An AI agent action gateway and a man-in-the-middle proxy can both sit between an agent and an external service. That surface resemblance causes bad architecture decisions. One model executes an authenticated action on the agent's behalf while holding the credential. The other forwards or intercepts traffic that the agent has already decided to create.

The difference decides where you can say no, what the agent can steal, what an approval means, and whether your audit record describes a deliberate operation or a reconstructed packet flow. If the requirement is "the agent must never possess production credentials," a proxy is usually the wrong primary boundary. It may still have a job, but it cannot repair a secret that already lives in the client process.

## A gateway executes named actions while a proxy handles connections

An **AI agent action gateway** accepts a request to perform an external operation, selects a stored credential, executes the operation, and returns the result. The agent asks for work; it does not receive the bearer token, password, or private key needed to repeat that work elsewhere.

A forward proxy receives a network connection from a client and forwards it to a destination. The client still owns the request. For plain HTTP, the proxy can read the method, URL, headers, and body because the client sends HTTP to it. For HTTPS, the common case is a CONNECT tunnel: the proxy establishes a TCP connection to the target and relays encrypted bytes in both directions.

A MITM proxy changes the HTTPS case. It terminates the client's TLS connection, inspects or modifies the decrypted HTTP message, then creates a separate TLS connection to the upstream server. The client must trust a certificate authority controlled by the proxy, because the proxy presents a certificate for the destination host.

These models answer different questions:

- A proxy asks where traffic may go and, with interception, what traffic says.
- An action gateway asks whether it will carry out a specific authenticated operation.
- A proxy can add or remove material from a client-owned request.
- A gateway can keep the credential and construct the authenticated request itself.

That last point is not wording. It determines whether a compromised agent can take a credential and call the service from a different machine, at a different time, through a different route.

Consider an agent asked to create a deployment. In a proxy design, the agent commonly prepares `POST /deployments`, chooses the JSON body, and sends the request. The proxy may permit, deny, log, or inject an `Authorization` header. In an executor design, the agent calls an action such as `create_deployment` with arguments. The gateway resolves the configured destination and secret, performs the HTTP call, and returns the status and response body that the action allows it to return.

The executor still needs careful design. A carelessly defined generic action like "send arbitrary HTTP request" can recreate much of the proxy model. But the credential boundary remains different: the gateway possesses the credential and the agent does not.

## TLS turns inspection into a certificate authority problem

HTTPS traffic is not visible to an ordinary forward proxy merely because it passes through that proxy. This gets misstated often enough that teams build controls on an assumption that fails the first time a client uses CONNECT.

RFC 9110 describes CONNECT as a request to establish a tunnel to a target host and port. Once the tunnel is established, the proxy relays bytes. The TLS handshake happens inside that tunnel between the client and origin server. A proxy can record the target host, port, timing, byte counts, and connection outcome, but it cannot read `POST /v1/...` or an API key in an encrypted header.

To inspect HTTPS, an intercepting proxy must become the TLS endpoint for the client. TLS 1.3, specified in RFC 8446, requires the client to validate the certificate chain and hostname. A proxy can only satisfy that validation if the client trusts a certificate authority that can issue certificates for the sites being intercepted.

That requirement creates real operational work:

1. Install and protect a private CA on every machine or runtime that an agent uses.
2. Make language runtimes, package managers, command line tools, containers, and embedded clients trust it.
3. Handle clients that pin public certificates or use their own certificate store.
4. Protect decrypted request bodies and credentials after the proxy receives them.
5. Explain why a process designed to distrust unknown certificate issuers now trusts your interception CA.

This can be appropriate in a managed enterprise environment. It is not a small implementation detail. A proxy that decrypts all agent traffic becomes a high-value holder of every secret, request body, and response that crosses it.

A credential-holding executor does not need to impersonate every destination certificate to observe an operation. It acts as the HTTP client for the operation it owns. It creates a normal TLS connection to the destination, validates the destination's public certificate as any client should, and adds the stored credential at the moment of execution.

That does not remove TLS concerns. The gateway must validate certificates correctly and protect its secret store. It does remove the need to distribute a private interception CA to the agent process just to gain visibility into an action.

There is a useful test: if your design document says the proxy will inspect HTTPS requests, ask where the client trusts the interception CA. If nobody can answer that plainly, the proxy will only see tunnels, or the system will fail when a tool validates certificates correctly.

## Credential custody changes the damage a compromised agent can do

The useful security boundary is not "the agent made a network request through our box." It is whether the agent can obtain reusable authority.

Bearer tokens make this plain. An API server usually accepts a bearer token from any process that can reach it. If an agent receives the string, the agent can write it to a file, place it in tool output, transmit it to another endpoint, or use it after the approval session ends. Redacting logs after that event does not help. The credential has already left its intended boundary.

A proxy can reduce exposure if it injects the token itself. Yet the design still deserves scrutiny. The agent controls the request that reaches the proxy. Unless the proxy understands the API's semantics and enforces them reliably, the agent may use the injected token for any endpoint, method, or payload that the token permits.

For example, a proxy rule that says "inject this token for `api.example.internal`" gives the requesting process the token's effective authority across that host. The agent never sees the token string, but it can ask the proxy to perform destructive calls. That may be acceptable for a narrowly scoped service account. It is not the same control as allowing a named deployment action while refusing unrelated administrative endpoints.

An action gateway can bind a credential to the action path that uses it. The agent supplies arguments, not authorization material. The gateway can show a human the credential identity and intended operation before it creates the network request. It can also reject a request that does not fit the configured channel without attempting a connection.

The sharp distinction is between **secret non-disclosure** and **authority containment**.

Secret non-disclosure means the agent never sees raw credentials. A header-injecting proxy can provide this.

Authority containment means the agent cannot turn a permitted integration into a general-purpose authenticated transport. That takes action definitions, destination handling, argument validation, and controls applied before the side effect. A generic proxy does not automatically provide it.

SSH makes the issue harder to ignore. SSH public-key authentication proves that a client possesses the private key during the protocol exchange. If the agent has the private key, the agent can authenticate wherever that key is accepted. If the agent only has an SSH command routed through a gateway, the gateway or its helper must perform the authentication without exporting the key.

RFC 4253 describes the SSH transport protocol and the authentication architecture around it. The practical consequence is simple: you cannot safely "inject an SSH private key header" into a client request. Either the process holds signing authority, or another process performs the authenticated connection for it.

## Authorization must happen before the external side effect

A control point has value only if it acts before the thing you intend to control. Logging a request after an upstream server accepted it gives you evidence. It does not give you a veto.

MITM proxies often offer policy and approval systems based on request attributes: host, URL, method, headers, request body, client identity, or destination category. Those can be strong controls when the proxy sees decrypted traffic and understands the application's protocol. They also become a rules problem. Someone must decide whether `/projects/123/members` is safe, whether a JSON payload changes a harmless update into a privilege grant, and whether an encoded request bypasses a string match.

I have watched teams start with three proxy rules and end up maintaining an undocumented language of exceptions. The failure is not that rules are inherently bad. The failure is pretending that an agent's arbitrary request format has a stable, low-ambiguity policy surface.

An action gateway can use a smaller vocabulary. The authorization decision can refer to the calling process, the configured credential, the requested action, and the supplied arguments. A person does not need to inspect an opaque `curl` command and infer which stored secret will be attached downstream.

Sallyport takes this route with a fixed decision ladder instead of a policy language. Its locked vault denies every action. A new agent process needs session authorization by default, and the approval identifies the process's code-signing authority. Individual credentials can also require approval on every use. Those are deliberately coarse controls, but they occur before the app performs the HTTP or SSH action.

This approach has a limitation worth stating: a fixed approval model cannot express every organization's conditional rule. If you need a rule such as "permit writes only during a maintenance window when a ticket field has a given value," you need a system that can evaluate and maintain that rule. Do not disguise a simple action gateway as a general-purpose policy engine.

The payoff for keeping the control set small is that an operator can predict it. The vault is either locked or unlocked. A process run is either approved or not. A credential either asks each time or it does not. Security controls fail in practice when nobody can explain why a call passed.

## Request visibility and action authority are separate properties

Teams often demand "full visibility" when they actually need two different things: a record of which agent initiated work, and a record of each external action. Packet-level visibility can help with debugging, but it is a poor substitute for an action record.

A proxy log may contain source address, destination, TLS details, HTTP fields if interception succeeded, and raw bytes. That is useful forensic material. It also creates a messy identity problem. A connection tells you which process connected only if the environment supplies and preserves that identity. A request tells you what arrived at the proxy, not necessarily which model instruction or agent session caused it.

An action gateway starts with the operation boundary. It can record the agent run that requested the operation and the individual call it executed. Those records answer different questions:

- Which authorized agent process had an active session?
- Which external action did that session ask for?
- Which credential or channel did the executor use?
- What result came back, or where did the call fail?

Do not confuse an audit trail with an access control system. A detailed log will not stop an agent from deleting data if you granted that action. It can make later alteration detectable and make incident review much less dependent on a service's own database.

Sallyport projects its Sessions and Activity journals from one encrypted, hash-chained audit log. The `sp audit verify` command checks that chain offline over ciphertext and does not need a vault key. That design separates verification from the ability to decrypt secrets, which is the right split for an investigator who should validate history without gaining credential access.

A concrete verification workflow should have an output shape people recognize. For example:

```text
$ sp audit verify
Verifying audit chain...
Entries checked: 184
Chain status: valid
```

The exact number will vary. The useful property is that a changed, missing, or reordered record should make verification fail instead of quietly producing a shorter history. Keep a copy of the encrypted audit data outside the machine that produced it if you need protection against wholesale deletion. A hash chain detects tampering with records you retain; it cannot prove the existence of files an attacker destroyed along with the machine.

## HTTP and SSH expose different mediation limits

HTTP looks easy because it has headers, URLs, and verbs. That appearance can mislead teams into treating every integration as a header injection problem.

For an HTTP bearer-token API, the executor can keep a credential record that says how to authenticate and where it applies. When an agent requests an operation, the executor adds the bearer header itself. For a custom-header scheme, it adds the configured header without returning its value to the agent. Basic authentication follows the same custody rule, although the executor must treat the username and password as secrets rather than convenient configuration text.

The practical artifact is the division of inputs. The agent may provide request data such as this:

```json
{
  "method": "POST",
  "path": "/repos/acme/widget/deployments",
  "body": {
    "environment": "staging",
    "revision": "7d3c1a"
  }
}
```

The agent should not provide this:

```json
{
  "authorization": "Bearer token-value-goes-here"
}
```

That separation prevents the common failure where a tool schema advertises a secret field, the model places a value in it, and the value then appears in traces, terminal scrollback, test fixtures, or copied conversation text. Treating a token as a tool argument is a design error, even if the UI masks it after the call.

HTTP mediation still needs boundaries. If the gateway accepts arbitrary URLs, the agent can target internal services, cloud metadata endpoints, or unrelated hosts through a credentialed path. If it accepts arbitrary headers, the agent can attempt request smuggling or override authentication semantics. If it accepts arbitrary bodies, the gateway must accept that the API itself becomes the policy language.

SSH has different edges. An action may need to run a remote command, copy a file, or query a host. The gateway needs a destination and a private key it retains. A stateless helper can create the SSH connection and return standard output, standard error, and exit status without putting the key in the agent's environment.

The command boundary matters. A request such as:

```text
host: build-host
command: git rev-parse HEAD
```

has a narrower review surface than an agent running a local shell with access to `~/.ssh`, arbitrary proxy settings, and an unrestricted command line. It is still an authenticated remote command. If the credential can run `rm -rf` remotely, the gateway cannot make that safe by changing the transport. Limit the remote account's permissions and choose credentials for the jobs they actually perform.

A proxy can carry SSH over a TCP tunnel, but it cannot inspect the SSH command simply by routing port 22. To inspect SSH protocol content, it would need to act as an SSH endpoint and establish another SSH connection upstream, with all the host trust, authentication, recording, and compatibility obligations that follow. Calling that a proxy does not reduce the engineering work.

## A proxy remains useful when it owns the right layer

The argument against using a MITM proxy as an agent action gateway is not an argument against proxies. Proxies solve several problems well when they operate at the layer you actually need.

Use a forward proxy or egress gateway when you need to restrict which networks or hostnames a runtime may reach, force traffic through a known route, control outbound access from ordinary tools, or collect connection metadata. These controls can stop an agent from calling an unapproved host, even if that agent has no understanding of your action model.

Use a MITM proxy when you own the clients, can manage a trust CA, need to diagnose or enforce behavior across many conventional HTTP clients, and accept responsibility for handling decrypted traffic. Security test environments and managed device fleets often meet those conditions.

Use an action gateway when the requirement is tied to the identity and authority of an autonomous agent: the agent must request an external action, must not hold the credential, and must leave a reviewable record of the action that an executor performed.

Many serious deployments combine them. The agent runtime receives restricted outbound access so it cannot make arbitrary direct calls. The action gateway receives the narrow network access needed to reach approved external services. The gateway owns credentials and approvals. The network layer blocks escape routes.

Do not put all controls into the proxy because it is already in the network path. That choice often forces application-level authorization into URL patterns and pushes secret handling into an interception service built to relay traffic. It is popular because deployment diagrams look tidy. The operational boundary gets worse.

## A plausible proxy design fails at the handoff

Take a coding agent running in a development environment. It needs to query an issue tracker, create a deployment, and inspect a build host over SSH. A team installs an HTTPS proxy and configures environment variables such as these:

```text
HTTPS_PROXY=http://proxy.internal:8080
HTTP_PROXY=http://proxy.internal:8080
```

The proxy injects an API token for the issue tracker. The team considers the token protected because the agent never reads it from a configuration file.

The agent now sends a request to an administrative endpoint on the same host. The proxy sees a permitted hostname and injects the same token. If the rule does not understand endpoint semantics, it has just given the agent the token's full authority through an indirect interface.

The team tries to fix this with path allowlists. Soon they need exceptions for pagination, attachment upload endpoints, redirects, alternate API versions, and a workflow that includes a write followed by a read. The proxy is now carrying an application policy that changes whenever the service API changes.

Meanwhile, one tool does not honor `HTTPS_PROXY`. Another uses a private certificate store and fails TLS interception. A third is a container with a different CA bundle. Someone adds a bypass to keep work moving. The bypass produces the exact path that a prompt-injected agent or compromised dependency will choose later.

SSH arrives last and exposes the mismatch. The proxy cannot inject the SSH private key into a tunnel. The team mounts the key into the agent's environment "temporarily" or starts an agent process that can access a local SSH agent. At that point the system has lost the property it set out to preserve.

An action-execution design changes the handoff. The agent invokes an MCP tool through a local stdio connection. The executor owns the API credential or SSH key, makes the external connection, and returns the outcome. MCP transports the tool request; it does not grant the agent a free pass to secrets. The Model Context Protocol specification defines the tool interaction boundary, but credential custody remains the implementer's responsibility.

This design does not eliminate prompt injection. A malicious instruction can still persuade an agent to request a harmful action that it is allowed to request. It limits the failure to the authority the gateway exposes, gives the operator a point to approve or deny, and avoids turning every successful tool call into an opportunity to exfiltrate a reusable secret.

## Choose the architecture from the authority you refuse to hand over

Start with the sentence you need to make true. If it is "the process may reach only approved destinations," put a network control in the path. If it is "the process must never possess this API key or SSH private key," make another process execute the authenticated action. If it is "a human must approve each use of this credential," ensure the approval sits before the executor calls the remote service.

Then test the claim against bypasses. Can the agent read an environment variable with a token? Can it access a credential file, local SSH agent, browser session, cloud metadata service, or unrestricted outbound network? Can it ask a generic HTTP tool to call a different path with the same injected credential? Does a failing TLS interception setup cause an operator to disable certificate validation or create a direct route?

A useful short review has four questions:

1. Which process holds each secret in memory?
2. Which process creates the authenticated connection?
3. Where can a human deny the call before the remote service sees it?
4. Which record ties a particular agent run to the completed operation?

If the answer to the first two questions is "the agent," no proxy rule changes the basic risk. If the answer is "the proxy," decide whether you are prepared to operate TLS interception and application policy. If the answer is "a credential-holding executor," make sure it has a narrow action surface and that the agent cannot bypass it.

Sallyport is built for the last arrangement on macOS: its `sp mcp` shim lets MCP-capable agents request HTTP and SSH actions while the app retains the secrets and executes those actions. It is not a MITM proxy, and it should not be presented as one.

The first implementation task is usually unglamorous: remove direct credentials from the agent runtime. Until that is true, approvals and traffic logs are guardrails around a process that still carries the keys.
