Airlock can restrict MCP token traffic to a set of IP ranges. A bearer token presented from outside its configured allowlist is rejected before any tool call executes, every denial is auditable, and the rejection is opaque to the caller so denied requests can't learn anything about the policy.
Where allowlists live
Allowlists are layered. A request must pass every applicable layer to proceed.
| Layer | Where to configure | Applies to |
|---|---|---|
| Organization | Settings → Security → Network access | Every MCP token in the org (service account tokens, future user tokens) |
| Service account | Service accounts → [account] → Network access | Any token bound to that service account |
An empty (or missing) allowlist at a layer means "no restriction at this level" — the next layer's restriction (if any) still applies. Setting an org-level allowlist therefore restricts every token in the org; setting a service-account-level allowlist restricts only that account's tokens.
CIDR format reference
Each entry is a CIDR — bare IPs are not accepted at the API layer. Examples:
| Notation | Meaning |
|---|---|
203.0.113.42/32 | One specific IPv4 address |
203.0.113.0/24 | The 256-address IPv4 range 203.0.113.0–203.0.113.255 |
10.0.0.0/8 | Private RFC 1918 range |
::1/128 | One specific IPv6 address (loopback) |
2001:db8::/32 | An IPv6 prefix |
0.0.0.0/0 | Every IPv4 address (IPv4-only — does not match IPv6 clients) |
::/0 | Every IPv6 address (IPv6-only — does not match IPv4 clients) |
To allow both IPv4 and IPv6 traffic, include both 0.0.0.0/0 and ::/0. In practice, "allow everything" is the same as having no restriction at all — leave the list empty instead.
CIDRs are stored in canonical form, so 2001:DB8::/32 is rewritten to 2001:db8::/32 on save.
IPv4-mapped-IPv6 note. Some hosts emit IPv4 connections as ::ffff:192.0.2.1. Airlock unwraps that form before evaluation, so an IPv4 CIDR like 192.0.2.0/24 covers both the bare IPv4 address and the IPv4-mapped IPv6 representation. You do not need to enumerate both.
Layered evaluation
For every incoming MCP request:
- Airlock resolves the source IP (see "
X-Forwarded-Forhandling" below). - If the organization has an allowlist and the source IP is not in it → reject with HTTP 403.
- If the service account has an allowlist and the source IP is not in it → reject with HTTP 403.
- Otherwise the request proceeds to the policy engine.
Rejections never echo the source IP back to the caller, so a denied client cannot learn what address it was seen from. The full denial — IP, reason, entity, timestamp — is recorded in the audit log instead.
Bulk paste
The chip-input UI accepts a comma- or newline-separated list, splits it into chips, validates each, trims whitespace, drops empties, and dedupes. Invalid entries surface as red chips so you can fix them in place; the form blocks save until every chip is valid.
If you paste more than 50 entries (the cap), Airlock accepts the first 50 and shows "X entries dropped (cap is 50)". If you need to cover more addresses than fit, use a broader CIDR — for example 203.0.113.0/24 instead of 256 separate /32 entries.
Test against my current IP
The editor has a "Test my current IP" button that resolves your current public IP and checks it against the pending (unsaved) chip list. Use this before saving to confirm the configuration covers your own connection.
Self-lockout safeguard
When you click Save on a non-empty allowlist, Airlock resolves your current public IP and checks it against the proposed list. If your IP is not covered, you see this modal:
Your current IP is not in this allowlist. You will lose access from this connection after save. If you're configuring from a jump host or VPN, this is expected. [Cancel] [Continue and save]
The modal is the only path to save in this state. The intent is that a jump-host admin (who deliberately isn't in the allowlist that covers production hosts) sees the warning, confirms, and continues.
Recovery path. If you save an allowlist that locks every admin out of the Control Room UI, you can still sign in (Control Room sign-in is governed by Cognito, not the MCP IP allowlist) and edit the list back. The lockout only affects MCP token traffic — Control Room access for admins is unaffected.
X-Forwarded-For handling
By default, Airlock does not trust X-Forwarded-For. The source IP comes from the transport (API Gateway's request context) so a caller cannot spoof their address by setting headers.
If Airlock runs behind a trusted reverse proxy, an operator can opt in by setting the TRUSTED_PROXY_CIDRS environment variable on the MCP handler to one or more CIDR ranges. When set, and only when the immediate hop matches one of those CIDRs, Airlock walks X-Forwarded-For right-to-left and uses the first entry that isn't itself a trusted proxy.
Setting this incorrectly would let any caller spoof an arbitrary IP, so leave the env var unset unless you control the proxy in front of Airlock.
Operational visibility
The Security → Blocks page includes a "Recent IP allowlist denials" widget that lists the 20 most recent denied requests with the source IP, reason (org vs entity), entity type, and timestamp. Use this to spot NAT rotations or misconfigured allowlists without trawling the audit log by hand.
For a deeper forensic view, the standard audit-log page accepts an IP_ALLOWLIST_DENIED action filter that returns the full event payload, including the resolutionMethod (requestContext.http.sourceIp vs x-forwarded-for) so you can verify how the source IP was determined for any given denial.
Limits
- Maximum 50 entries per allowlist (per organization, per service account). Prefer broader CIDRs over enumerating individual addresses.
- Both IPv4 and IPv6 are supported, including mixed-family allowlists on the same entity.
- Canonical storage means duplicates that differ only in case (
2001:DB8::/32vs2001:db8::/32) are silently deduped on save.