Prompt Says No, Configuration Says Yes: Five Detection Layers for AI Coding Agent Hijacking
This article explains why coding agent configuration hijacking cannot be fixed by a single vendor patch. It breaks down the five-step attack chain, from a web page writing a rules file into the Downloads folder to credential and data exfiltration, and proposes five practical detection layers: session entry checks, configuration integrity monitoring, prompt/execution separation, egress allowlisting, and discovery-driven credential rotation. It also provides a read-only drift-check script, a control mapping table, and a phased rollout plan.
1. The Uncomfortable Conclusion: There Is No Patch to Apply
One of the most important takeaways from a public report on coding agent configuration hijacking is not the attack technique itself. It is the root-cause assessment:
This is not a vulnerability that a single vendor can patch.
The evidence is not an attempt to excuse any vendor. The authors reproduced the issue across two independent coding agent products with completely different implementation paths. Both attack chains succeeded. In one chain, the proportion of sessions where malicious dependencies were executed exceeded 90%. In the other chain, it was around 50%. The numbers are different, but neither result is occasional. This suggests that the problem is not an implementation flaw in one product. It is embedded in the definition of what counts as a coding agent.
A more useful analogy for test engineers is browser rendering of a fake bank login page. When a browser renders a forged page, the browser is doing what it is supposed to do. The attack exists in the page, not in the browser. There is no browser-side patch for it.
Similar issues have existed for years:
- Email clients correctly render phishing emails.
- Spreadsheet software correctly calculates malicious formulas inside spreadsheet fields, commonly known as formula injection.
The common point is this: a data channel is treated as a control channel.
Coding agents push this contradiction to a new level. Traditional parsers still distinguish between “this is file content” and “this is a command you should execute.” Coding agents, however, work by treating natural-language files as behavioral input. A text file placed in a project root directory, with a name that follows common rules-file conventions such as agents.md, naturally gains instruction-level authority.
You may disagree with the “no patch” conclusion. But the engineering consequence is unavoidable:
If the vendor side has nothing to patch, this becomes a check item in your own security gate.
2. The Attack Chain: Five Actions, Five Detection Points
The disclosed attack chain can be broken into five actions. Describing them in order is useful because each step corresponds to a detectable location.
Step 1: A web page writes a rules file into the user’s Downloads directory
The report emphasizes that, on most systems, the Downloads directory is one of the few folders a web page can write to autonomously. No click is required, no confirmation is required, and both the file name and file content can be specified by the web page. Mechanisms such as automatic downloads, repeated downloads, and attachment-style delivery can all achieve this.
Operating systems have long blocked the path where “downloaded executables run automatically.” But this file is not executable, so executable-focused guardrails do not apply. This is where the protection gap exists:
Risk controls target things that can execute, while coding agents turn things that can be understood into things that can execute.
Step 2: The user starts the agent inside the Downloads directory
The report cites its own telemetry: about half of customers have run coding agents in the Downloads directory, and about one quarter of sessions open a real browser. These numbers explain why the path is viable. It is not a coincidence. It is habit.
Security designers often assume that “users will not work in the Downloads directory.” Real-world data says otherwise.
Step 3: The agent reads the file, treats it as project rules, and changes its global configuration
This is the key transition in the entire chain: the impact expands from “this current session” to “all future sessions.”
A project-level file obtains global-level authority. The model does not have the ability to determine which file is allowed to modify its configuration, because for the model, this is text semantics, not permission metadata.
Step 4 and Step 5: Malicious dependencies are introduced, and credentials or code are carried out
In a general environment, these two steps usually appear as:
- Installing a third-party package that contains lifecycle scripts, such as
postinstall. - Sending tokens, source code, or environment variables back through outbound network requests.
Once the global configuration has been rewritten, defaults such as automatic installation and automatic execution can be enabled. Later actions no longer require human confirmation.
The core takeaway
Model output is untrusted. Only the policy layer is enforceable.
All permission decisions must move from model output to deterministic policy. The model may request an action. It must not be able to authorize itself.
3. Five Executable Detections
3.1 Entry Detection: Where the Session Starts Matters More Than What the File Looks Like
The detection target is not “whether there are suspicious files in the Downloads directory.” There are too many legitimate files there, and false positives will drown out the signal.
The target should be the startup location and directory origin of the agent session.
Checkable items:
- Whether the session working directory is under a path that a web page can write to or whose origin is untrusted, such as the Downloads directory, temporary directory, extracted temporary area, or mounted shared drive.
- Whether the working directory contains a rules file whose origin cannot be traced, for example:
- No version repository.
- No commit history.
- File creation time closely matches the timestamp of a download event.
- There is also a commonly overlooked risk inside the Downloads directory: a web page can create a folder, place a rules file inside it, and then the user may extract or open it. Once the user enters that directory, the current directory becomes the “project root directory.”
Implementation recommendation: perform path checks at the session startup hook or command-line entry point. If the path matches a risk condition, refuse to start the session and provide clear guidance, such as moving the project into a controlled workspace. Do not merely warn and allow the session to continue.
3.2 Configuration Integrity: Global Configuration Must Be Watched by an External Control Point
This is the highest-value layer in the entire chain. The core principle is:
Do not rely on the agent itself to report whether its own configuration has been modified.
Self-auditing is ineffective in this scenario. Supervision must be performed by host-side probes, CI jobs, or centralized configuration management.
| Check dimension | Risk signal | Why it matters |
|---|---|---|
| Owner and permissions | Global configuration files are writable by group or other users | Any local process can modify them, so baseline hashes can be “legitimately” updated |
| Content hash | Differs from the baseline manifest | Freeze the baseline first, then compare. Comparison results must be reported externally, not only written to local logs |
| Auto-execution switches | Defaults such as automatic dependency installation, automatic script execution, or automatic patch application change from off to on | These are the keys attackers most want to modify, and they have higher priority than text-only configuration |
| Allowed-directory and allowed-command lists | Wildcard allowances outside the workspace appear | A wildcard allowlist is equivalent to no allowlist |
| Rules-file load priority | Project-level files can override global-level policy | If they can override, any directory can become a privilege-escalation entry point |
3.3 Separate Prompts From Execution: Text Must Never Escalate Into Permission
This layer is architectural. It cannot be solved by adding “do not execute” to a prompt. The prompt layer is untrusted. Putting security constraints in the untrusted layer is like hanging the door lock on a piece of paper outside the door.
Possible layering approaches:
Expose risky actions as tool calls with parameter validation.
Writing to the global configuration directory, installing dependencies, executing lifecycle scripts, and accessing credential stores should all be defined as high-risk actions that require explicit approval.Approval must be given by a human.
The approval interface should show which file will be modified and what scope the change will affect. It should not show only a model-generated summary.The prompt layer must not carry security responsibilities.
System prompts, project rules files, code comments, dependency package READMEs, and web content should all be treated at the same level: untrusted.Default deny, not default allow.
Directory writes, command execution, and outbound network access that are not explicitly listed in the allowlist should be blocked directly.
3.4 Egress Allowlisting: Treat the Exfiltration Channel as Part of the Attack Chain
Credential theft and result exfiltration require outbound network access. This is the hardest part of the attack chain to bypass and the easiest to control centrally.
Recommended policy:
- Default deny. Allow by exact domain. Avoid broad wildcards.
- After DNS resolution, validate the resolved target address again. Block requests pointing to private network ranges, loopback addresses, and cloud environment metadata service addresses, which are typically link-local addresses. This covers bypasses where a domain resolves to an internal address.
- Try to converge coding-agent traffic to a unified egress proxy. Proxy logs should at least retain time, process, target domain, request byte count, and session identifier.
- Alert on changes such as “a new domain suddenly appears in the middle of a session.” This has more signal value than “a certain domain was accessed.”
- In centralized environments, egress access logs and anomalous outbound connection alerts can be handled by general cloud logging and monitoring/alerting capabilities. The key point is to make proxy logs queryable and correlatable, rather than leaving them in local files on a single host.
3.5 Discover-and-Rotate: Define the Response Before It Happens
Once global configuration tampering is confirmed and dependencies have been executed, the response must be handled as “credentials are assumed compromised,” not as “one file was modified.”
Recommended response order:
Isolate first, then collect evidence.
Stop the session and disconnect sensitive credentials, but preserve host snapshots, configuration copies, and proxy logs first. Cleaning up too early destroys evidence needed for tracing.Assume compromise is real and rotate credentials.
Invalidate and reissue static tokens, session credentials, cloud access keys, private repository credentials, and signing keys. Rolling back the configuration alone does not mean the risk is resolved.Roll back and verify.
Restore the configuration baseline. Check whether installed dependencies or lifecycle scripts left behind files, scheduled tasks, or startup items.Align the messaging.
Internally and externally, make it clear that this is a trust-boundary issue caused by the agent working as designed, not a crash in a specific product. Avoid reducing the conclusion to “wait for the vendor to fix it,” which delays building your own gate controls.
4. Read-Only Configuration Drift Check Script
The following script turns the checks in sections 3.1 and 3.2 into executable logic. It is read-only and does not modify any configuration. A non-zero exit code indicates that risk was detected.
Placeholder variables should be adjusted for your environment. Configuration file paths and key names differ across products. The script uses generic placeholders and does not assume a specific schema.
#!/usr/bin/env bash# agent-drift-check.sh - Read-only drift and entry-cleanliness check for coding agent configurationset -uo pipefailDL="${DOWNLOAD_DIR:-$HOME/Downloads}" # Download directoryAGENT_HOME="${AGENT_CONFIG_HOME:-$HOME/.agent}" # Global configuration rootMANIFEST="${CONFIG_BASELINE:-/etc/agent-config-baseline.sha256}"RULE_FILES='agents.md .agent.md *rules*.md'hits=0hit() { printf '[RISK] %s\n' "$*"; hits=$((hits+1)); }ok() { printf '[ OK ] %s\n' "$*"; }# 1) Entry cleanliness: detect coding-agent rule files in the download directory treewhile IFS= read -r f; do[ -n "$f" ] && hit "Rule file found in download directory; it may be treated as project instructions: $f"done < <(find "$DL" -maxdepth 3 -type f \( -iname 'agents.md' -o -iname '.agent.md' \) 2>/dev/null)[ "$hits" -eq 0 ] && ok "No rule files found in the download directory"# 2) Ownership and writability of global configuration: any locally writable file is untrustedwhile IFS= read -r f; do[ -n "$f" ] && hit "Global configuration file is writable by group or other users: $f"done < <(find "$AGENT_HOME" -type f -perm /0022 2>/dev/null)# 3) Content hash drift (freeze the baseline first: find "$AGENT_HOME" -type f -exec sha256sum {} \; > "$MANIFEST")if [ -r "$MANIFEST" ]; thenout="$(cd / && sha256sum -c "$MANIFEST" 2>&1 | grep -v ': OK')"[ -n "$out" ] && hit "Configuration baseline differs from current content:" "$out" || ok "Configuration baseline matches current content"elseprintf '[WARN] Baseline manifest not found; cannot determine content drift: %s\n' "$MANIFEST"fi# 4) High-risk auto-execution switches (key names depend on the actual configuration; this uses generic keyword matching)for cfg in "$AGENT_HOME"/settings.json "$AGENT_HOME"/config.json; do[ -r "$cfg" ] || continueif grep -Eiq '"(autoInstall|allowScripts|autoApprove|bypass[A-Za-z]*)[[:space:]]*:[[:space:]]*true' "$cfg"; thenhit "Auto-install, auto-execute, or auto-approve switch detected as true: $cfg"fidone# 5) Whether allowed-directory whitelists degrade into wildcardsfor cfg in "$AGENT_HOME"/settings.json "$AGENT_HOME"/config.json; do[ -r "$cfg" ] || continuegrep -Eq '"(allow[A-Za-z]*Dir|writableRoots)"[[:space:]]*:[[:space:]]*\[[^]]*("/\*"|"~"|"\$HOME")' "$cfg" \&& hit "Write allowlist contains wildcard entries, effectively removing directory boundaries: $cfg"done# 6) Whether egress is routed through a unified proxyif [ -z "${HTTPS_PROXY:-${https_proxy:-}}" ]; thenprintf '[WARN] No egress proxy configured; cannot enforce an egress allowlist or retain logs\n'elseok "Egress proxy configured: ${HTTPS_PROXY:-$https_proxy}"fiprintf '\nCheck complete. Risk items: %d\n' "$hits"exit $(( hits > 0 ))
Usage recommendations:
- Attach the script to three places: the session startup hook, a scheduled task, and a pre-check in CI.
- Store the baseline manifest in a location the agent itself cannot write to.
- Report check results to centralized logging rather than local files.
Using only one of these places is easy to bypass. Only when all three are combined can the script cover the case where “the configuration is changed and the baseline is changed as well.”
5. Control Mapping Table
| Attack stage | Detection layer | Risk signal | Response | Primary owner |
|---|---|---|---|---|
| Web page writes a rules file | Entry detection | Rules file appears in Downloads directory; no version history | Warn before session start and block work in that directory | Endpoint / workspace policy |
| User starts the agent in Downloads | Entry detection | Session working directory belongs to an untrusted path list | Hard block and guide migration to a controlled workspace | Platform-side entry policy |
| Agent reads the rules file | Prompt and execution separation | Project-level rules file attempts to modify global configuration | High-risk actions require human approval; reject self-authorization | Architecture and product policy |
| Global configuration is rewritten | Configuration integrity | Permissions loosen, hash drift, auto-execution switches become true | Automatically roll back baseline, alert, and freeze the session | Host-side supervision / CI |
| Malicious dependency is installed | Configuration integrity + egress | Lifecycle scripts execute; package source or version is abnormal | Block script execution and isolate the dependency cache | Supply-chain controls |
| Credentials and data are exfiltrated | Egress allowlist | New target domain appears mid-session; access to internal or metadata addresses | Default deny and trace through proxy logs | Network policy |
| Hijacking is confirmed | Discover and rotate | Configuration tampered and dependencies executed | Isolate and preserve evidence, rotate all credentials, and perform retroactive investigation | Incident response |
6. Common Objections and Responses
“Users should not start agents in the Downloads directory.”
The conclusion is correct, but it is insufficient as a defense. Telemetry shows that about half of users have done it. This is an existing habit, not an edge case. Building security on “users will not do this” sets the baseline at the most optimistic scenario.
“This is a model-capability issue. The next model version will recognize it.”
Recognizing “this is a malicious instruction” and being unauthorized to execute the action are two different things.
The first is probabilistic. The second is deterministic. Security controls should rely on the second.
“We already wrote a system prompt prohibiting the agent from modifying its own configuration.”
In this scenario, the prompt layer is exactly the position under attack. The effectiveness of a project-level rules file comes from the loading mechanism, not from whether it is polite.
Any constraint that can be overridden by content cannot count as a security control.
7. Phased Rollout
Do not try to deploy all five layers at once.
A practical progression is:
First, gain visibility.
Enable logging and checks only. Collect three types of signals: entry-point hits, configuration drift, and anomalous outbound connections. Use them to establish the real baseline for your organization.Then, enforce blocking.
Turn configuration integrity monitoring into automatic rollback. Change session startup in the Downloads directory from a warning to a hard block.Finally, automate response.
Connect egress allowlisting and credential rotation processes to incident response plans, and run exercises.
The essence of this work is to translate a design property for which “there is no patch” into a set of deterministic checks that can run in your security gate.
Vendors do not need to change code. Your pipeline needs to change configuration.
