FR
live

AI agents should propose the next system state, not write it as root

On 8 October 2026, CNCF ambassador Mauro Morales put the question haunting platform teams: under what conditions can an autonomous system safely operate a machine. His answer is a principle — immutable host, workload isolation, and a proposed state that flows through the software factory.

A transparent acrylic guard panel bolted over a server’s power switch and status LEDs, a single amber LED glowing faintly behind the glass.

8 October 2026. Mauro Morales, a CNCF ambassador and Kairos maintainer, publishes a post that restates a question now on everyone’s lips. A doubt. “Under what conditions can we safely allow an autonomous system to operate a machine?” An answer. Do not give agents root; have them propose the next state and let the software factory turn that proposal into reality. Why it matters: as AI agents settle into operations pipelines, the line between “observe” and “modify” becomes the new security perimeter of DevOps.

Root is not an API

The post opens with an honest confession: handing an agent root feels immediately powerful. Morales recounts migrating a home service from a MacBook to a Linux box with no downtime, simply by granting superuser access. Then he draws the opposite conclusion: “just because it can be done doesn’t mean it should be done.” Experimentation and production obey different rules, and expecting a well-written AGENTS.md file to prevent an unrecoverable mistake is self-deception.

The core argument is not failure — an API can contain bugs too. It is reproducibility: knowing what changed and who changed it. “We should not give agents unrestricted root access to production systems, for the same reason we should not give humans unrestricted root access to them.” That sentence alone is a verdict. The problem is not that the model is bad; it is that the model is non-deterministic, so its outcome cannot be guaranteed.

The reasoning places the agent in the long history of least privilege. Root was never a programming interface — it is a boundary. Crossing it for a human demands justification; crossing it for an agent should demand no less.

Containers moved the boundary

Morales locates the debate in the history of Linux and containers. Before them, an application that needed a library installed it on the base system, tightly coupling the application to the machine. Containers changed that boundary by packaging an application’s user-space dependencies with the application itself. They do not make the host irrelevant — they still share its kernel — but they deliver a cleaner separation of concerns between the application and the system that runs it.

The host’s job narrows to a tight mission: boot reliably, provide the kernel and runtime capabilities the platform needs, and keep that platform running. The platform, in turn, cares for the containerised applications. This division is not cosmetic; it is what lets you reason separately about what an agent may touch.

That is where immutability enters, as a means rather than an end. An immutable system does not mean a frozen one; it means the machine moves from one defined state to another defined state. Base-system changes are expressed in a versioned definition and consumed as a new image, not edited package by package at runtime. Runtime is no longer where the next state is improvised — it is where a state produced elsewhere is executed.

Immutability is not a sandbox

The post does not stop at the immutable host, and that is its strength. bootc, Flatcar Container Linux and Kairos already support these image-based host lifecycles. Hadron, Kairos’s minimal system, goes so far as to ship no package manager at all. But Morales warns: immutability alone does not protect a machine from a process with unrestricted host, kernel or disk access. The agent still holds every surface where it has write access.

The decisive point is that agent software does not come from the distribution. It arrives through a package manager such as npm, a standalone binary, a container image, or integrated into another application. That is why agent harnesses offer sandboxing: to place a stronger boundary around what the agent can do. But not every sandbox is sealed. Local harnesses such as Claude Code or Codex remain connected to the host through the filesystem, credentials, tools, sockets, network access or session-granted permissions. The CNCF blog has already covered why sandboxing an agent is not enough.

The section’s conclusion is a warning: assuming that, because the base system is protected, the rest of the machine is protected too, is a reasoning error.

The agent is a workload too

Morales then flips the perspective. The agent is a workload, and each session can run in a short-lived execution environment, created for the duration of the work and discarded afterwards. The execution boundary should follow the threat model: a standard pod shares the host kernel and suits a narrowly scoped agent, while an agent that runs untrusted code or needs broad capabilities requires a sandboxed pod or a virtual machine.

The key argument is that the agent does not need direct host access to observe the system or to propose how it should change — it can do both from an isolated workload. The distinction reminds us the question is not binary, “does the agent have access or not,” but graded: what access, to what surface, for how long, under what approval authority.

Here Morales introduces the post’s most useful distinction, between self-healing and self-improvement. Self-healing means choosing among responses we have already authorised: restart, replace, or roll back a workload. Self-improvement means proposing a system state we have not yet authorised, which must therefore travel through the software factory before it becomes real.

Close the loop without opening the host

The post grounds the distinction in a concrete, dated example. During QA of Kairos Trusted Boot images, an agent helped trace multi-minute boot stalls and firmware reset loops to an incorrect PE section alignment in go-ukify, the library AuroraBoot uses to assemble UKIs. Sections were aligned to 512-byte boundaries when the systemd stub required 4 KB. The fix landed as go-ukify v0.5.2, then a AuroraBoot update, and the agent verified the corrected images.

What the agent must not do is apply those changes through root access or modify a mutable system in place. Starting from the question of autonomy, an immutable system is clearly the better model: the agent inspects the current state, records its assessment and opens a pull request proposing the next state. That proposal then follows the same path as a human change: review, testing, a new image build, signing, release. Only then is the new state consumed.

For this to be a real boundary, the agent’s identity must be allowed to propose a change without being allowed to approve or merge it, alter the pipeline, publish or sign the image, or force the machine to consume it. Otherwise we have replaced root with “root plus a few more steps.” This separation of authority joins the CI/CD threat model described in the work on shadow AI in CI/CD.

Verdict

If your agents already operate your clusters or hosts, replace any direct root access with a three-layer chain: an immutable base (image, no hot mutation), workload isolation proportionate to the threat model (pod, sandboxed pod or VM), and a proposed state that flows through the factory — review, build, signing, release. Grant the agent’s identity the right to propose, never to merge, sign or deploy. If you have not yet put agents into production, set these boundaries before the first access, not after the first incident: “trust the boundaries, not the model” is far cheaper to install than to retrofit.

References

The cyber brief, every Tuesday

The flaws that matter and the patches to apply, in a ten-minute read.

No spam. One-click unsubscribe.
read next

On the same topic

Fixing Kubernetes means patching the kubectl on Windows boxes, not just the control plane

In late September 2026, the Kubernetes Security Response Committee fixed two medium flaws: CVE-2026-19444, a kubectl cp path traversal on Windows, and CVE-2026-2270, a confused deputy in the StatefulSet controller. The lesson for everyone: updating the control plane protects neither your admin workstation nor the isolation between namespaces.

The OpenTelemetry Java agent 3.0 renames your metrics and ships GA this month

Version 2.32.0 of the OpenTelemetry Java agent, released on October 6, 2026, serves as the release candidate for 3.0, which is slated to go stable this month: attribute names, units, and trace shapes all change. Turn on dual emission with the /dup flag and compare your telemetry before the new schema becomes the default.

← Back to the feed

Type at least two characters.

↑ ↓ navigate ↵ open esc dismiss