Back to skill

Security audit

AI Daily Digest

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real RSS digest generator, but it stores an API key in a predictable plaintext home-directory file and runs an unpinned package at execution time.

Review before installing. Use environment variables instead of saving API keys, avoid custom OpenAI-compatible endpoints unless you control and trust them, prefer a preinstalled or pinned Bun runtime, and remove `~/.hn-daily-digest/config.json` if it contains a real key.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T01 · Skill Instruction Hijacking

Note
Location
SKILL.md:60
Finding

Mandatory Promotional Content Injected into Agent Responses

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:159
Finding

Gemini API Key Persisted in a Predictable Plaintext File

Content
View full analysis
~/.hn-daily-digest/config.json << 'EOF' { "geminiApiKey": "", "timeRange": , "topN": , "language": "", "lastUsed": "" ``` The broader configuration instructions also require the Agent to inspect and parse this predictable file before execution. ### Technical Analysis The Skill directs the Agent to store a long-lived Gemini API key directly in JSON under the user's home directory. The command does not establish restrictive directory or file permissions, does not use an operating-system credential store, and does not ask whether the user consents to persistent secret storage. The resulting permissions depend on the user's current `umask`. On permissively configured systems, the credential may become readable by other local users or processes. Even when filesystem permissions are restrictive, the key remains exposed to plaintext backups, support bundles, accidental uploads, and software that scans user configuration files. Persisting the key is not required for the Skill's core functionality because the implementation already supports receiving credentials through environment variables. ### Attack Path 1. The user supplies a Gemini API key. 2. After execution, the Agent creates `~/.hn-daily-digest/config.json`. 3. The API key is written into the file as an unencrypted JSON string. 4. A local process, another user permitted to read the file, backup operator, or accidentally published archive obtains the file. 5. The exposed key is reused to make Gemini API requests under the victim's quota or billing account. ### Impact Assessment Successful exploitation discloses the stored Gemini credential. An attacker may consume the associated API quota, incur charges where billing is enabled, access capab ...[truncated 222 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:146
Finding

Unpinned Package Download and Execution Through npx

Content
View full analysis
" export OPENAI_API_KEY="" export OPENAI_API_BASE="https://api.deepseek.com/v1" export OPENAI_MODEL="deepseek-chat" npx -y bun ${SKILL_DIR}/scripts/digest.ts \ --hours \ --top-n \ --lang \ --output ./output/digest-$(date +%Y%m%d).md ``` The environment requirements reiterate that Bun is automatically installed through `npx -y bun` at `SKILL.md:211`. ### Technical Analysis The command asks `npx` to resolve, download, and execute the package currently published under the name `bun`, without specifying an exact version or integrity digest. The `-y` option suppresses the installation confirmation. This makes runtime behavior dependent on mutable external registry state. A compromised maintainer account, registry compromise, or malicious future package release could cause code that was not present during the audit to execute locally. The process also receives the exported AI credentials, increasing the consequence of dependency compromise. This is a supply-chain weakness rather than evidence that the currently resolved package is malicious. ### Attack Path 1. An attacker compromises the relevant package publication channel or publishes a malicious version that is selected by default. 2. A user invokes the Skill. 3. `npx -y bun` downloads the mutable package without interactive confirmation. 4. Package installation or startup code executes with the user's local privileges. 5. The malicious package can access the process environment, including exported API keys, and any files accessible to the invoking user. ### Impact Assessment A compromised dependency could execute arbitrary code with the privileges of the user running the Skill. This could expose Gemini and OpenAI-co ...[truncated 214 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/digest.ts:398
Finding

Custom OpenAI-Compatible Endpoint Can Receive API Credentials and Prompt Data Without Validation

Content
View full analysis
{ const normalizedBase = apiBase.replace(/\/+$/, ''); const response = await fetch(`${normalizedBase}/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}`, }, body: JSON.stringify({ model, messages: [{ role: 'user', content: prompt }], ``` Related configuration flow at `scripts/digest.ts:1049-1052`: ```ts const geminiApiKey = process.env.GEMINI_API_KEY; const openaiApiKey = process.env.OPENAI_API_KEY; const openaiApiBase = process.env.OPENAI_API_BASE; const openaiModel = process.env.OPENAI_MODEL; ``` ### Technical Analysis `OPENAI_API_BASE` is accepted from the environment and used directly to construct a credential-bearing request. The implementation does not require HTTPS, validate the destination against an allowlist, reject loopback or private-network destinations, or request explicit confirmation before sending the bearer token and article-derived prompts to a custom host. The prompts include RSS-derived article titles, descriptions, and source names used for scoring and summarization. This content is intentionally sent to the chosen AI provider, but allowing an arbitrary endpoint without destination safeguards expands the network privilege beyond trusted providers. The fallback logic can also activate this endpoint after Gemini fails, meaning a configured fallback destination may receive data automatically rather than only when explicitly selected as the primary provider. ### Attack Path 1. An attacker or unsafe launcher controls `OPENAI_API_BASE`, or a user is persuaded to configure an attacker-controlled ...[truncated 1132 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/digest.ts:369
Finding

Gemini API Key Included in Request Query String

Content
View full analysis
{ const response = await fetch(`${GEMINI_API_URL}?key=${apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }], ``` ### Technical Analysis The Gemini API key is embedded in the URL query string. HTTPS protects the URL while it is transmitted between the client and the intended server, but complete URLs are commonly captured by application telemetry, reverse proxies, gateways, debugging tools, and error-reporting systems. Credentials in authorization headers are generally easier to redact and less likely to be included in routine URL logs. The static code does not itself print this request URL, so exploitation depends on surrounding infrastructure or tooling recording it. ### Attack Path 1. The Skill calls Gemini using a URL containing the API key in the `key` query parameter. 2. A proxy, gateway, runtime diagnostic component, or telemetry system records the complete request URL. 3. A person or service with access to those logs extracts the key. 4. The key is reused for unauthorized Gemini API requests. ### Impact Assessment Exposure permits use of the Gemini API within the compromised key's authorization, quota, and billing limits. Possible consequences include quota exhaustion, unexpected charges, and temporary denial of service for the legitimate user. This finding does not by itself provide access to unrelated host resources. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (17)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `scripts/digest.ts` | 主脚本 - RSS 抓取、AI 评分、生成摘要 |

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes network access, reads environment variables, and executes a script, but it does not declare an explicit tool scope such as permissions or allowed-tools. That mismatch weakens reviewability and policy enforcement because the actual runtime capabilities are broader than what the manifest communicates.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill persists geminiApiKey in ~/.hn-daily-digest/config.json in plaintext and does not clearly warn the user about credential retention risk. Plaintext API key storage can expose secrets to other local users, backup systems, logs, or later processes that read the home directory.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The skill transmits user-supplied API credentials and fetched article content to external services, including a configurable OpenAI-compatible endpoint and DeepSeek example base URL. External transmission is expected for this skill's function, but it is still security-relevant because users may not appreciate that third-party services receive feed content, prompts, and metadata.

Content

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

md
export GEMINI_API_KEY="<key>"
# 可选:OpenAI 兼容兜底(DeepSeek/OpenAI 等)
export OPENAI_API_KEY="<fallback-key>"
export OPENAI_API_BASE="https://api.deepseek.com/v1"
export OPENAI_MODEL="deepseek-chat"

npx -y bun ${SKILL_DIR}/scripts/digest.ts \

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using npx -y bun without a pinned version allows retrieval of whatever package/version is current at execution time. This creates a supply-chain risk where a compromised upstream package, typo-squat, or unexpected major-version change could execute arbitrary code in the agent environment.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The skill creates persistent state under ~/.hn-daily-digest, including configuration and timestamps, which can retain sensitive operational data across sessions. Session persistence increases exposure because secrets and usage metadata remain available after the run and may be accessed by unrelated processes or future tasks.

Content

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

Step 2b: 保存配置

bash
mkdir -p ~/.hn-daily-digest
cat > ~/.hn-daily-digest/config.json << 'EOF'
{
  "geminiApiKey": "<key>",

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The environment requirements again instruct use of npx -y bun without version pinning, reinforcing the same unbounded supply-chain exposure. Repeated unpinned installation increases the chance that users or agents execute unreviewed remote code as part of normal workflow.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/digest.ts (reported line 10)May include surrounding context.

ts
// ============================================================================

const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
const OPENAI_DEFAULT_API_BASE = 'https://api.openai.com/v1';
const OPENAI_DEFAULT_MODEL = 'gpt-4o-mini';
const FEED_FETCH_TIMEOUT_MS = 15_000;
const FEED_CONCURRENCY = 10;

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/digest.ts (reported line 1017)May include surrounding context.

ts
// ============================================================================

const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
const OPENAI_DEFAULT_API_BASE = 'https://api.openai.com/v1';
const OPENAI_DEFAULT_MODEL = 'gpt-4o-mini';
const FEED_FETCH_TIMEOUT_MS = 15_000;
const FEED_CONCURRENCY = 10;

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script hardcodes Chinese category labels and later defaults the CLI language to 'zh', causing generated reports and UI text to be produced in Chinese unless the user explicitly overrides it. This is a natural-language locale constraint applied by default rather than offered as an opt-in choice.

Content

No source excerpt is available for this finding.

Ssd 1

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Untrusted RSS titles and descriptions from dozens of external feeds are inserted directly into the scoring prompt with no instruction/data separation, escaping, or adversarial-content handling. A malicious feed can embed prompt-injection text that influences scoring, categorization, keyword extraction, or downstream model behavior, degrading integrity of the digest and potentially steering later processing.

Content

No source excerpt is available for this finding.

Ssd 1

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The summarization step passes raw external text and URLs into the model, creating a direct prompt-injection channel from remote content into generated summaries and reasons. Because this stage shapes the final published digest, a malicious feed can coerce the model to emit manipulated output, propaganda, unsafe links, or instructions, and poisoned summaries can propagate into subsequent highlight generation.

Content

No source excerpt is available for this finding.

Ssd 1

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Highlight generation relies on model-derived summaries that may already be poisoned by earlier prompt injection, and it does not distinguish trusted instructions from tainted upstream content. This creates a second-order injection path where a single malicious article can disproportionately bias the top-level 'today's highlights' narrative.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The lang variable is initialized to 'zh', so summaries and highlights are generated in Chinese unless the user supplies --lang en. This enforces a specific locale by default and does not obtain user opt-in first.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill sends fetched article titles, descriptions, links, and derived summaries to an OpenAI-compatible endpoint whose base URL is fully configurable via environment variable. That allows data to be transmitted to arbitrary third-party services or attacker-controlled inference gateways, creating a clear exfiltration path and weakening assurances about where external content and metadata are processed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest description presents the skill as generating digests with Chinese-translated titles, which imposes a language choice in the top-level skill behavior description. While later interactive steps offer Chinese or English output, the primary description still frames Chinese output as the default behavior without user opt-in.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes fetching RSS feeds, scoring/filtering articles, and generating a Markdown digest with translations and visual statistics. The code additionally appends a self-promotional message for a WeChat/public account brand, which is not part of the stated digest-generation behavior and changes the output's purpose from purely informational to partially promotional.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/digest.ts:1049