{"slug": "show-hn-egress-waf-to-limit-ai-agents-and-npm-malware-based-on-mitmproxy", "title": "Show HN: Egress WAF to limit AI agents and NPM malware based on mitmproxy", "summary": "A developer released mitmwall, an egress Web Application Firewall for Ubuntu that uses iptables and mitmproxy to block all outbound HTTP(S) traffic except explicitly allowed routes. The tool prevents data exfiltration from compromised npm, PyPI, and Cargo packages, as well as backdoor connections from malware and rogue AI agents, by enforcing an allowlist-based network policy. Mitmwall runs as a systemd service with a transparent proxy, DNS proxy, and real-time monitoring interface, and fails closed if its rule configuration is missing or invalid.", "body_md": "mitmwall is an egress Web Application Firewall (WAF) for Ubuntu. It combines\n`iptables`\n\nwith [mitmproxy](https://mitmproxy.org/) to ensure that only\nexplicitly allowed HTTP(s) routes can be reached. Any network connection that\ndoes not match the allowlist is blocked. This prevents:\n\n**Data exfiltration**— compromised npm/pypi/cargo etc. packages, rogue AI agents, or other untrusted processes stealing credentials, API keys, or source code.**Backdoor connections**— malware phoning home to command-and-control servers.\n\nThe built-in mitmweb interface can be used to monitor all proxied traffic in real time.\n\nRead this blog post for background [Protecting against npm and AI agents](https://esamattisnotes.wordpress.com/2026/05/31/protecting-against-npm-and-ai-agents/)\n\nThe name is a wordplay for mitmproxy + firewall = mitmwall.\n\n- systemd\n`mitmwall.service`\n\nstarts`mitmweb`\n\nin transparent HTTP(S) proxy mode and DNS proxy mode. `ExecStartPre`\n\ninstalls`iptables`\n\n/`ip6tables`\n\nrules that:- redirect outbound TCP port\n`80`\n\nand`443`\n\ntraffic to the HTTP(S) proxy - redirect outbound TCP/UDP port\n`53`\n\ntraffic to the DNS proxy- only allow root, the dedicated\n`mitmwall`\n\nuser,`systemd-resolve`\n\n, and installed time-sync service users to make required upstream connections- the proxy is running as the\n`mitmwall`\n\nuser - root is left unrestricted for host administration and troubleshooting\n`systemd-resolve`\n\nis left able to perform resolver recursion without looping back into the DNS proxy- installed time-sync service users such as\n`systemd-timesync`\n\n,`_chrony`\n\n, or`ntp`\n\nare left able to perform NTP synchronization on UDP/123 and direct DNS queries on UDP/TCP 53\n\n- the proxy is running as the\n\n- only allow root, the dedicated\n- drop other new outbound traffic so applications cannot bypass the proxies\n\n- redirect outbound TCP port\n- The mitmproxy addon in\n`src/addon`\n\nloads TOML files from`/etc/mitmwall/rules.d`\n\nand:- kills HTTP(S) flows whose host, method, and pathname do not match the allowlist\n- refuses DNS queries whose hostname does not match any allow rule\n\n`ExecStopPost`\n\nremoves the firewall rules when the service stops.\n\nIf `/etc/mitmwall/rules.d`\n\nis missing or any rule file is invalid, mitmwall\nfails closed and blocks all proxied HTTP(S) traffic and DNS resolution.\n\nYou should also read the [How mitmproxy works](https://docs.mitmproxy.org/stable/concepts/how-mitmproxy-works/) -article.\n\nRun on the Ubuntu server as a sudo-capable user:\n\n```\nsudo bash -c \"$(curl -fsSL https://raw.githubusercontent.com/esamattis/mitmwall/main/web-install.sh)\"\n```\n\nOr, from a local checkout:\n\n```\nsudo ./install.sh\n```\n\nThe installer creates a `mitmwall`\n\nsystem user, installs mitmproxy under\n`/opt/mitmwall`\n\n, creates `/etc/mitmwall/config.toml`\n\nand `/etc/mitmwall/rules.d`\n\n,\ninstalls the systemd service, generates the mitmproxy CA, and adds the CA to\nthe system trust store with `update-ca-certificates`\n\n.\n\nThe scripts can be also used for upgrading mitmwall.\n\nEnable at boot and start immediately:\n\n```\nsudo systemctl enable --now mitmwall\n```\n\nRestart after changing rules:\n\n```\nsudo systemctl restart mitmwall\n```\n\nStop mitmwall and remove its iptables/ip6tables rules:\n\n```\nsudo systemctl stop mitmwall\n```\n\nStart again with\n\n```\nsudo systemctl start mitmwall\n```\n\nView logs:\n\n```\nsudo journalctl -u mitmwall.service -f\n```\n\nRules are stored as TOML files in `/etc/mitmwall/rules.d`\n\n. Each `*.toml`\n\nfile\ncan contain zero or more `[[allow]]`\n\ntables. Traffic is blocked unless the\nrequest hostname, HTTP method, and optional pathname filter match at least one\nallow rule. Files are loaded in alphabetical filename order.\n\nThe [example-rules.toml](/esamattis/mitmwall/blob/main/example-rules.toml) file in this repository is\ninstalled to `/etc/mitmwall/rules.d/5-examples.toml`\n\n. It contains a fully\ncommented reference covering syntax, constraints, matching behavior, and\nexamples.\n\nAfter editing files in `/etc/mitmwall/rules.d`\n\n, restart the service:\n\n```\nsudo systemctl restart mitmwall\n```\n\n`inject_headers`\n\ncan add custom headers to requests, which can be used to\ntransparently supply credentials. This can be a powerful way to avoid exposing\ncredentials to untrusted users. A typical workflow is to first configure the\ntools that require the credentials, inspect in mitmweb how the credentials are\nused, write a matching rule that injects the credential headers, and finally\nreplace the real credentials with dummy values so the tool still thinks\ncredentials are configured. Credential injection also prevents\nmalware from using their own credentials.\n\nThe installer reads the plain env file [ system_enviroment](/esamattis/mitmwall/blob/main/system_enviroment)\nto build the mitmwall-managed CA environment block written to\n\n`/etc/environment`\n\n.\nThese variables point common runtimes and TLS libraries at the mitmproxy CA\ncertificate or the rebuilt system CA bundle so HTTPS clients can trust\ncertificates generated while mitmwall is intercepting traffic. The values apply\nto new login sessions after installation.Settings are stored in `/etc/mitmwall/config.toml`\n\n. The installer creates this\nfile if it does not already exist. See the [default config](/esamattis/mitmwall/blob/main/config-default.toml) for\nthe available settings.\n\nRestart the service after changing addon configuration:\n\n```\nsudo systemctl restart mitmwall\n```\n\nThe `mitmweb`\n\nweb interface can be used to inspect traffic, which makes it\neasier to create accurate rules. Rules added through the options interface are\napplied immediately without a service reload and are persisted to\n`/etc/mitmwall/rules.d/2-web.toml`\n\n- mitmweb listens on port\n`58081`\n\n. - The password can be viewed as an administrator from the generated mitmweb config:\n\n```\nsudo grep '^web_password:' /opt/mitmwall/mitmweb/config.yaml\n```\n\nmitmwall runs mitmproxy in both transparent HTTP(S) mode and DNS mode. The\nfirewall redirects ordinary users' TCP/UDP port 53 traffic, including attempts to\nquery local resolvers such as `127.0.0.53`\n\nor public resolvers such as `1.1.1.1`\n\n,\nto mitmproxy's local DNS listener. Root, the `mitmwall`\n\nproxy user, and the\n`systemd-resolve`\n\nuser are excluded so administration, proxy upstream lookups,\nand system resolver recursion do not loop back into the proxy.\n\nBy default, the mitmproxy addon applies the same rule files in\n`/etc/mitmwall/rules.d`\n\nto DNS queries before forwarding them upstream. DNS\npolicy is hostname-only: `domain`\n\n, `domain_regex`\n\n, and `include_subdomains`\n\ndecide whether a query may be resolved, while HTTP-specific filters such as\n`methods`\n\n, `pathname_pattern`\n\n, `pathname_regex`\n\n, and `inject_headers`\n\nstill\napply only to web requests. Queries for the machine's local hostname are also\nallowed. Other queries that do not match any allow rule are answered with DNS\n`REFUSED`\n\nand are not resolved upstream.\n\nSet `block_dns = false`\n\nin `/etc/mitmwall/config.toml`\n\nto disable addon-level DNS\nfiltering and pass through all DNS queries. This does not change the firewall\nredirection rules.\n\nWell, first of, AI agents helped creating this. So there is that 😅\n\nThe security model relies on Linux user permissions: Only root and the\n`mitmwall`\n\nuser can access the network freely. Root is intentionally exempt so\nadministrators can manage and troubleshoot the host without going through the\nproxy. So if the attacker can do privilege escalation:\n\n- to the\n`mitmwall`\n\nuser they can access the network - to root they can access the network and can just stop the service\n\nDNS filtering closes the obvious DNS-based exfiltration path where a process\nencodes data into lookup names, for example `secret-token.attacker.example`\n\n, and\nrelies on the normal DNS resolution path to reveal that full query to an\nattacker-controlled authoritative nameserver. Because mitmwall refuses names\noutside the configured allowlist before resolving them, those synthetic\nexfiltration domains are never sent upstream.\n\nAllowed domains should still be chosen carefully: if an attacker can control a\nsubdomain under an allowed rule, or if a broad `domain_regex`\n\nallows untrusted\nnames, DNS can still be used as a data channel within that allowed namespace.\n\nAllowed domains can still be used for credentials dumping, especially when a\nrule allows write-capable methods such as `POST`\n\n, `PUT`\n\n, or `PATCH`\n\n, or uses\n`methods = \"ANY\"`\n\n. For example, if `github.com`\n\nis allowed with a method that\ncan create or update content, malware could post secrets to an\nattacker-controlled issue, gist, repository, or workflow log without violating\nthe hostname and method allowlist.\n\nThe default method policy only allows `GET`\n\nand `HEAD`\n\n, which blocks many common\nwrite paths. When a write-capable method is needed, prefer narrowing the rule\nwith `pathname_pattern`\n\nor `pathname_regex`\n\ninstead of allowing the whole domain.\nFor example, a GitHub rule can allow only the repository path needed for a Git\noperation rather than every issue, gist, repository, or workflow endpoint on the\nhost.\n\nPathname filters reduce accidental exfiltration risk, but they do not make an allowed domain safe: secrets may still be leaked through URLs, query strings, headers, or any endpoint where an allowed method causes data to leave the host.\n\nRegular non-root processes on Ubuntu do not have `CAP_NET_RAW`\n\n, so they cannot\ncreate raw sockets that would bypass iptables. Only root and processes explicitly\ngranted this capability (for example via `setcap`\n\n) can craft packets that skip\nthe firewall rules. This makes raw socket-based circumvention impractical for\nthe threat model mitmwall targets.\n\nBut the idea is not to protect from targeted attacks, but from rogue AI agents gone mad and from general credentials dumping malware as seen on the npm registry lately.", "url": "https://wpnews.pro/news/show-hn-egress-waf-to-limit-ai-agents-and-npm-malware-based-on-mitmproxy", "canonical_source": "https://github.com/esamattis/mitmwall", "published_at": "2026-05-31 09:52:23+00:00", "updated_at": "2026-05-31 10:16:23.420250+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-infrastructure", "ai-tools", "ai-products"], "entities": ["mitmproxy", "mitmwall", "Ubuntu", "npm", "pypi", "cargo", "systemd", "mitmweb"], "alternates": {"html": "https://wpnews.pro/news/show-hn-egress-waf-to-limit-ai-agents-and-npm-malware-based-on-mitmproxy", "markdown": "https://wpnews.pro/news/show-hn-egress-waf-to-limit-ai-agents-and-npm-malware-based-on-mitmproxy.md", "text": "https://wpnews.pro/news/show-hn-egress-waf-to-limit-ai-agents-and-npm-malware-based-on-mitmproxy.txt", "jsonld": "https://wpnews.pro/news/show-hn-egress-waf-to-limit-ai-agents-and-npm-malware-based-on-mitmproxy.jsonld"}}