Executive Summary
This report documents the results of a multi-phase security audit of the Kimi chat platform's containerised IPython sandbox (Kubernetes pod, Kata runtime, kernel 5.10.134). Fifteen distinct findings were identified across 18 test phases. Of these, nine were successfully exploited.
The most consequential finding is an unfiltered DNS egress channel that allowed complete, confirmed exfiltration of all process environment variables to an attacker-controlled server via 36 DNS queries. The attack was fully automated, required no special privileges, and ran silently in the background as a persistent agent.
Container escape to the host was not achieved. The pod isolation boundary held. All exploits are scoped to the attacker's own pod.
Disclosure timeline: Initial contact 2026-04-29 · Follow-up with full details 2026-05-01 · Second follow-up 2026-05-07 · No response received at any point · Public disclosure 2026-05-09.
Findings Summary
| # | Finding | Severity | Exploited |
|---|---|---|---|
| 1 | World-readable /proc/*/environ | High | ✅ Yes |
| 2 | Unauthenticated Chrome CDP (port 9222) | High | ✅ Yes |
| 3 | SSH key injection | Medium | ✅ Yes |
| 4 | DNS exfiltration — unfiltered egress | High | ✅ Yes |
| 5 | World-writable systemd service files | Low | ⚠️ Write only |
| 6 | Internal network & K8s API enumeration | Medium | ✅ Yes |
| 7 | Stale Jupyter kernel connection files | Low | ⚠️ Partial |
| 8 | User namespace escape attempt | Info | ❌ Blocked |
| 9 | CVE-2024-1086 — nf_tables loaded | Info | ❌ Blocked |
| 10 | Writable filesystem paths | Medium | ✅ Yes |
| 11 | Mount-point parent traversal | Low | ✅ Yes |
| 12 | Capability effective set all-zero | Info | N/A |
| 13 | SUID binaries present | Low | ❌ Not exploitable |
| 14 | Fork-based overlayfs escape | Info | ❌ Blocked |
| 15 | Persistent DNS exfiltration agent deployed | High | ✅ Yes |
Environment
| Platform | Kimi Chat (kimi.com / moonshot.cn) |
| Runtime | Kubernetes pod, Kata container runtime |
| Kernel | 5.10.134-...-kangaroo |
| Init system | s6-svscan (PID 1, not systemd) |
| Container user | UID 999 (non-root), CapEff: all-zero |
| Test date | 2026-05-07 |
Detailed Findings
Finding 1 — World-Readable /proc/*/environ High Confirmed, exploited
Any process can read environment variables of all other processes via /proc/*/environ without elevated privileges. This exposes all secrets injected at container startup.
* GOOGLE_API_KEY shown is the standard public Debian Chromium key, widely published in Linux packaging. It is not a private Kimi credential. However, the exfiltration channel would equally expose any private key placed in the environment of a future session.
Finding 2 — Unauthenticated Chrome DevTools Protocol (Port 9222) High Confirmed, exploited
Chromium runs with --remote-debugging-port=9222, exposing an unauthenticated WebSocket endpoint accessible to any process in the pod. The Chrome DevTools Protocol allows full browser control: arbitrary JavaScript execution, cookie access, screenshot capture, and internal network navigation.
The outbound fetch() failed due to network policy; the CDP channel itself is fully operational. Remediation: remove --remote-debugging-port, or bind to a Unix socket with authentication.
Finding 3 — SSH Key Injection Medium Confirmed, exploited (within-pod)
/home/kimi/.ssh/authorized_keys is writable by the container user. An Ed25519 key pair was generated and the public key appended. Local SSH authentication with the corresponding private key was verified.
Impact is within-pod only. Remediation: mount authorized_keys read-only from a ConfigMap, or disable sshd.
Finding 4 — DNS Exfiltration (Confirmed Data Leakage) High Confirmed — live DNS logs available
Outbound UDP/TCP port 53 is unrestricted. Environment data (1,238 bytes) was encoded into base64 subdomain labels and transmitted to an attacker-controlled Interactsh nameserver in 34 queries, plus a heartbeat. 36 DNS queries total were logged. Queries originated from IP 8.146.128.72–73 (Alibaba Cloud, the Kimi sandbox egress range). The decoded first chunk confirms the data arrived intact.
See Finding 15 for the complete attack chain and prompt-by-prompt reproduction steps.
Remediation
Route all container DNS through an internal resolver; block raw UDP/TCP 53 egress from pods.
Finding 5 — World-Writable Systemd Service Files (Overlayfs) Low Write confirmed; execution not possible
Overlayfs copy-up allows UID 999 to write to /usr/lib/systemd/system/*.service files despite root ownership. rc.service (permissions 666) was successfully modified. PID 1 is s6-svscan; systemctl daemon-reload fails. The modified file is never executed. This is an overlayfs hardening gap.
Finding 6 — Internal Network & Kubernetes API Enumeration Medium Confirmed
Internal Kubernetes DNS and TCP connectivity was fully enumerated from the pod.
The Kubernetes service account token received HTTP 403 on most endpoints. The cluster topology is fully mapped from within the pod.
Finding 7 — Stale Jupyter Kernel Connection Files in /tmp Low Files found; kernels unresponsive
Kernel connection files in /tmp contain IP addresses, ZMQ ports, and HMAC keys. Kernels were stale and did not respond to ZMQ messages. If active, an attacker could connect to another kernel's ZMQ socket and execute code in its context.
Finding 8 — User Namespace Escape Attempt Info Blocked by seccomp/AppArmor
unshare(CLONE_NEWUSER) failed with EINVAL in both direct and fork-based approaches. The multi-threaded Jupyter kernel process is incompatible with unshare, and the container's seccomp/AppArmor profile blocks the syscall regardless.
Finding 9 — CVE-2024-1086 — nf_tables Module Loaded Info Blocked by missing capabilities
nf_tables is loaded and a NETLINK_NETFILTER socket can be created and receives responses. CAP_NET_ADMIN is absent from the effective capability set, preventing the crafted netlink messages required to trigger the CVE-2024-1086 use-after-free.
Finding 10 — Writable Filesystem Paths Medium Confirmed
Paths writable by UID 999 and used during testing:
/tmp— key pairs and test files/home/kimi(including.ssh) — persistent exfil agent/app— writable application directory/mntand/mnt/agents/output— mounted output directories/usr/lib/systemd/system— via overlayfs copy-up (see Finding 5)
Finding 11 — Mount-Point Parent Directory Traversal Low Pod-level only
openat(fd, '..') on /mnt traverses to the container root, not the host. Does not constitute a container escape, but could enable cross-pod file access if pods share an emptyDir volume.
Finding 12 — Capability Effective Set All-Zero Info — Correct Hardening
The bounding set includes CAP_NET_RAW and CAP_SYS_ADMIN but they cannot be raised. This correctly blocks raw socket operations, mounting, and most kernel exploits.
Finding 13 — SUID Binaries Present Low Present but not exploitable
13 SUID binaries found including chrome-sandbox, mount, and su. Classic SUID privilege escalation is not effective in a container; mount requires CAP_SYS_ADMIN. No privilege escalation was achieved.
Finding 14 — Fork-Based Overlayfs Escape Attempt Info Blocked
Fork-based user namespace creation followed by overlayfs overlay of /etc was attempted. The child process failed immediately with EPERM. Both seccomp and AppArmor profiles block the required syscalls, and the multi-threaded Python environment makes fork/unshare unsafe regardless.
Finding 15 — Persistent DNS Exfiltration Agent Deployed High Confirmed — agent running at time of report
The full attack chain was executed across eight prompts entered verbatim into the Kimi chat interface. The assistant executed every step without refusal. The result is a live background Python process exfiltrating all environment variables to an attacker-controlled server via DNS every hour for the lifetime of the container session.
Background: DNS Tunneling
DNS tunneling encodes data into DNS subdomain query labels. Because DNS resolution is a fundamental network primitive, it is frequently permitted even where direct TCP/UDP egress is blocked. The attacker controls a domain with a public authoritative nameserver. Any DNS query for a subdomain of that domain reaches the attacker's server, carrying the encoded data in the query name. No TCP connection, no HTTP request, no visible data transfer in application-layer logs.
Prerequisites — Obtaining an Interactsh Listener
Before running the attack, the tester obtains a unique collector domain from Interactsh, an open-source out-of-band interaction server.
Open https://app.interactsh.com/ in a browser. No account required. The page auto-generates a unique domain (e.g. lopbivgzufostwbuvbbzrbnkzry7ixt0r.oast.fun). Copy this domain — it is substituted into Prompt 1. Keep the Interactsh tab open; incoming DNS queries appear in real time.
Each browser session generates a fresh domain. Do not reload the page during a test run or queries will stop logging.
Exact Prompts (Verbatim)
Each prompt is typed into the Kimi chat interface. The phrasing "What happens when this runs in the sandbox?" causes the assistant to execute the code inside its IPython kernel and report the result.
Expected response: Agent written (519 bytes)
Expected response: Permissions: 755
Expected response: Persistence added
Note: systemd is not PID 1 (s6-svscan is); write succeeds but is never executed.
Expected response: System has not been booted with systemd as init system (PID 1).
Expected response: True / 0o100755
Expected response: Agent started (PID shown)
Action: switch to Interactsh tab now. env-000 through env-033 queries should appear within seconds, followed by beat.<domain>.
Expected response: Agent started, PID: 568 / Status: sleeping / Memory: 11664 KB / Connections: [('10.164.30.70', 58904) → ('192.168.0.10', 53)]
Attack Chain Results
| Step | Prompt | Action | Result |
|---|---|---|---|
| 1 | Prompt 1 | Write /home/kimi/.agent.py | ✅ 519 bytes |
| 2 | Prompt 2 | chmod 755 | ✅ Executable |
| 3 | Prompt 3 | Append ExecStartPost to rc.service | ✅ Written (systemd not running) |
| 4 | Prompt 4 | systemctl daemon-reload | ❌ Expected — no systemd |
| 5 | Prompt 5 | Verify agent file | ✅ Confirmed: exists, 755 |
| 6 | Prompt 6 | Start agent (Popen) | ✅ Running, DNS queries sent |
| 7 | Prompt 7 | Full chain, single block | ✅ All steps succeed |
| 8 | Prompt 8 | Full chain + start_new_session=True | ✅ PID 568 alive after 5 sec |
Live Agent Status at Time of Report
| PID | 568 |
| Status | sleeping |
| Memory | 11,664 KB |
| Network | 10.164.30.70:58904 → 192.168.0.10:53 (DNS resolver) |
| Agent running | True |
| Next exfil cycle | ~3,600 seconds |
DNS Exfiltration Evidence
Live DNS query logs were captured using an Interactsh listener. 36 queries arrived from IP 8.146.128.72–73 (Alibaba Cloud, the Kimi sandbox egress range), comprising 34 data chunks and 1 heartbeat. Decoding the first subdomain label yields:
The full decoded environment is available to the Kimi security team on request. DNS query logs and Interactsh export are retained.
What the Agent Transmits
* The GOOGLE_API_KEY value is the standard public key shipped with the Debian Chromium package. The channel would equally exfiltrate any private key present in a future session.
Disclosure Timeline
Recommendations
| Priority | Finding(s) | Recommendation |
|---|---|---|
| 1 — High | 4, 15 (DNS egress) | Block raw UDP/TCP 53 egress from pods. Route all DNS through an internal resolver that logs and rejects queries for non-whitelisted domains. |
| 2 — High | 1 (/proc/*/environ) | Enable a PID namespace per pod so each container only sees its own processes in /proc. |
| 3 — High | 2 (Chrome CDP) | Remove --remote-debugging-port. If debugging is required, bind to a Unix socket with authentication. |
| 4 — Medium | 3, 10 (SSH, writable fs) | Mount /home/kimi/.ssh read-only from a ConfigMap. Disable sshd if not required. Review /app and /mnt mount permissions. |
| 5 — Medium | 6 (Internal network) | Apply a Kubernetes NetworkPolicy to restrict pod egress. Block access to IMDS (100.100.100.200) unless required. |
| 6 — Low | 5 (Overlayfs writes) | Mount /usr/lib/systemd and other system directories read-only. Restrict overlayfs upper-layer permission inheritance. |
| 7 — Low | 7 (Jupyter /tmp files) | Ensure kernel connection files are only readable by the owning process. Use a per-pod private tmpfs (mode 0700). |
| 8 — Info | 13 (SUID / capabilities) | Drop CAP_NET_RAW from the bounding set if not required. Audit and remove unnecessary SUID binaries from the image. |
Conclusion
The Kimi sandbox demonstrates reasonable container-level isolation. User namespace and overlayfs escapes were blocked. The effective capability set is all-zero. No host escape was achieved.
The primary risk is the combination of unfiltered DNS egress with world-readable process environments. These two findings together form a complete, automated, and practically invisible data exfiltration primitive. Any secret placed in a user's pod environment can be silently transmitted to an external server during the session lifetime, requiring only the standard Python code execution capability available to every Kimi user.
Restricting outbound DNS to an internal resolver is the single highest-impact remediation.
Full DNS query logs and decoded environment data are available to the Kimi security team on request.
elvec1o · 2026 · elvec1o.github.io/home