Back to skill

Security audit

Eir Daily Content Curator

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent daily news-curation skill, but it needs review because it schedules persistent agents, fetches arbitrary URLs, stores API keys, and can post or shape Eir account content without tight safeguards.

Install only if you are comfortable with a scheduled agent searching the web, crawling selected URLs, storing local API keys, and posting generated content to an Eir account. Use a dedicated workspace, restrict config file permissions, review or remove the cron footer, avoid enabling personalization or interest sync unless intended, and prefer allowlisted public crawl/search endpoints.

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 (5)

T01 · Skill Instruction Hijacking

Error
Location
references/eir-setup.md:50
Finding

Persistent branded content injection into scheduled user-facing briefs

Content
View full analysis
**Tip:** End the brief with a link to [heyeir.com](https://www.heyeir.com) so readers can explore more content on the Eir canvas. ``` The cron message is loaded by an isolated agent on every scheduled execution. It therefore changes future user-facing output by requiring an external promotional call to action unrelated to the substantive news-curation result. Although scheduling a user-requested news pipeline is a legitimate feature, mandating branded promotional output is not necessary for that function. The behavior should be optional and clearly disclosed at configuration time. ### Attack Path 1. The user follows the documented Eir cron setup. 2. A persistent daily job is registered with the supplied agent message. 3. On each execution, the isolated agent compiles the user's brief. 4. The agent is instructed to append the fixed Eir promotional link. 5. User-facing output is repeatedly altered without a per-run request or confirmation. ### Impact Assessment The issue does not provide operating-system privileges or code execution. Its scope is control over persistent user-facing agent output. It can cause undisclosed promotion, reduce output integrity, and establish a pattern in whi ...[truncated 88 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/pipeline/crawl.py:205
Finding

Unrestricted candidate URL fetching permits server-side request forgery

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
scripts/pipeline/task_builder.py:190
Finding

Untrusted crawled content is embedded directly into agent generation instructions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pipeline/eir_post.py:25
Finding

Unrestricted API endpoint overrides and redirects can expose Eir bearer credentials

Content
View full analysis
dict: """Load Eir API config from env vars or config file.""" api_url = os.environ.get("EIR_API_URL") api_key = os.environ.get("EIR_API_KEY") if api_url and api_key: return {"apiUrl": api_url, "apiKey": api_key} # Fallback: config file for path in [ Path(os.environ.get("EIR_CONFIG", "/dev/null")), CONFIG_DIR / "eir.json", SKILL_DIR / "config" / "eir.json", ]: if path.exists(): try: return json.loads(path.read_text()) except (json.JSONDecodeError, KeyError): continue return {} def get_api_url() -> str: """Return base API URL without trailing /api suffix. Normalizes both old (https://api.heyeir.com) and new (https://api.heyeir.com/api) formats to the same base.""" config = load_config() url = config.get("apiUrl", "").rstrip("/") # Strip /api suffix if present — callers add /api/oc/... themselves if url.endswith("/api"): url = url[:-4] return url ``` Authenticated requests then attach the bearer token to the resulting URL: ```python def api_request(method, url, data=None, api_key=""): """Make API request with retry.""" body = json.dumps(data, ensure_ascii=False).encode() if data else None for attempt in range(3): try: req = urllib.request.Request( url, method=method, data=body, headers={ "Authorization": "Bearer " + api_key, "Content-Type": "a ...[truncated 1949 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/connect.py:49
Finding

API credentials are persisted without explicit owner-only file permissions

Content
View full analysis
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (48)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description underspecifies that the skill builds internal task bundles, manages manifests/state, performs deduplication, and can report results back to an API. These backend workflow and reporting behaviors expand the data flow and persistence surface beyond what a user would expect from a simple daily briefing skill.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
81% confidence
Finding

A documented destructive endpoint that disconnects and revokes the API key can be dangerous if exposed to an LLM-driven agent without strong confirmation and authorization checks. In this skill context, an agent handling natural-language requests could be induced to call the disconnect action accidentally or via prompt manipulation, causing denial of service and loss of integration state.

Content

Scanner excerpt · references/eir-api.md (reported line 25)May include surrounding context.

md
**Response:** `{ "apiKey": "eir_oc_xxx", "userId": "u_abc123" }`

### DELETE /oc/connect
Disconnect and revoke API key.

### POST /oc/refresh-key

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

The delete-content endpoint enables irreversible removal by id or contentGroup, creating a broad destructive capability that an agent could misuse if prompt-injected or if identifiers are guessed or mishandled. Because this skill automates curation and content publishing, accidental or malicious deletions could wipe large portions of curated output and disrupt the user's content pipeline.

Content

Scanner excerpt · references/eir-api.md (reported line 167)May include surrounding context.

md
### GET /oc/content/:id
Read back a content item.

### DELETE /oc/content/:id
Delete by id or contentGroup.

### POST /oc/curation/miss

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 · references/interest-extraction-prompt.md (reported line 87)May include surrounding context.

}

text

**Output rules:**
- 8-15 topics maximum
- Each topic: `label` (human-readable), `keywords` (search terms), `freshness` (how recent the content should be)
- De-identified labels only — no personal details

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
96% confidence
Finding

This function constructs and returns a full LLM prompt by directly embedding untrusted task fields such as source_text, reader_context, suggested_angle, and even a task-supplied writer_prompt. In a content-curation skill, those inputs are likely derived from web content or upstream files, so an attacker can inject prompt instructions that override system intent, manipulate output, exfiltrate hidden context included in the prompt, or steer the agent into unsafe generation behavior.

Content

Scanner excerpt · scripts/pipeline/generate.py (reported line 102)May include surrounding context.

python
"\nReader context:\n" + reader_context if reader_context else "",
        source_text)

    return prompt


def save_generated(content_data, suffix=""):

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill declares environment variables and clearly instructs the agent to perform filesystem and network operations, but it does not explicitly constrain tool scope via permissions or allowed-tools. This increases the chance of over-broad agent execution, especially because the workflow includes reading/writing local files, calling external APIs, crawling URLs, and storing credentials.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

The skill is designed to send queries and possibly user-defined interests to external search providers, which is an intentional external transmission of potentially sensitive preference data. In a personalization context, this increases privacy risk because interest topics, freshness windows, and query content can reveal user profile information to third parties.

Content

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

md
"mode": "standalone",
  "language": "en",
  "search": {
    "search_base_url": "https://api.search.brave.com/res/v1",
    "search_api_key": "YOUR_BRAVE_API_KEY"
  }
}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
82% confidence
Finding

The documented use of Brave, Tavily, SearXNG, and Crawl4AI expands outbound data flows to multiple external or semi-external services. Because the skill performs personalized content curation, these requests may expose user interests, selected URLs, and browsing targets beyond the local environment.

Content

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

md
Search provider examples:
| Provider | `search_base_url` | Get API key |
|----------|-------------------|-------------|
| Brave Search | `https://api.search.brave.com/res/v1` | [brave.com/search/api](https://brave.com/search/api/) |
| Tavily | `https://api.tavily.com` | [tavily.com](https://tavily.com/) |

> **Want richer results?** Install [SearXNG](https://docs.searxng.org/) and/or [Crawl4AI](https://github.com/unclecode/crawl4ai) locally. Add `searxng_url` and `crawl4ai_url` to your search config — they work as fallback or primary search/crawl providers.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This file states that lang must be either "zh" or "en", which imposes a language policy constraint in natural language. Because the document does not explain that this is a user-selected option or a narrowly justified regional limitation, it may violate the policy against forcing a specific language or locale without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The API reference describes transmitting user interests, profile attributes, and generated content to a remote service, but it does not warn that sensitive personalization data and produced summaries will leave the local agent boundary. In a content-curation skill, this matters because interests, language preferences, and uploaded content can reveal user profiling data, and operators may deploy the skill without understanding the privacy implications.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The rules section states that the lang field is required and limited to only en or zh, which is a natural-language locale constraint. Because the document does not indicate user opt-in, language selection flexibility, or a region-specific justification, this may violate the policy against forcing a specific language/locale without user choice.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented behavior expands a news-curation skill into collecting inferred interests from user conversations and mutating the user's interest profile via POST /oc/interests/add. That creates a privacy and authorization risk because conversational data is being repurposed for profile changes without an explicit, narrowly scoped consent step, and it can let the agent persistently shape future recommendations based on incidental or misinterpreted chat content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The guide specifies --tz "Asia/Shanghai" for all scheduled jobs, which imposes a specific locale/timezone setting in natural-language setup instructions. Because no opt-in, alternative, or justification is provided, this appears to violate the policy against forcing a specific locale without user choice.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a skill for learning interests, searching the web, and delivering curated news summaries. This file instead pairs the installation with an external Eir service, exchanges a pairing code for an API key, and writes persistent credentials to disk, which is not part of the described end-user curation behavior.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/eir-api.md (reported line 3)May include surrounding context.

md
SCRIPT_DIR = Path(__file__).resolve().parent
CONFIG_DIR = SCRIPT_DIR.parent / "config"
CONFIG_PATH = CONFIG_DIR / "eir.json"
API_BASE = "https://api.heyeir.com/api"


def main():

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/eir-setup.md (reported line 77)May include surrounding context.

md
SCRIPT_DIR = Path(__file__).resolve().parent
CONFIG_DIR = SCRIPT_DIR.parent / "config"
CONFIG_PATH = CONFIG_DIR / "eir.json"
API_BASE = "https://api.heyeir.com/api"


def main():