← Security advisories MOORAI-2026-001

Inbound WebFetch and WebSearch content was never scanned

Severity: Medium Fixed and released in 0.79.0 Vendor-assigned identifier · no CVE Published 7 September 2026

MoorAI's agent hook ran only on the PreToolUse event. PreToolUse fires before a tool runs, so at the moment a WebFetch was inspected the page did not exist yet. The outbound request — the URL and the prompt — was scanned; the content that came back and went into the model's context never was. WebSearch results were in the same position. Both are the delivery path for indirect prompt injection, and both were invisible to detection.

IdentifierMOORAI-2026-001 — vendor-assigned by glick.run. Not a CVE.
CVENone. No CVE has been requested or assigned for this advisory.
ProductMoorAI agent (open-source community edition, AGPL-3.0)
Componentcli/moorai-hook.mjs — hook event registration
Affected versionsAll releases up to and including 0.78.0
Fixed in0.79.0
StatusFixed and released in 0.79.0. Commit ad3d817 is on the agent repository's published main branch, and later 0.79.x releases are tagged.
Fixing commitad3d81700f6eedf10e2cb6f50e5f3390f83fe10c ↗
Classified asAMTSO agentic testing vector 2 — indirect input
Published7 September 2026
01 — impact

What an attacker gets

An attacker who controlled a page an agent was told to fetch, or who could influence a search result the agent read, could put instructions in front of the model with no MoorAI finding raised. Because the gap was in coverage rather than in a decision, it produced silence rather than a wrong answer: no alert, no telemetry, nothing in the operator's console.

What has to be true first

02 — severity

Why we rated it medium

Medium

No control was defeated and nothing an attacker did made MoorAI weaker — the surface was simply not covered, so attacks delivered through fetched web content produced no signal at all. It is rated medium rather than low because that delivery path is the main route for indirect prompt injection, and rated below high because the fix itself is detection, not prevention: the hook that closes it runs after the tool has already run.

We assign a qualitative severity and show the reasoning rather than publishing a CVSS vector. We are not a CVE Numbering Authority and have not had this scored by one, so a numeric score here would carry a precision it has not earned. If you disagree with the rating, the reasoning above is the thing to argue with — tell us and we will publish the correction.

03 — technical detail

What actually happened

Everything below is taken from the diff in commit ad3d817 ↗. The repository is public and AGPL-3.0 — read it rather than take our word for it.

Why the outbound scan could not see it

PreToolUse is the only event the hook registered. It runs before the tool executes, which is exactly what makes it able to deny an action — and exactly what makes it blind to a response. The source that shipped in 0.78.0 states the limit at the WebFetch branch itself rather than implying it: PreToolUse fires before the fetch, so inbound page content is not scannable from this surface, and that is the vector-2 delivery path.

The fix

0.79.0 registers a PostToolUse hook for WebFetch and WebSearch. WebSearch is included because snippets are attacker-influenceable through SEO poisoning and land in the model's context in exactly the same way as a fetched page.

Which field the response arrives in

Three sources disagreed on the name of the field carrying the tool result: an embedded reference document said tool_response, the hooks UI said inputs/response, and a documentation lookup said tool_result. The contract was settled against the runtime schema in the shipped agent host binary, which parses the payload and names it tool_response. Reading the wrong key would fail silently and permanently — the same defect class this advisory is about — so the handler reads tool_response with tool_result, tool_output and response as fallbacks.

This closes detection, not prevention

A PostToolUse hook cannot un-run the tool, and the permission decision field is PreToolUse-only — emitting it from PostToolUse is silently ignored. So content that arrives through a fetch is now seen and reported; it is not blocked before the model reads it. We state that on the methodology page too, and we do not claim prevention on this vector.

What was measured

Through the real hook rather than the library: output-stage vector-2 attacks reaching a content-free alert went from 0 of 24 to 22 of 24 (91.7%). PreToolUse latency was unchanged at a 35.0 ms median against 35.8 ms before (n=30). The new PostToolUse work adds a 34.9 ms median, off the critical path. Scanning at the output stage was chosen by measurement, not by analogy: on those 24 attacks, output caught 22, file caught 16, and their union caught 22 — file's catches are a strict subset, so scanning both buys nothing.

The cost we did not tune away

8 of 11 benign controls also alert on this surface. Those are notify-level: across the set the decisions are 10 allow and 1 ask, and nothing blocks. The obvious trim was investigated and rejected — excluding the data-loss class costs 13 attacks to save 5 false positives, because a vector-2 payload usually reads "send this to <address>". Eleven benign samples is far too small a denominator to scope detectors against, so this waits for a real benign web-content corpus rather than being patched to look better.

What was not proven

The live payload was never observed — a nested agent run failed authentication — so the field names come from the runtime schema rather than from a captured message, mitigated by the multi-key fallback above. A hard block decision from this event was not tested against a live host. The mechanism that could redact a page before the model reads it is deliberately unused: parallel hooks race on it, last write wins.

04 — timeline

Timeline

6 September 2026

0.78.0 (commit 2f66be3) puts WebFetch on a PreToolUse matcher for the first time and records in the source that inbound content is not scannable from that surface.

6 September 2026

The gap is closed in commit ad3d817, released as 0.79.0. We do not hold a separate discovery timestamp: this was found and fixed in one development session.

7 September 2026

This advisory published.

05 — credit

Credit

Found internally during MoorAI development. No external reporter. If you are the first person outside the project to report an issue we did not already know about, you will be credited here by the name you choose.

Our coordinated disclosure policy sets out how to report something, what we commit to in return, and the safe-harbour terms we work under.

All advisories Read the fixing commit ↗ Report a vulnerability → security.txt →

MOORAI-2026-001 is a vendor-assigned identifier published by glick.run for a defect in our own product. It is not a CVE identifier, and no CVE has been requested or assigned. Version ranges refer to the MoorAI agent's own releases. This advisory describes what the fixing commit changed and states what the fix does not cover; where a measurement is quoted it comes from a harness in the agent repository, and the method behind those harnesses is on the methodology page.

glick.run — AGPL-3.0