This isn't a bug. It's the default.
Codex writes unbounded session logs to local SSDs. Mapped correctly to MITRE T1499, not T1071 - a disk-exhaustion DoS primitive EDR baselines miss.
Codex writes its session transcripts and trace logs to local disk by default. No size cap. No rotation boundary. No retention ceiling. The write path scales with token throughput, so a verbose configuration or a retry loop turns logging into a sustained I/O workload: gigabytes in a single session, terabytes across a campaign. The topic circulating with this issue calls it a logging bug and maps it to MITRE ATT&CK T1071. Both framings are off. It is not a discrete bug; it is a default. And T1071 is the wrong technique.
T1071 is Application Layer Protocol - command and control tunnelled inside HTTP, DNS, or another protocol. Process Injection, the label paired with it, is T1055. Neither describes disk exhaustion. What this produces is uncontrolled resource consumption against a local volume, and the technique for that is T1499, Endpoint Denial of Service. Scope, not technique, is what changes when the same write path degrades a shared host: still T1499, now crossing into co-tenant jobs. The ID is not trivia. It selects the data source instrumented and the team that owns the gap. Map it to injection and the SOC hunts for threads and hollowed processes that are not there.
No CVE is assigned, and assigning one would misrepresent the shape. There is no memory-corruption primitive, no patch delta, no affected-version boundary in the usual sense, since the behaviour is present wherever the default verbosity and unbounded log path ship. The classification is CWE-400, uncontrolled resource consumption, with CWE-779, logging of excessive data, and CWE-770, allocation of resources without limits or throttling, as the contributing conditions. Scored as an availability-only local issue - AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - the base sits near 5.5, Medium. The vector moves. If the workload that triggers the write storm is supplied remotely - a poisoned repository, an attacker-shaped prompt or task handed to the agent - the access vector trends to AV:N and the score rises. On a shared CI volume, scope flips from unchanged to changed: one job exhausts the disk every co-tenant depends on, and the impact crosses the boundary the runner was supposed to hold.
The mechanism is unbounded log growth with no eviction. The agent emits a structured record per model interaction, per tool invocation, per streamed token range. JSONL or equivalent - every event re-serialises context, so bytes per event run high and redundant. Each record is appended to a session log. Nothing rotates the file. Nothing truncates it. Nothing ages it out. An interactive session writes tens to hundreds of megabytes. An agent caught in a retry loop - a failing tool call retried, a plan that does not terminate, a model regenerating the same step - writes continuously, bounded only by event rate and disk bandwidth, until something else stops it.
The physical cost exceeds the logical byte count. Log writes are small appends flushed frequently, often with an fsync per record for durability. On an SSD the flash translation layer programs in whole pages and erases in whole blocks, so frequent small synced writes force read-modify-write and garbage collection. Write amplification pushes physical NAND writes above the logical total - a workload that logically writes a terabyte wears the cells as if it wrote more. The endurance budget is finite and published. Consumer TLC NVMe is rated near 600 terabytes written per terabyte of capacity; a drive at 0.3 drive-writes-per-day is provisioned for roughly that over five years. A logging workload running at a fraction of NVMe write bandwidth still reaches those numbers in days, not years, when it loops. The wear does not reverse. Free space returns when the logs are deleted; spent write cycles do not.
Weaponisation needs no dropped binary and no memory primitive. It needs influence over the workload the agent processes. An attacker who can shape what the agent runs - a repository structured to induce a tool-call loop, a task written to maximise verbose output, an input that forces repeated regeneration - drives the write path while staying inside the sanctioned execution of a trusted tool. No payload is delivered. The logging is the payload, and it is working as designed.
This is living off the land in the exact sense. The writing process is the Codex binary - signed, allow-listed, expected on a developer workstation or a build host. The writes target a known log directory. No new process spawns. No remote thread is created. No beacon leaves the host. The malicious condition is indistinguishable from heavy legitimate use at the resolution most telemetry runs. Sustained, it fills the volume: temp space gone, builds fail, services that need scratch space stall, the host degrades into a soft denial of service. Aimed at the same SSD over weeks, it spends endurance and pulls hardware failure forward in the maintenance window.
The self-hosted CI runner is the clean target. Ephemeral cloud runners reset their disk between jobs and absorb the wear in someone else’s fleet. A self-hosted or persistent runner carries log accumulation and NAND wear across every job it serves. Drop an agent task into that pipeline that drives sustained verbose logging, repeat it across the build matrix, and the write volume compounds on a disk nobody is watching for wear. The runner keeps reporting green until the volume fills or the drive throws errors. This is the same failure CI/CD has seen from cache poisoning and log floods, reached through a sanctioned agent instead of a malicious step.
No confirmed in-the-wild campaign is tied to this specific default, and claiming one would be invention. What exists is a predictable, low-skill primitive that maps cleanly to T1499 and requires only workload influence over a tool that is being adopted fast and run with broad local privilege. The absence of a named actor is not the same as absence of exposure. It is a primitive sitting in front of detection that is not built yet.
In telemetry the gap is structural, not a missing rule. Sysmon Event ID 11 records file creation - it fires once when the log file is created, then goes silent while the file grows to terabyte scale, because Sysmon carries no write-volume field. There is no Sysmon event for bytes written. Windows Security auditing has no event for disk write throughput. The kernel file and disk I/O providers in ETW - Microsoft-Windows-Kernel-File, Microsoft-Windows-Kernel-Disk - do carry byte counts and write operations, but the event volume is enormous and almost no one ships it to a SIEM. On Linux the equivalent visibility means auditd file rules or eBPF on the write path, again high-volume and rarely retained.
EDR observes file I/O, but sustained appends to a known-good log path by a signed, allow-listed process are precisely what an EDR aggregates and de-prioritises. The behavioural baseline absorbs it. No alert category fits the activity - it is not injection, not credential access, not exfiltration, not lateral movement. It looks like a developer tool writing logs, because that is exactly what it is. MITRE’s data-source mapping for T1499 leans toward network traffic and sensor health; the technique was modelled around network floods, not disk fills, which is part of why this endpoint variant has no obvious home in standard SIEM content. The drive-write evidence lives in the DS0016 Drive data source, which most SOCs do not stream.
The signal that does exist lives outside the SIEM. LogicalDisk free megabytes falling at a steady, attributable rate. NVMe SMART Data Units Written, or SATA Total LBAs Written, climbing faster than the workload accounts for. Filesystem quota warnings. df on a runner. These are infrastructure and observability signals - real, and early. They are rarely correlated with the process that caused them, because the team watching SMART health and disk capacity is not the team watching process and network telemetry. Shops that run at scale - the Cloudflares and Oktas of the world - keep drive health in infrastructure observability, separate from the SOC SIEM. That separation is the gap. Not a missing detection. A missing join between two systems that each hold half the evidence.
The detection that works is a correlation, not a signature. Free-space rate-of-change per volume, alerting on sustained decline rather than a static threshold. SMART Data Units Written delta per host, baselined per role, alerting when the rate departs from the workload profile. Both joined to process attribution - ETW kernel file write events on Windows, eBPF on the write path on Linux, sampled enough to name the writer without drowning the pipeline. The output is one correlated finding: this process, this volume, this write rate, this wear delta. That join is engineering work. It does not exist in a default SIEM content pack.
The fix is a configuration boundary, not a binary patch - which is the residual exposure. Log rotation and a hard size cap on the path. A dedicated log volume with a quota so exhaustion cannot starve root or the build filesystem. Non-debug verbosity as the shipped default. A retry ceiling so a loop terminates instead of writing forever. Monitoring on Data Units Written and free-space delta, attributed to the writing process. None of that is on by default, and a default that persists across every install means every un-reconfigured host carries the same primitive until it is changed per host, per pipeline. The endurance already spent does not return; NAND wear is physical and no update reverses consumed cycles. For an operator under the SOCI Act, an availability impact to an in-scope asset is the reportable event the obligation exists for, and a disk-exhaustion condition that degrades a critical system qualifies regardless of how mundane the cause reads in the log. The bug is boring. That is why it works. The write path is trusted, the volume is invisible to the tooling pointed at the host, and the damage is counted in free megabytes and write cycles - two numbers the SOC is usually not watching.
See also: NordVPN for tunneled traffic when operating outside controlled networks.
#ad Contains an affiliate link.
Keep Reading
axios CVE-2025-3891: What the Advisories Don't Say About Immutable Images
CVE-2025-3891 in axios allows prototype pollution leading to RCE. This post reveals why deployed container images remain at risk even after patching, due to missing artifact provenance and immutable verification.
social engineeringSocial engineering is a misconfiguration
Human error in identity workflows is a misconfiguration, not incompetence - how Scattered Spider, 0ktapus and MFA fatigue exploit the validation gap.
dev/tcpRemoving curl and wget stops nothing
Bash /dev/tcp opens TCP sockets and sends HTTP with no curl or wget, evading process-name detection while leaving cleartext on the wire.
Stay in the loop
New writing delivered when it's ready. No schedule, no spam.