{"id":"GHSA-39g5-644c-qwcg","summary":"container: pf Rule Injection via Domain Name Argument in `container system dns create --localhost` Command","details":"#### Product\n\nName: container\n\nGithub Link: https://github.com/apple/container\n\nVersion: \u003c= 0.12.2\n\n\n\n#### Summary\n\nThe `container system dns create --localhost` command accepts a `domainName` argument and passes it unsanitized into the pf anchor file (`/etc/pf.anchors/com.apple.container`) as a comment in a rule line. A domain name containing a newline character breaks out of the comment context and injects an arbitrary pf rule into the anchor file. When `pfctl -f` subsequently loads the configuration, the attacker-controlled rule is loaded into the macOS kernel packet filter.\n\nA `isValidDomainName()` function exists in `Parser.swift:892` but is **never called** from `DNSCreate`.\n\n**The core harm caused by this vulnerability is the bypassing of sudo privileges. An administrator may have only granted a user or an automation tool such as CI/CD the ability to execute `container system dns create` with root privileges, expecting that the user or automation tool could only add redirects from other IPs to localhost in the firewall rules file via `--localhost`. However, an attacker can exploit this vulnerability to write arbitrary rules into the firewall rules file: the target address is no longer restricted to localhost, and the rules are no longer limited to redirects.**\n\n#### Impact\n\n**What a legitimate invocation can write**\n\n`--localhost` is an optional parameter. Its presence or absence determines whether any pf rule is written at all:\n\n- **Without `--localhost`**: only a resolver config file is written; no pf rule is produced.\n- **With `--localhost \u003cIP\u003e`**: exactly one rule is written to the pf anchor file:\n\n```\nrdr inet from any to \u003cIP\u003e -\u003e 127.0.0.1 # \u003cdomain\u003e\n```\n\nThe redirect destination is hard-coded to `127.0.0.1`. The rule type is always `rdr inet`. There is no legitimate way to produce a rule that redirects traffic to any IP other than `127.0.0.1`, nor to produce `pass`, `block`, or `nat` rules, through normal command usage.\n\n**What injection additionally enables**\n\nThe injection lives in the domain name argument. `--localhost` must be supplied to trigger the `createRedirectRule()` code path — without it, no pf rule is written at all and the domain name never reaches the pf anchor file. However, the value passed to `--localhost` is unconstrained (only IP format is validated), so any valid IP suffices to open the injection path.\n\n```bash\nsudo container system dns create --localhost 127.0.0.1 \\\n  $'foo.local\\nrdr inet from any to 1.2.3.4 -\u003e 5.6.7.8'\n```\n\nThe `--localhost` value becomes the `from` IP in the legitimate rule. The injected content after the newline is an entirely independent pf directive with fully attacker-controlled `from` and `to` values.\n\nThe capability gap between normal use and injection is therefore:\n\n| | Normal use (no `--localhost`) | Normal use (with `--localhost`) | Injection (with `--localhost`, domain contains `\\n`) |\n|---|---|---|---|\n| Writes pf rule | No | Yes | Yes |\n| `from` IP | — | User-specified | Arbitrary |\n| `to` IP | — | Hard-coded `127.0.0.1` | **Arbitrary** |\n| Rule type | — | `rdr inet` only | Any (`pass`, `block`, `nat`, …) |\n\nThe single capability that injection uniquely adds is: **writing a pf rule with an arbitrary `to` IP** — redirecting traffic to any external host rather than being confined to `127.0.0.1`.\n\n**Primary scenario: sudo delegation bypass**\n\nThe most direct attack path requires only that an administrator grants a restricted user sudo access to this specific command:\n\n```\n# /etc/sudoers\nuser ALL=(root) NOPASSWD: /usr/bin/container system dns create *\n```\n\nThe administrator's intent is to allow `user` to manage DNS domains for container networking. Under normal usage this is bounded: even with `--localhost`, the command can only produce `rdr ... -\u003e 127.0.0.1` rules. Without `--localhost`, it produces no pf rules at all.\n\nWith the injection, the user provides any valid IP to `--localhost` to open the pf write path, then embeds the actual malicious rule in the domain name:\n\n```bash\nsudo container system dns create --localhost 127.0.0.1 \\\n  $'evil.local\\nrdr inet proto tcp from any to 10.0.0.1 -\u003e 203.0.113.1 port 4444'\n```\n\nThis is a classic sudo delegation bypass: the administrator delegated a scoped capability; the injection expands it to writing arbitrary kernel firewall rules.\n\n**Additional scenarios:**\n\n- An automated script or CI/CD pipeline that runs `sudo container system dns create $DOMAIN_FROM_ENV` where the environment variable originates from a container label, image metadata, or external API response — any newline in the upstream value triggers injection without any user action\n- A developer following documentation or a README that includes a crafted domain name example (social engineering)\n\n**Consequences of successful injection:**\n\n- pf redirect rules with arbitrary `from` and `to` IPs — enabling redirection of any host-level traffic to an attacker-controlled external address (not achievable through normal command use)\n- Additional rule types (`pass`, `block`, `nat`) with arbitrary port and protocol filters loaded into the kernel\n- Legitimate traffic selectively blocked (denial of service against specific endpoints)\n- Injected rules persist across DNS domain deletions — the `removeRedirectRule()` cleanup path cannot match and remove standalone injected lines\n\n\n#### Credit\n\nThis vulnerability was independently discovered and reported by multiple sources:\n\n- XlabAI Team of Tencent Xuanwu Lab\n- Atuin Automated Vulnerability Discovery Engine\n- Mohamed Abdelaal (@0xmrma)","modified":"2026-05-07T02:05:45.650008Z","published":"2026-05-07T01:43:31Z","database_specific":{"github_reviewed":true,"github_reviewed_at":"2026-05-07T01:43:31Z","nvd_published_at":null,"cwe_ids":["CWE-20"],"severity":"LOW"},"references":[{"type":"WEB","url":"https://github.com/apple/container/security/advisories/GHSA-39g5-644c-qwcg"},{"type":"PACKAGE","url":"https://github.com/apple/container"}],"affected":[{"package":{"name":"github.com/apple/container","ecosystem":"SwiftURL","purl":"pkg:swift/github.com/apple/container"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.12.3"}]}],"database_specific":{"last_known_affected_version_range":"\u003c= 0.12.2","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-39g5-644c-qwcg/GHSA-39g5-644c-qwcg.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P"}]}