Blackbox Blast
BB Preflight
← Incident log

CASE · Minor · other

Unverified reportCollected from public reports

An AI agent was confined to a dedicated user, but a root configuration script was the way out (unverified report)

According to the author, in a self-built tool that runs an AI coding agent as a dedicated user without sudo, the root configuration and update scripts that write that user's home had a hole. If a settings file in the home was replaced with a symlink pointing at a protected file outside the home, the next update made root rewrite the link target and even change its owner to the dedicated user. This is the author's own report; it does not describe actual harm.

5 min read

OBSERVED
CATEGORY
other
BLAST RADIUS
none
DETECTED BY
ai-code-review
TAGS
#symlink #root-script #dedicated-user #privilege-boundary #claude-code #codex #regression-test #linux

CH 1

Cause

Per the author, files inside the user's home are not necessarily what they look like, yet root wrote them with full privileges. The same result occurred when the symlink sat on a directory in the middle of the path, not only at the final file. In the prior version, write_agent_file created intermediate directories as the user, but the final install ran as root.

CH 2

Consequence

Per the author, in a reproduction in a disposable container, a line was appended to a verification file readable and writable only by root, and its owner changed from root to agent. After the fix, two more holes of the same kind were found: a root rm -f that removed old settings when no proxy setting existed, and a root tar -c backup that put root files the user could not read into the archive. The author reproduced both in containers.

CH 3

Fix

The author moved operations inside the home to the user's own privileges via runuser, including opening files, changing permissions and deleting. A regression test that places symlinks at the end and in the middle of paths was added to a disposable container, writes to the home were gathered into a few functions, and the rule was written into the repository's CLAUDE.md. Per the author, all 49 tests passed on v0.3.1 on October 26, 2026.

What happened

The author (PROPAGANDIST CORPORATION) reports a hole in a self-built configuration tool (propagandist/agent-host-autoinstall) that runs an AI coding agent as a dedicated user without sudo. The root scripts that set up that user's configuration could follow symlinks in the user's home and rewrite protected files outside it. This is the author's own report and does not describe actual harm. The hole was found before v0.2.0 was released, and the fixed version passes the tests as of v0.3.1.

The chaos on the ground

Per the author, the hole was found when an AI agent was asked to review the whole repository. Codex pointed out that root reads and writes the agent's home settings during updates and changes ownership, and filed an issue with a reproduction in a disposable Ubuntu 26.04 container. Claude Code independently verified and reproduced it, and also found a path the issue text had not mentioned, write_agent_file (Issue #1).

The author describes the flow as follows. The dedicated user can replace a settings file in its own home (for example ~/.config/mimeapps.list) with a link to a protected file. The user cannot write through that link, so nothing happens by itself. But on every update a root script writes the same settings file, follows the link, rewrites the target, and the final chown changes its owner to agent. In the container reproduction, a line was added to a verification file that only root could read and write, and its owner changed from root to agent. The author notes that links can be planted even without malice by the agent, through instructions hidden in repositories or web pages it reads, scripts in dependency packages, or mistaken operations.

Root cause

Per the author, the problem arises when three conditions hold together. The user can replace the target settings file, or a directory in the middle of its path, with a link. An administrator or automated process runs the configuration and update scripts as root. Those scripts operate on user-controlled paths with root's privileges.

The author gives two concrete examples. One is that ini_set, which writes the default-browser setting, used Python's open(path, "w") and wrote as root. The other is write_agent_file, which created intermediate directories as the user but ran the final install as root. So if an intermediate directory was a link to a system configuration directory, a file owned by agent was created at the link target. The author explains that O_NOFOLLOW can refuse only a link at the end of a path, and that shell commands cannot reject links anywhere in the path. The author also says Ubuntu's default fs.protected_symlinks did not stop root from following links inside the home (confirmed by the author).

The fix

The author chose to perform operations inside the home with the user's own privileges, rather than checking for links first. Checking first leaves a window between check and write in which a link could be swapped in (TOCTOU), and every intermediate directory would also need checking. Concretely, the author added agent_run, which runs commands as the user via runuser. write_agent_file now does everything as the user, from creating intermediate directories to writing a temporary file in the same directory and replacing the target with mv -T. The default-browser setting became ini_set --as-agent with the chown removed. Appends to .bashrc, the editor settings, chmod on ~/.ssh and deletion of old settings were also moved to agent_run.

The regression test runs only as root inside a disposable container. It places a root-owned file and directory outside the home, creates links as agent at the end and in the middle of paths, calls the real functions, and checks that the contents, owner and permissions outside are unchanged. Per the author, v0.3.1 was tested in a disposable Ubuntu 26.04.1 container on October 26, 2026, and all 49 tests passed.

After the fix, the author asked another agent to check the article against the project's facts and found two more holes of the same kind. One was Issue #24, a root rm -f that removed old settings when no proxy setting existed; the path was held in a variable, so the grep audit did not match it. The other was Issue #23, where a root tar -c backup followed a link in an intermediate directory and put root files the user could not read into the archive. Both were fixed in v0.3.0 by handling them with the user's privileges. The author also states that grep only produces candidates and a person must judge them, and that swapping links in the middle of an update and exhaustive checking of all update scripts were not verified.

As a lesson for operators: scripts that write a confined user's home as root should be changed to write with that user's privileges, with regression tests for links at both the end and the middle of paths.

Sources

PREFLIGHTIs your own Mac prepared?BB Preflight is a free Mac tool that checks 21 things, from AI agent permissions to where your keys live, without changing anything.Run the check →