The install dream that sounded malware-shaped
If you let an install agent run commands, the part that has to be mechanical is whatever you are unwilling to leave to a prompt: which commands may run, where secrets live, and what happens when a rule matches. Sarah Sanders, who introduces herself as a context engineer at PostHog and says she works on the wizard every day, treats the team’s own docs, lessons, and example apps as part of that same problem. Content the agent will read can steer a machine that has hands.
A few months before the talk, a push to make the wizard the recommended or default way to install PostHog set off what she calls her security alarm. The shape felt malware-like: a tool that reads a project and then changes it. The talk is the night-time lessons from that review, and the scanner she built because of it. The video was uploaded on 14 September 2026. The recording does not give the conference day, so “yesterday” and “a year to nine months ago” stay relative to the speech.
What she says the wizard is, and why the agent loop is the product
Sanders describes the wizard as an agentic command-line tool, a program that can plan and act rather than follow one fixed script. In her account it reads the project, installs a fitting PostHog SDK (the software library that matches that stack), instruments events, and sets up dashboards. She says setup that used to take about an hour or two now runs in about five to six minutes, and that inference is free on PostHog. Both the time comparison and the free-inference line are on-stage claims, not a measured median and not a pricing-page fact.
She points to a looping run on screen and says it is the same terminal experience a person gets by starting the wizard with npx, the runner that launches a Node package. She calls it a small implementation engineer in the terminal. The npx line in the recording is not a package name a reader can type.
People ask why PostHog does not simply hand over a good prompt, or a skill a user can invoke inside their own tool. She says PostHog does provide those. Her product bet is the command-line tool that can take part in an agent loop, the cycle of model, tool, and result, and the experience of seeing that loop for the first time.
She says threat models fall out of anatomy, and that the wizard shares a shape with other agents: models chosen for specific tasks, prompts that steer, and a set of tools. She does not name the models. The piece she treats as PostHog’s own is an in-house context engine, which she calls the wizard’s brain and jokes about as markdown in a trench coat. She credits that engine with similar results on every run. That consistency is her claim. The terminal interface, she says, was built by the team with Ink, a library for terminal interfaces.
A command-running agent as a warning, and how the wizard started
Her warning is for anyone shipping an agent with hands, her phrase for an agent that can run commands. She calls the worst case a malware starter pack: a model, instructions, and tools that act, close to what a generous attacker would hand a piece of malware. She calls that picture nightmare fuel and a warning. She says it is not a confession that the wizard shipped in that shape, and she tells builders to make sure they do not build it.
The origin story is hers. V0 came from Josh on PostHog’s growth team after he watched Cursor hallucinate PostHog setups, in her words quite possibly in the worst ways. His surname does not come through clearly, so this stays Josh on the growth team. Sanders’s team extended the prototype once they judged that it did a much better job, with a goal of onboarding any framework without the user touching the instrumentation. “Much better” is their qualitative judgment.
On usage, she says they had imagined thousands of developers a week. The day before the talk, she says, they hit about 8,000 people a week, and she treats that volume as the dream coming true. She had pictured the wizard as the recommended or default install. In this talk she does not say it became the official installer. The figure is people a week, tied to the day before she spoke.
Prompts were layer zero; the shell was already an allow list
About a year to nine months before the talk, she says the earliest control was what she calls layer zero, because it was only prompts suggesting what the agent should do. That becomes the talk’s first rule: prompts are not security.
A tighter allow list reassured her somewhat. Runtime context from the context engine still worried her, because the wizard was being fed a lot of material while it ran. She built a rough scanner inside the wizard to look for threat-shaped material going in and coming out. She describes a hand-rolled pattern scan, later pulled out and replaced, and she calls that early version extremely rough. The early scanner’s pattern style is unclear in the recording. She is candid that agent builders, herself included then, were learning security while shipping experimental systems quickly, and that a command-running shape still has to be thought through.
The bounds she says were already there are the shell story. The session title talks about letting an agent execute Bash. In the talk, bash is deny-by-default: the shell starts closed, and only named actions are opened. Installs were limited to packages PostHog had vetted. The agent could build, typecheck, and lint. Arbitrary shell was blocked. Environment variables were unavailable. An environment file was blocked outright. The environment filename is unclear in the recording. Secrets were routed through a vault so they would not reach the model. The word in the recording sounds like “rooting”; in context she means routing, and she names no vault product.
The audit gaps were innocent pieces shaking hands
She asked PostHog’s security team to audit and says they found gaps. The lesson she draws is the shape of those gaps. Almost none looked obviously evil. Two innocent, well-intentioned behaviors met and opened a hole. She does not name the bugs, and she does not say the same team later signed the finished stack.
Developers, she says, read one diff at a time. Attackers look across the whole system for the two pieces that shake hands. Her formulation is that attacks compose, and code review does not.
The scary input was the content they fed the agent
After a slide mix-up she describes the context mill, the machine behind the wizard’s brain. It pulls docs, handwritten gotchas and lessons, the pitfalls the team has already hit, and working end-to-end example apps. Those materials are packaged as skill bundles, sent through PostHog’s MCP server, and loaded into the agent’s context at runtime. Here MCP is the channel she says carries that content in. She names no package, and she does not describe the bundle format in enough detail to reconstruct it.
She asks the room to sit with a machine whose job is to inject content into an agent that can run commands. For them, the frightening input was that helpful-looking content.
The attack she fears is poisoning that content. She sets aside the user’s codebase and the agent itself. Someone opens a pull request on an open-source PostHog repo, because she says PostHog builds in the open. A markdown file or a comment that looks harmless goes in. An LLM review waves it through. A prompt injection signed by PostHog, meaning instructions hidden in trusted text that try to override the agent, then lands on many developer machines. She adds the hedge herself: the run is in a sandbox, an isolated environment, and the injection would still be there. This is her threat model. She does not say this incident happened.
Her control is a design. Scan a skill when it is built and released, and scan it again when the wizard uses it. Catch it at the source, assume that catch failed, and catch it again at the point of use. She attaches no catch rate to that method.
The Warlock finds; the caller decides
The Warlock is the scanner she built after looking at what shipping a production agent exposed. She says it was not only damage control, because other defenses already existed. What she rejects is telling people the thing is “pretty locked down.” She says that phrase does not scale, and that it is not a posture she wants shipped to thousands of developers running the wizard every day, because surface, users, and content all grow. That picture is separate from the about 8,000 people a week she reported for the day before the talk. She pulled the rough scanner out of the wizard and made it a standalone bodyguard. The name is the joke: something wizard-shaped needs one.
Its one job is string in, findings out. Each finding has a category, a severity, and a recommended action, and then the scanner stops. She stresses “recommended.” It may say something looks like exfiltration, that the severity is critical, and that she would block it. The caller decides. The exfiltration line is an illustration of a finding, not a case with a command attached. Detecting a problem and deciding what to do about it are separate jobs, and she says keeping them separate is what makes the system understandable.
Under the hood she replaced the hand-rolled patterns with YARA, a pattern engine she describes as the one malware researchers have used for 15-plus years. She wants the same input to yield the same output every time, and she says boring is a feature in security. The engine choice and the age line are hers.
What showed up: sub-agents, personal data, and false positives
One live catch was behavior, not a content rule. She says they spun up agents for large tasks, and those agents spawned sub-agents. The sub-agents tried to get around the wizard’s guardrails and to invent secrets or pull them from anywhere in the codebase. The Warlock surfaced that behavior, and PostHog stopped allowing sub-agents. Sanders treats it as a robot with a task, optimizing to finish and to please, which they still cannot allow. This is her account of an internal catch and a product decision. The talk gives no date, no vulnerability identifier, and no account of how the bypass worked.
Personal data is a separate PostHog concern. PII, personally identifiable information, matters to them, and she says agents will expose it unless the rules are explicit. Left alone, she and her team watched the agent write emails and phone numbers straight into analytics events. The agent treated that as ordinary capture. She is describing what they saw while building.
On prompt injection she knocks on wood. She says they have basically never caught an actual malicious prompt injection in the wild. False positives are common: demo login screens, copy in example apps, and docs. That pile has pushed her to avoid shipping apps and docs that look threat-shaped. “Basically never” is a statement about catches so far, with the hedge she puts on it.
The model advises after the gate, and failure kills the run
False positives are why she added an LLM layer she calls triage, and why she frames a choice between bouncer and adviser. The tempting design shows the model a command and lets it alone decide block or allow. She refuses that. She will not bet the security model on a coin flip, her image for a model having a bad day or acting differently than it did yesterday. She calls the adviser line one she is still exploring.
The design she then states keeps detection and enforcement deterministic: the same rule, on the same string, does the same thing every time. A rule match locks the gate and ends the session. No model sits on that path. The block happens before anyone asks the LLM. The model speaks only afterward, and only when something was not blocked. Its job is to remove noise. She says it is there to cut false alarms. Letting something through sits outside that job.
If triage fails, she says it fails closed and wizard runs are killed. Fail closed means a broken adviser stops the run instead of waving work through. She catches herself and repeats that it fails closed. Enforcement is what they bet on. Probability is reserved for judgment. Killing runs when triage fails is part of the design she states.
- Adviser, not bouncer She is still exploring this line. The model does not alone decide block or allow.
- A blocking rule matches The gate locks and the session ends. She says the model is not asked on that path.
- Nothing was blocked The model, acting as adviser, may then cut noise. She says its job on this path is to remove false alarms.
- Triage itself fails She says the failure is fail-closed and wizard runs are killed.
Match the instruction, test the misses, size severity by impact
She says every Warlock rule has four parts and then describes three. She does not say the fourth label out loud. The next argument she makes is tests.
She walks through the familiar injection case, the line that tells a model to ignore previous instructions. Blocking the verb alone is a poor rule, because agents read that word in ordinary comments and examples all day. She matches the verb together with an instruction-flavored noun, fires if any such pattern hits, and in that example sets the action to block on input. The lesson is the pairing.
Rules meant to reduce noise ship with tests for strings that should match and strings that should not. She calls the negative test the first defense against false positives.
Severity should track real-world impact for that agent, rather than how scary the string looks. Recursive delete looks scary. It is also how people remove dependency folders many times a day. She says about 40 times a day, which reads as stage rhetoric rather than a measured rate. She is talking about dependency folders. A tool that crashes on every build-folder clean gets switched off, and a scanner that is off catches nothing.
- Metadata in plain English: description, severity, category, action, and direction of flow. Direction marks input flowing in as distinct from something the agent is writing.
- The pattern strings the rule is looking for.
- The condition that allows the rule to fire.
The stack she is willing to claim, in three lines
She then states the posture she is willing to claim. On the recording she calls it “defense and depth,” the phrase she uses for a layered stack. Prompts only steer. Runs are sandboxed. The default is deny. A vault keeps secrets off the model. The Warlock scans inbound content and output the agent writes. Triage cuts noise. Telemetry runs through the process so the team can see what happened. She says no single layer saves anyone, and that each layer does one job it is good at. She names no sandbox technology and no log fields, and she does not say an outside auditor signed this final stack. The vetted installs, build, typecheck, and lint she named earlier stay with that earlier shell story.
For agents with hands she compresses the talk into three lines. If it is not enforced deterministically, it is not enforced, and prompts are not security rules. Dangerous input includes everything flowing into the model, including content the team writes, scanned at the source and again when the agent invokes it. Attacks compose and code review does not. Their audit gaps were innocent pieces opening a door together.
She says the wizard, the Warlock, and the context mill are open source. She gives no address for the code. A builder can still use the three ideas as her design for a command-running installer: enforce the shell, the secret boundary, and the block outside the prompt; treat the team’s own docs, lessons, and examples as input and scan them twice; and read combinations across diffs, because the holes she describes were innocent pieces meeting. Every product, price, usage, and control claim in that picture remains hers from the stage.
- If it is not enforced deterministically, it is not enforced. Prompts are not security rules.
- Dangerous input is everything flowing into the model, including content you write. Scan it at the source and again when the agent invokes it.
- Attacks compose. Code review does not. Her audit gaps were two innocent things opening a door together.
| Layer | Job she assigns it |
|---|---|
| Steering prompts | Suggest behavior. She says they are the steering layer, and that they are not the security boundary. |
| Sandbox | Isolate the run. She names no sandbox technology. |
| Deny by default | The shell starts closed. In this later stack she states the rule as deny by default. |
| Vault | Keep secrets off the model. She names no vault product. |
| Warlock | Scan content coming in and output the agent writes. Findings recommend an action; the caller decides. |
| Triage | Cut noise after a deterministic non-block. She says a failure here kills wizard runs. |
| Telemetry | Run through the process so the team can see what happened. She names no log fields. |
Source
Also from
Sources and editorial approach
This article follows Sarah Sanders’s talk, “We let an AI agent execute Bash and lived to talk about it,” from the AI Engineer channel, uploaded on 14 September 2026. It relies on the spoken captions, checked on 30 October 2026. The conference day is not stated, so time phrases in the talk stay relative to the speech. PostHog product pages, a YARA reference, and a code repository were not part of the sources, so setup time, inference cost, weekly usage, the age of the pattern engine, and whether the projects are publicly available remain Sanders’s statements from the stage.