Back to skill

Security audit

HN Daily Brief

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent Hacker News daily-report helper, but it needs review because it can fetch arbitrary Hacker News-linked websites from the user's environment and can run scheduled retry jobs.

Install only if you are comfortable with scheduled runs fetching live Hacker News stories and third-party article URLs from the agent's network. Prefer running it in a sandbox or network-restricted environment, disable scheduling unless needed, and add URL validation or an allowlist before unattended use.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_hn_daily.py:30
Finding

Unrestricted Article Retrieval Enables Server-Side Request Forgery and Local Resource Access

Content
View full analysis
str: if not url: return "" try: req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) with urllib.request.urlopen(req, timeout=20) as r: raw = r.read(300_000).decode("utf-8", errors="ignore") except Exception: return "" raw = re.sub(r"", " ", raw, flags=re.I) raw = re.sub(r"", " ", raw, flags=re.I) txt = re.sub(r"<[^>]+>", " ", raw) txt = html.unescape(txt) txt = re.sub(r"\s+", " ", txt).strip() if len(txt) < 150: return "" return txt[:max_chars] ``` The externally controlled URL is passed to this function as follows: ```python for idx, st in enumerate(stories, 1): sid = st["id"] url = st.get("url") or f"https://news.ycombinator.com/item?id={sid}" snippet = fetch_article_snippet(url) comments_raw = collect_comments(st, limit=comments_limit) ``` ### Technical Analysis The article URL originates from Hacker News story metadata and is not trusted input. The code passes it directly to `urllib.request.urlopen` without validating: - The URL scheme. - The destination hostname or IP address. - The destination port. - Whether DNS resolution points to a private, loopback, link-local, reserved, or multicast address. - Redirect destinations. - Non-HTTP resource handlers supported by `urllib`. - Cloud instance metadata addresses. Consequently, a malicious or compromised Hacker News submission can cause the machine running the Skill to make requests from its own network context. Redirect handling can also bypass a su ...[truncated 1724 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:45
Finding

Untrusted Article and Comment Content Reaches the LLM Without Prompt-Injection Isolation

Content
View full analysis
--top --language --outdir /tmp/hn-daily-draft --materials /tmp/hn-daily-draft/HN-materials.json` - Script must only output `HN-materials.json` (no user-facing report body). - Use `HN-materials.json` as the only source for final writing. 4. LLM generation (required, prompt-driven quality): - Use a single strict prompt template to generate final report in selected `language`. ``` The materials file includes arbitrary article text and Hacker News comments: ```python "score": st.get("score", 0), "comments": st.get("descendants", 0), "by": st.get("by"), "time": st.get("time"), "snippet": snippet, "source_short": len(snippet) < 150, "comments_raw": comments_raw, "comments_short": len(comments_raw) == 0, ``` ### Technical Analysis Article pages and Hacker News comments are attacker-influenceable content. The collection process stores their text in `snippet` and `comments_raw`, and the Skill then instructs an LLM to use the resulting JSON as the source for final writing. The documented generation process does not explicitly require the model to treat all material fields as inert, quoted data. It also does not define a robust trust boundary that forbids following instructions embedded in article text or comments. Content such as “ignore prior instructions,” requests to reveal contextual data, or instructions to invoke tools may therefore be interpreted as model instructions rather than source material. The source/comment separation rules address report quality and factual provenan ...[truncated 1569 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The code clearly supports part of the declared workflow: it retrieves top Hacker News stories, fetches article snippets, gathers comments, accepts Top-N/style/language parameters, and persists output to a file. However, the declared purpose says the skill generates and delivers a daily report with article summaries and synthesized comment viewpoints in the user-selected language, plus optional index update. This code does not perform those higher-level reporting tasks. Instead, it produces a JSON 'materials' file intended for a separate mandatory LLM rewrite step, as indicated by the --materials help text and the stored requirements metadata. It also does not update any index, and 'language' is merely stored in output metadata rather than affecting summarization behavior. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description says the skill generates and delivers a Hacker News daily report with summaries and comment synthesis. This code chunk does not generate, fetch, summarize, translate, deliver, persist, or update any index. It is a standalone validator for an already-produced report file, enforcing minimum summary/comment lengths and anti-padding/repetition rules. That is a materially different primary purpose from the declared behavior, so this is a mismatch.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 55)May include surrounding context.

md
- Under concurrent retry profile: success can be achieved by primary run or any retry run; retries must skip if the report is already complete.
- If any required condition fails, treat run as failed (do not claim completion).

## Output rules
- Send only report body to user (no receipts/status metadata).
- Never send script draft markdown directly; user-facing report must come from LLM rewrite over materials JSON.
- Output must use one language only: the selected `language` for the run (no bilingual/mixed-language output).

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill specifies behavior requiring network access plus file read/write, but it does not declare any explicit tool scope or permissions boundary. That creates an under-constrained execution model where an agent may use broader capabilities than reviewers or users expect, increasing the chance of unintended data access, file modification, or outbound requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function default sets the language to "zh", which imposes a specific language/locale preference by default. While a command-line override exists later, the default behavior still forces Chinese output unless the user explicitly changes it.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The CLI argument for language defaults to "zh", meaning users who do not specify a language receive Chinese output automatically. This is a natural-language locale policy concern because the tool enforces a language choice by default rather than requiring opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code fetches external article content from arbitrary story URLs using HTTP requests, which transmits the host's network metadata and may access third-party sites beyond the Hacker News API. There is no confirmation prompt, log message, comment, or docstring warning the user that the script will contact external websites in addition to Hacker News.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.