At end of input, such as < /dev/null, Aider answers yes to its "Run shell command?" prompt, so unattended runs execute model-proposed shell commands.
What we found.
The report's lead finding, in the wording of our correction sent two hours later: the trigger is "end-of-input on readable stdin, for example `< /dev/null` or a pipe that has ended", and Aider then answers yes to "the tested confirmation prompts that reach the end-of-input handler with a yes default, including the explicit-yes shell prompt". "With stdin fully closed, Aider exits with an error instead." "That is more permissive than --yes-always, which deliberately refuses shell commands."
So a scripted run such as aider --message "..." < /dev/null, , a common setup in cron and CI, "executes shell commands the model proposes with no human present, while --yes-always would refuse them." The report's own words on the stakes: "unattended runs are exactly where nobody is watching, and a prompt injection in repository content could get commands run." As our correction added: "Prompt injection is a possible consequence, not an exploit we demonstrated." It also noted that "the chat history records the answer as "[Yes]: y", which looks the same as a person typing yes."
We re-checked this on 19 October 2026 on Aider 0.86.2. The direct test with stdin at /dev/null returned the same result as sent, and with the one-line fix from our report applied the same test returns False in all three cases. Nothing in the release has changed; the fix is ours on the table, not a vendor change.
What EOF answers.
What we tested, and what we saw.
"Direct test with no API calls (Aider 0.86.2, the latest PyPI release, identical to the v0.86.2 tag; current main has no changes to io.py)." The mechanism, from the report: "In confirm_ask, an EOFError falls back to the default answer, "y" ("Treat EOF (Ctrl+D) as if the user pressed Enter")" at aider/io.py lines 884 to 887, and "The guard that stops --yes-always from running shell commands only applies when self.yes is True" at lines 866 to 867.
The direct test ran the same test.py with stdin at /dev/null; as sent: "Output: True, True, False." "A person reproduced this independently." The live run, as sent: "Live run: without --yes-always, with stdin at /dev/null, the model's suggested" ls -la and find . -maxdepth 2 -name "*.env*" "were executed and their output was sent back to the model. The find command listed file names only; no file contents were sent."
- Re-check, 19 October 2026, Aider 0.86.2 (aider_chat-0.86.2 from PyPI, still the release the report covers): with stdin at /dev/null the same direct test again returned True for the explicit-yes prompt with fancy input on and off, and False with yes=True. Unchanged.
- With the report's one-line fix applied ("res = "n" if explicit_yes_required else default" on the EOFError path), the same test returns False in all three cases.
- The two smaller points from the report were also re-run and unchanged: the analytics opt-in question is still answered yes at EOF without a human seeing it (the seeded install inside the PERCENT = 10 band came back with asked_opt_in true), and an --api-key deepseek key still lands in full in .aider.chat.history.md while the OpenAI dummy key stayed masked.
Where they differ.
| What a reader would expect | What we observed |
|---|---|
| "The scripting documentation presents --message for scripted use without mentioning this." | "executes shell commands the model proposes with no human present, while --yes-always would refuse them." |
| --yes-always, the flag for unattended use: "deliberately refuses shell commands". | At end of input Aider answers yes to "the tested confirmation prompts that reach the end-of-input handler with a yes default, including the explicit-yes shell prompt", so a plain run without --yes-always is the more permissive one. |
| "Analytics are opt-in, the payload matches your documentation, and --analytics-disable and --no-analytics both held." | "In the same EOF mode, and with --yes-always, the analytics opt-in question is answered yes without a human seeing it, and the choice persists for later runs." The question is asked of installs whose UUID falls within PERCENT = 10, per the report. |
| Key flags are masked in the chat log: "only the OpenAI and Anthropic key flags are masked". | "A key passed as --api-key provider=KEY is written in plain text to .aider.chat.history.md; only the OpenAI and Anthropic key flags are masked" |
The fix we proposed and tested, as sent to Aider:
--- a/aider/io.py
+++ b/aider/io.py
@@ -882,8 +882,8 @@ class InputOutput:
else:
res = input(question)
except EOFError:
- # Treat EOF (Ctrl+D) as if the user pressed Enter
- res = default
+ # Treat EOF (Ctrl+D) as Enter, but never as consent to an explicit-yes prompt
+ res = "n" if explicit_yes_required else default
break
"The fix is deliberately narrow: non-explicit prompts such as "Create new file?" keep their current default on EOF, so existing scripts do not break." "It does not change the analytics opt-in question, which is not an explicit-yes prompt" in the report's wording. And the offer stands: "I am happy to open this as a pull request, with a test, if you would like." "If it helps downstream users, we would also support a GitHub security advisory or CVE crediting your fix."
What a reader can do with this.
Unattended runs: until a fix ships, treat any Aider run whose stdin reaches end of input (for example < /dev/null, or a pipe that has ended) as one that will answer yes to "Run shell command?". With stdin fully closed, Aider exits with an error instead. That is the difference the report draws: "while --yes-always would refuse them."
Keys: "A key passed as --api-key provider=KEY is written in plain text to .aider.chat.history.md; only the OpenAI and Anthropic key flags are masked" in the report's wording. The sound list, as sent: "API keys never appeared in request bodies. .env is added to .gitignore by default, and --yes-always correctly refuses shell commands."
Timeline note from the report: "We plan to publish a short research note on 26 October 2026, or once a fix is released if that is sooner."
What we are not claiming.
- "The find command listed file names only; no file contents were sent."
- "Analytics are opt-in, the payload matches your documentation, and --analytics-disable and --no-analytics both held."
- "API keys never appeared in request bodies."
- "It does not change the analytics opt-in question, which is not an explicit-yes prompt" in the report's wording.
- The re-check was one day on Linux, on Aider 0.86.2: the direct test, the patched build and the two smaller points. It covers the confirmed behaviours and nothing else; whether a live unattended run executes a proposed command also depends on the model proposing one.
- We make no claim about versions after 0.86.2.
Disclosure of interest: "Agentic Thinking also owns AgentProtect, commercial AI agent governance software."
Disclosure timeline.
- 26 Sep 2026: reported to aider@aider.chat: "I am emailing you privately because the repository has no security policy or private reporting channel, and we found an issue you should see before anything is published." (Date header "Sat, 26 Sep 2026 09:29:13 +0100"; Message-ID <179041135379.2193194.14174648673599296116@agenticthinking.uk>).
- 26 Sep 2026, 10:17: the same report re-sent to aider@aider.chat (Message-ID <179041422724.2239027.12153767667138220274@agenticthinking.uk>).
- 26 Sep 2026, 11:21: correction sent in the same thread (Message-ID <179041809168.2291843.1699905992255386070@agenticthinking.uk>): the trigger is end of input on readable stdin, not closed stdin, and the claim covers the tested prompts with a yes default, including the shell prompt. This note uses the corrected wording.
- Vendor response: No reply. No acknowledgement or reply from Aider is in our records; the acknowledgement requested within "a week or so" did not arrive.
- 19 Oct 2026: re-checked on Aider 0.86.2. The direct test is unchanged; the proposed fix, patched in, returns False in all three cases. Nothing is fixed in the release, so there is nothing to credit.
- 26 October 2026: this note published, stating the version tested and this timeline.
Any response will be added here. Evidence and reproduction steps are available to the Aider maintainers and to researchers on request: research@agenticthinking.uk.