Why this verdict
- suspicious: finding mcp-server:.:daily-worker/src/index.ts:530:SUPPLY
- suspicious: finding mcp-server:.:pyproject.toml:38:SUPPLY
Security findings 2
Supply chain
highContextual risklow confidenceThe package depends on the unpinned `agentprod`, with a uv source pointing to a local path outside the repository (../agentprod). The code that is installed is therefore unverifiable.
"agentprod",
conceal:remotevector:metadata
Counter-argument considered
agentprod is an unpinned runtime dependency whose uv source is a local path outside the repo. A wheel install from an index would resolve whatever package carries that name, and nothing cited mitigates this.
Supply chain
mediumContextual risklow confidenceThe daily worker's empty-state HTML page loads the Tailwind CSS script from a mutable third-party CDN URL with no pinning or integrity check, so the remote code can change without notice (low-impact, common practice).
<script src="https://cdn.tailwindcss.com"></script>
conceal:remotevector:code
Counter-argument considered
The page loads an unpinned third-party script with no integrity check. Impact is low and it is served to browsers rather than agents, but no cited carve-out or mitigation neutralizes it.
Open questions 2
What the analysis could not settle from the code alone.
Which tool or caller supplies the webhook URL and the alert body to send_alert, and does the body include anything beyond public DART filing data?
Data exfiltration
[file request src/koreanpulse/server.py] Where is send_alert called, who controls the webhook URL, and what data goes into the alert title and body?
Data exfiltration
Refuted findings 3
Candidates the review stage examined and rejected, kept for transparency.
Data exfiltration
criticalRefutedlow confidenceThe cache worker sends the OpenAI API key and user-supplied text to a Cloudflare AI Gateway proxy URL instead of api.openai.com; the gateway is undeclared in the manifest but disclosed in a code comment as a region-block workaround.
"https://gateway.ai.cloudflare.com/v1/520ed8d88fdd95e30af7d0a0e81c1706/koreanpulse/openai/chat/completions",
Why it was refuted
The key is the operator's own env OPENAI_API_KEY for the wrapped OpenAI service. It goes to an operator-controlled Cloudflare AI Gateway route, a disclosed proxy for OpenAI, so this is the env-API-key carve-out and not exfiltration.
Data exfiltration
highRefutedlow confidencesend_alert posts title/body content to a caller-supplied Discord/Slack/Telegram webhook URL, which could send data off-host to an attacker-chosen channel if the URL or content is influenced by untrusted input; no caller is shown here, so the source and destination are not established.
return await client.post(url, json=payload)
Why it was refuted
The webhook sender is a declared alert feature. detect_channel only accepts Discord, Slack and Telegram URL patterns and rejects everything else as unsupported, so the destination is allow-listed. The payload is only title/body, and no tool in the shown server.py calls send_alert with untrusted or sensitive data, so there is no source-to-sink chain.
Tool poisoning
highRefutedlow confidenceThe tool docstring, which is MCP tool metadata, directs the client LLM how to handle another tool (not to fall back to `track_korean_filings`) and to relay paywall text verbatim; this conditions agent tool use but appears to be a paywall UX instruction.
Do NOT silently retry with `track_korean_filings`
Why it was refuted
The docstring text is a paywall UX instruction. It tells the client to relay the license notice and not to fall back to a free tool that would return a misleadingly empty answer. It does not touch credentials, exfiltrate data, or hide behavior, and it is openly declared in the tool description, so it is benign.
Coverage gaps 3
Parts of the artifact the static analysis could not fully examine.
manifest_unparseable server configuration is not an object
landing/public/.well-known/mcp.json
request_unanswered request.0: behavior-chains.9/req-alert-callers: resolved_clean: citation not shown or quote not in it
invalid_refuter refuter results do not match requested findings