A Parallel.ai employee (GitHub @NormallyGaussian, commit email mharris@parallel.ai) submitted 161 pull requests across 14+ open-source agent projects adding Parallel as a web search backend. Of the ten that merged, one disclosed the employment relationship. In NousResearch’s Hermes Agent the change made search.parallel.ai/mcp the zero-config default, so a fresh install with no API key and no configuration sent every web_search and web_extract call to a third party. Founder teknium1 merged it in 4.5 hours with zero reviews on 11 June; it was reported on 12 June, triaged P3, “cosmetic, nice to have”, and reverted on 14 June. If you run Hermes or OpenClaw, set your web backends explicitly and check your egress logs.
On 12 June a Hermes Agent user filed issue #45058 with an unglamorous observation: their agent was making outbound calls to search.parallel.ai. They had configured no web backend. They held no API key for anything. The traffic went out regardless.
That is the whole vulnerability. There is no memory corruption, no injected payload, no obfuscated dependency. Someone changed a default value in a config resolver, and roughly a fifth of a million stars’ worth of installed agent quietly acquired a new upstream.
What actually changed
Before commit e0e2571, Hermes Agent’s backend auto-detection fell through to firecrawl when nothing was configured. Firecrawl needs a key, so the call failed at invocation time. Ugly, but honest: the tool told you it wasn’t set up.
After the commit, the terminal fallback became Parallel’s free hosted Search MCP. No PARALLEL_API_KEY required, because Parallel made the endpoint keyless in April. So the failure mode inverted. Instead of erroring, the agent worked, and every query went to a company the user had never heard of. Two follow-up commits (93764b9, 0a5762c) hardened the default against override.
The provenance is where it gets interesting. The change arrived as PR #34971 from @NormallyGaussian and was closed unmerged. Days later teknium1, the NousResearch founder, opened PR #43798 titled “Salvages #34971 by @NormallyGaussian with authorship preserved,” and merged it 4.5 hours later with zero reviews and zero comments. The commit lists Matt Harris <mharris@parallel.ai> as author and Teknium as committer. Part of the same diff added "mharris@parallel.ai": "NormallyGaussian" to scripts/release.py, so the employer domain is sitting in the repo’s own author map.
@NormallyGaussian’s GitHub bio reads “Currently at @parallel-web.” The PR description never mentioned it.
One contributor, 161 pull requests
An anonymous researcher documented the pattern in a gist on 14 June. Every one of @NormallyGaussian’s 161 PRs is Parallel-related. Zero non-Parallel contributions. Ten merged across six repos, and exactly one, agno #7857 (“Note: I work for Parallel.”), disclosed the relationship.
OpenClaw shows the persistence. Six PRs between January and March, all rejected. Then #85158 landed on 22 May with zero reviews, and the next three sailed through, including #90849: “add free Parallel Search MCP as the zero-config default web_search provider.” Auto-detect order 76, deliberately ahead of DuckDuckGo’s 100.
Parallel’s April launch post for the keyless MCP named its targets outright: “free by default for agents and AI tools like Cursor, Claude Code, OpenClaw, Hermes Agent, and OpenCode.” Same post ships a copy-paste prompt instructing your coding agent to install Parallel into its own MCP config. The company also hosts parallel.ai/agents.md, a page written for agents to read. The distribution channel is the agent itself.
OpenClaw’s review bot called it. A human overrode it.
On 6 June, OpenClaw’s clawsweeper Codex bot posted a full analysis on #90849 flagging two P1 risks:
Existing no-provider/keyless web_search users would silently move from DuckDuckGo to Parallel’s hosted Search MCP and a new outbound host unless maintainers explicitly accept that default change.
Its verdict on whether this was the right approach: “No, not as-is.” Its recommended option: land the provider as explicitly selectable first. Its security section cleared the code itself while noting “the default-host switch remains a compatibility/privacy merge risk.”
Merged the next day by davemorin. Zero human reviews.
Why a security team should care
Three things, in ascending order of severity.
Query content is data egress. Agent search queries carry internal hostnames, error strings, package versions, customer names, and half-written code. A default that ships them to an unauthenticated endpoint creates an undeclared data processor in every environment running the tool. There is no account, no contract, no DPA, and no way to ask what was sent.
Search results are a write channel into the context window. Whoever answers web_search decides what text the model reads and acts on. That is the same lethal trifecta shape: untrusted content, private data access, and an outbound path, with the untrusted-content leg handed to a default nobody chose. Compromise the search provider and you get direct write access to the reasoning of every agent that fell through to it.
Defaults are invisible to your tooling. No scanner models “which URL does the config resolver terminate at” as a trust boundary. SCA watches dependency manifests; secret scanners watch for keys. A one-line change to auto-detect ordering, submitted by a helpful contributor with a real name and a plausible commit history, passes every gate you have. In a repo carrying 5,000+ open PRs, the small config change is the least-scrutinised diff in the tree, and the harness is the security boundary now.
Triaged as cosmetic, fixed in two days
Hermes maintainers labelled #45058 P3, a priority whose description reads “cosmetic, nice to have.” The issue drew 19 👍 and 10 😕, plus comments like vektorprime’s: “This is a huge concern. This organization must not be allowed to play us for their profit.”
Credit where due: two weeks ago, on 14 June, teknium1 merged PR #46350, removing the keyless fallback and restoring the requirement for explicit configuration. Three days from merge to revert is a good number.
The residue is the part that lasts. Five copycat PRs from unrelated developers are now open or merged in other projects, one citing “Hermes preference order” as justification and another “modeled on OpenClaw’s equivalents.” A default that survives a fortnight in a popular repo becomes precedent everywhere else.
If you run Hermes Agent, set your web backends explicitly in every profile, since explicit config stops auto-detect before it can reach a keyless fallback:
# ~/.hermes/config.yaml and ~/.hermes/profiles/*/config.yaml
web:
backend: searxng
search_backend: searxng
extract_backend: ddgsSearXNG and DDGS are search-only, so web_extract will fail cleanly. That is the point. Blocking the silent route first, sorting out extract on your own terms second.
Then go read your egress logs. The question worth asking about an agent has moved from what its code does to who it talks to when you never told it to talk to anyone.
Sources
- NousResearch/hermes-agent, issue #45058: “web_search/web_extract silently routes to Parallel.ai without user opt-in” (12 June 2026)
- Gist: “Parallel.ai’s undisclosed PR campaign across 14 open-source agent frameworks” (14 June 2026)
- OpenClaw PR #90849, including the
clawsweeperCodex review of 6 June 2026 - Parallel, “Parallel Search is now free for agents via MCP” (23 April 2026)
- r/hermesagent discussion thread
Related on this blog
- Three Indirection Steps From a Reverse Shell: why anything that writes into an agent’s context is a trust boundary
- Agent Harnesses: A Standard for a Word Nobody Agrees On: the config layer that decides what your agent is allowed to reach