$ table inet pipelock_containment { chain output_filter { type filter hook output priority filter; policy accept; # Loopback always accepted. This is what the agent uses to reach the proxy. meta oif "lo" accept ip daddr 127.0.0.0/8 accept # Operator UID stays normal. meta skuid 1000 accept # Proxy UID has internet because the proxy IS the exit. meta skuid 988 accept # Agent UID: DNS to loopback resolver, then drop everything. meta skuid 987 udp dport 53 ip daddr 127.0.0.0/8 accept meta skuid 987 tcp dport 53 ip daddr 127.0.0.0/8 accept meta skuid 987 drop }
}
table inet pipelock_containment { chain output_filter { type filter hook output priority filter; policy accept; # Loopback always accepted. This is what the agent uses to reach the proxy. meta oif "lo" accept ip daddr 127.0.0.0/8 accept # Operator UID stays normal. meta skuid 1000 accept # Proxy UID has internet because the proxy IS the exit. meta skuid 988 accept # Agent UID: DNS to loopback resolver, then drop everything. meta skuid 987 udp dport 53 ip daddr 127.0.0.0/8 accept meta skuid 987 tcp dport 53 ip daddr 127.0.0.0/8 accept meta skuid 987 drop }
}
table inet pipelock_containment { chain output_filter { type filter hook output priority filter; policy accept; # Loopback always accepted. This is what the agent uses to reach the proxy. meta oif "lo" accept ip daddr 127.0.0.0/8 accept # Operator UID stays normal. meta skuid 1000 accept # Proxy UID has internet because the proxy IS the exit. meta skuid 988 accept # Agent UID: DNS to loopback resolver, then drop everything. meta skuid 987 udp dport 53 ip daddr 127.0.0.0/8 accept meta skuid 987 tcp dport 53 ip daddr 127.0.0.0/8 accept meta skuid 987 drop }
}
#!/bin/bash
set -euo pipefail
TOOL="$1"; shift
exec -weight: 600;">sudo -u cc-agent -- env \ HOME=/home/cc-agent \ HTTPS_PROXY=http://127.0.0.1:8888 \ HTTP_PROXY=http://127.0.0.1:8888 \ NO_PROXY=127.0.0.1,localhost \ NODE_EXTRA_CA_CERTS=/etc/pipelock/ca.pem \ SSL_CERT_FILE=/etc/pipelock/combined-ca.pem \ REQUESTS_CA_BUNDLE=/etc/pipelock/combined-ca.pem \ CURL_CA_BUNDLE=/etc/pipelock/combined-ca.pem \ PATH=/home/cc-agent/.local/bin:/usr/local/bin:/usr/bin:/bin \ "$TOOL" "$@"
#!/bin/bash
set -euo pipefail
TOOL="$1"; shift
exec -weight: 600;">sudo -u cc-agent -- env \ HOME=/home/cc-agent \ HTTPS_PROXY=http://127.0.0.1:8888 \ HTTP_PROXY=http://127.0.0.1:8888 \ NO_PROXY=127.0.0.1,localhost \ NODE_EXTRA_CA_CERTS=/etc/pipelock/ca.pem \ SSL_CERT_FILE=/etc/pipelock/combined-ca.pem \ REQUESTS_CA_BUNDLE=/etc/pipelock/combined-ca.pem \ CURL_CA_BUNDLE=/etc/pipelock/combined-ca.pem \ PATH=/home/cc-agent/.local/bin:/usr/local/bin:/usr/bin:/bin \ "$TOOL" "$@"
#!/bin/bash
set -euo pipefail
TOOL="$1"; shift
exec -weight: 600;">sudo -u cc-agent -- env \ HOME=/home/cc-agent \ HTTPS_PROXY=http://127.0.0.1:8888 \ HTTP_PROXY=http://127.0.0.1:8888 \ NO_PROXY=127.0.0.1,localhost \ NODE_EXTRA_CA_CERTS=/etc/pipelock/ca.pem \ SSL_CERT_FILE=/etc/pipelock/combined-ca.pem \ REQUESTS_CA_BUNDLE=/etc/pipelock/combined-ca.pem \ CURL_CA_BUNDLE=/etc/pipelock/combined-ca.pem \ PATH=/home/cc-agent/.local/bin:/usr/local/bin:/usr/bin:/bin \ "$TOOL" "$@"
#!/bin/bash
exec /usr/local/bin/cc-launch claude "$@"
#!/bin/bash
exec /usr/local/bin/cc-launch claude "$@"
#!/bin/bash
exec /usr/local/bin/cc-launch claude "$@"
operator ALL=(cc-agent) NOPASSWD: /usr/local/bin/cc-launch *
operator ALL=(cc-agent) NOPASSWD: /usr/local/bin/cc-launch *
operator ALL=(cc-agent) NOPASSWD: /usr/local/bin/cc-launch *
# 1. Operator still has internet.
-weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ # 2. Proxy UID still has internet.
-weight: 600;">sudo -u pipelock-proxy -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ # 3. Agent UID cannot dial direct.
-weight: 600;">sudo -u cc-agent -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' \ --max-time 5 https://example.com/ 2>&1 \ | grep -E '000|Connection refused|Network is unreachable' # 4. Agent UID can reach the internet through the proxy.
-weight: 600;">sudo -u cc-agent -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' \ -x http://127.0.0.1:8888 https://example.com/ # 5. The wrapper end-to-end.
cc-launch -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
# 1. Operator still has internet.
-weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ # 2. Proxy UID still has internet.
-weight: 600;">sudo -u pipelock-proxy -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ # 3. Agent UID cannot dial direct.
-weight: 600;">sudo -u cc-agent -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' \ --max-time 5 https://example.com/ 2>&1 \ | grep -E '000|Connection refused|Network is unreachable' # 4. Agent UID can reach the internet through the proxy.
-weight: 600;">sudo -u cc-agent -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' \ -x http://127.0.0.1:8888 https://example.com/ # 5. The wrapper end-to-end.
cc-launch -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
# 1. Operator still has internet.
-weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ # 2. Proxy UID still has internet.
-weight: 600;">sudo -u pipelock-proxy -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ # 3. Agent UID cannot dial direct.
-weight: 600;">sudo -u cc-agent -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' \ --max-time 5 https://example.com/ 2>&1 \ | grep -E '000|Connection refused|Network is unreachable' # 4. Agent UID can reach the internet through the proxy.
-weight: 600;">sudo -u cc-agent -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' \ -x http://127.0.0.1:8888 https://example.com/ # 5. The wrapper end-to-end.
cc-launch -weight: 500;">curl -s -o /dev/null -w '%{http_code}\n' https://example.com/ - operator: the human at the keyboard. Browser, terminal, -weight: 500;">git, -weight: 500;">kubectl. Normal egress.
- pipelock-proxy: the proxy daemon. Runs the agent firewall. Has internet because that is its job.
- cc-agent: every agent process. Coding CLI, AI assistant, browser driver, screenshot tool. Has loopback only. - NODE_EXTRA_CA_CERTS for Node.js and anything that uses tls.createSecureContext.
- SSL_CERT_FILE for OpenSSL-linked clients.
- REQUESTS_CA_BUNDLE for Python requests.
- CURL_CA_BUNDLE for -weight: 500;">curl. - Disable the system pipelock unit, re--weight: 500;">enable the user-mode unit.
- Delete the nftables table and -weight: 500;">remove the rule file.
- Remove the wrappers and the sudoers carve-out.
- Optionally -weight: 500;">remove the system users.