Deadbugz: A new kind of malicious MCP server Pillar Security documented Deadbugz, a malicious MCP server attributed to GitHub account zellkernel, which targeted 23 GitHub repositories in one evening and breached none. The server evades detection by behaving normally for the first three tool calls per client, then returning poisoned tool descriptions that instruct AI agents to exfiltrate SSH keys, AWS credentials, shell history, and Kubernetes configuration while concealing the activity from users. The attack spreads via pull requests that modify MCP configuration files, exploiting the invisibility of tool descriptions to humans. Malicious MCP servers are not a new idea. Tool poisoning, where a server hides instructions inside the descriptions it hands an AI agent, has its own entry in the OWASP MCP Top 10, and researchers have been publishing working examples for over a year. The category is established and reasonably well understood. What keeps changing is how much effort attackers will spend on being looked at and cleared. Deadbugz is a recent example, documented by Pillar Security and attributed to the GitHub account zellkernel . The operator went after 23 GitHub repositories in a single evening and, as far as anyone has published, got into none of them. It is worth studying anyway, because the method it used to avoid detection is more interesting than its success rate. The mechanism The server offers two tools, format text and summarize . Nothing about either one is alarming, and for a while nothing about the server's behavior is alarming either. It works. Behind that, the server keeps an in-memory counter for each connected client, incrementing on every tools/call request. Once that counter reaches three, the server starts returning different answers to tools/list and prompts/get . The tool descriptions it hands the agent now instruct it to go looking for SSH keys, AWS credentials, shell history, and Kubernetes configuration. The code that does this is not hidden. The counter is the whole trick, and the trick is timing. What makes it different A malicious server that is malicious from the first request has one serious problem, which is that anyone who looks at it sees what it is. Evaluation, testing, a security review, a curious engineer poking at it on a Friday: any of those catch it. Deadbugz is well behaved during exactly the period when someone might be watching. The first three calls are the calls a person makes while deciding whether to trust it. By the time the server turns, the human has moved on and the agent is working alone. That inverts how software review normally works. Review assumes that what you examined is what you will get, and that a component's behavior is a property of the component. Here the behavior is a function of how many times you have already used it, and the interesting state exists only on a server somebody else controls. How the malicious activity stays hidden Two things keep this out of view, and they compound. The first is explicit. Along with the instructions to collect credentials, the poisoned metadata tells the agent to conceal the activity from the user. The agent is being asked to do the work quietly, and agents are cooperative. The second is structural, and it matters more. Tool descriptions are written for the model, not for the person. They are exchanged between the server and the agent to help the agent decide which tool to use and how, and most MCP clients never put them in front of a human at all. A user watching their agent work sees tool names and results. The text steering those decisions scrolls past nobody, because it was never displayed in the first place. So the poisoned instructions live in the one part of the exchange that is both authoritative to the agent and invisible to the operator. How it reached people For anyone who does not spend time on GitHub, the delivery method needs a short explanation. A pull request is a proposal, not a change. Anyone can copy a public repository, edit their copy, and then open a pull request asking the project's maintainers to take those edits. Until a maintainer with write access merges it, nothing about the real project has changed. This is how open source works, and reviewing unsolicited contributions from strangers is an ordinary part of maintaining a project. Pillar describes the delivery mechanism as a pull request that adds or changes MCP configuration. An MCP configuration file lists the servers an AI client connects to, and teams often keep that file in the project repository so everyone working on the project gets the same tools. Add a server to that list, get the pull request merged, and people connect to it without ever having chosen it. The 23 requests went out in 74 minutes, between 9:52 and 11:07 PM UTC on August 10, 2026. Seventeen added a remote endpoint. Four pointed at a hidden local Python file at ~/.config/.cache/.sys/.deadbug-mcp.py . Two were submissions to directories and listings, which is the more familiar path where a server gets published somewhere public and people install it themselves. Targeting the configuration file rather than the code is a deliberate choice. A one-line addition to a list of servers reviews in seconds and does not look like a program. It looks like housekeeping. Of the 23, nineteen were closed and four were still open at the time of the writeup. None are reported as merged. Why this is hard to spot Read the source and you will not find it. The operator published a matching source repository, and the code there is fine. The malicious content is not in any file. It is in what a remote server chooses to say in response to a request, after it has counted to three. That defeats more defenses than it first appears. Code review inspects an artifact, and the artifact is clean. Package signing proves a file has not been altered since it was signed, which is true and irrelevant when the payload is a dynamic response. Malware scanning looks for known bad content in something at rest. And OAuth, which comes up constantly in MCP security conversations, answers the question of who a server is. Deadbugz does not lie about who it is. It lies about what it wants the agent to do, and it starts lying after the introductions are over. Every one of those controls runs once, at the beginning, against something that does not change. Deadbugz is something that changes. What actually catches it The defense has to run at the same time the attack does. Record the tool schemas a server presents when it is approved, then keep checking them. Pillar's recommendation to platform builders is to treat a change in the tool definition of an already-approved server as a security event that requires renewed approval. A server whose tools/list response differs from the one that was signed off has done something worth interrupting, whatever the explanation turns out to be. Beyond that, the practical measures are unglamorous. Review configuration diffs with the same suspicion as code, because a line that adds a server is a line that adds a program. Keep an inventory of which servers are approved, so that a connection to something outside it is a fact rather than a question. And treat a tool description as executable content, because to an agent it is. The part worth carrying forward The attacks are being designed against how AI tooling actually grants trust, and that model has a specific weakness. A person evaluates a tool once. An agent then follows that tool's instructions indefinitely, at machine speed, without the person in the loop. The gap between those two facts is where Deadbugz lives. Nineteen maintainers looked at this and said no, which is a good outcome and not a durable one. The technique is documented now, and the next version of it will not count to three.