Back to skill

Security audit

Smart Price Monitor

Security checks for vulnerabilities and agentic risk

Overview

This price-monitoring skill is mostly coherent, but it needs Review because its broad scraping scope and bundled scripts create avoidable local-file and dashboard-script risks.

Review before installing. Use it only for user-approved price or stock monitoring, avoid sensitive or authenticated pages, keep dashboards local unless the escaping issue is fixed, and do not run the scripts on untrusted monitor names or monitor IDs until path validation and HTML/script escaping are added.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dashboard_generator.py:92
Finding

Stored HTML and JavaScript Injection in Generated Dashboards

Content
View full analysis
\n' f'
{c["name"]}
\n' f'
\n' f' ${c["price"]:,.2f}\n' f' {change_arrow} {abs(c["change_pct"]):.1f}%\n' f' {stock_text}\n' f'
\n' f'
Deal Score: {ds}/100
\n' f'
\n' f' Low: ${c["low"]:,.2f}\n' f' Avg: ${c["avg"]:,.2f}\n' f' High: ${c["high"]:,.2f}\n' f'
\n' f'\n' ) ``` ```python chart_json = json.dumps(chart_datasets) ``` ```html ` sequence from terminating the surrounding script element. The remainder of the value can then introduce a new script or arbitrary HTML. The direct interpolation into the product card also permits stored markup ...[truncated 1483 chars]
Remediation
View remediation
... ``` ```javascript const chartData = JSON.parse( document.getElementById("chart-data").textContent ); ``` 3. Before embedding JSON in HTML, escape characters that are significant to the HTML parser, including `<`, `>`, and `&`. Also handle U+2028 and U+2029 where relevant. 4. Prefer a templating engine with contextual auto-escaping rather than constructing HTML through f-strings. 5. Add a restrictive Content Security Policy. Where practical, move inline JavaScript into a local static file and prohibit inline scripts. 6. Add regression tests covering names containing: ```text " ' < > & ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/price_collector.py:108
Finding

Path Traversal Through Unvalidated Monitor IDs

Content
View full analysis
list: """Load price history for a monitor.""" history_file = HISTORY_DIR / f"{monitor_id}.json" if history_file.exists(): return json.loads(history_file.read_text()) return [] def save_history(monitor_id: str, history: list): """Save price history for a monitor.""" ensure_dirs() history_file = HISTORY_DIR / f"{monitor_id}.json" history_file.write_text(json.dumps(history, indent=2, ensure_ascii=False)) ``` The CLI passes an unrestricted value into these functions: ```python elif cmd == "record": if len(sys.argv) < 4: print("Usage: record [in_stock] [seller] [shipping]") sys.exit(1) mid = sys.argv[2] price = float(sys.argv[3]) in_stock = sys.argv[4].lower() == "true" if len(sys.argv) > 4 else True seller = sys.argv[5] if len(sys.argv) > 5 else None shipping = sys.argv[6] if len(sys.argv) > 6 else None entry = add_price_entry(mid, price, in_stock=in_stock, seller=seller, shipping=shipping) ``` ### Technical Analysis The history filename is constructed by concatenating an unvalidated `monitor_id` with the `.json` suffix. `pathlib.Path` does not remove traversal components such as `..`. Consequently, an ID containing path separators can cause the resolved path to leave `HISTORY_DIR`. The `record` command does not verify that the supplied monitor ID matches the application's generated ID format or corresponds to an existing monitor. `add_price_entry()` first invokes `load_history()` and later `save_history()`, exposing both a read and a write path. The target must end in `.json` due to the hardcoded suffix, and an existing file must contain valid JSON ...[truncated 1746 chars]
Remediation
View remediation
str: if not MONITOR_ID_PATTERN.fullmatch(monitor_id): raise ValueError("Invalid monitor ID") return monitor_id ``` 2. Verify that the supplied ID belongs to an existing monitor before recording history. 3. Resolve and validate the final path to provide defense in depth: ```python base = HISTORY_DIR.resolve() history_file = (base / f"{monitor_id}.json").resolve() if history_file.parent != base: raise ValueError("History path escapes the configured directory") ``` 4. Apply validation consistently in `load_history()`, `save_history()`, removal operations, dashboard loading, and any future function that derives a filename from an ID. 5. Use atomic writes with restrictive file permissions to reduce corruption and unauthorized access risks. 6. Add tests for IDs containing `../`, absolute paths, alternate separators, encoded traversal forms, and valid-looking IDs with appended path components. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/dashboard_generator.py:128
Finding

Remote Chart.js Dependency Loaded Without Subresource Integrity

Content
View full analysis
``` The same remote script reference is included in the generated dashboard template and the example dashboard. ### Technical Analysis Every generated dashboard loads and executes JavaScript from a third-party CDN at viewing time. Although the URL specifies Chart.js version `4.4.1`, the browser does not verify the downloaded file against a trusted cryptographic digest because the script tag has no Subresource Integrity attribute. If the CDN account, hosted object, DNS resolution, TLS trust chain, or delivery infrastructure is compromised, a substituted script will execute with the same browser privileges as the dashboard itself. The dependency also means the dashboard is not actually self-contained, despite the documentation describing it that way. Opening the dashboard sends a request to the CDN and exposes network metadata such as the viewer's IP address, request time, and browser headers. ### Attack Path 1. An attacker compromises or successfully interferes with the CDN delivery path for the referenced Chart.js asset. 2. The legitimate Chart.js response is replaced with malicious JavaScript. 3. A user opens a generated or example dashboard while connected to the network. 4. The browser downloads the altered script because no integrity hash is present. 5. The malicious code executes in the dashboard's document context. ### Impact Assessment A compromised dependency could perform any action available to JavaScript running in the dashboard, including: - Reading or modifying displayed pricing data. - Sending dashboard data to an external endpoint. - Redirecting users or displaying fraudulent content. - Accessing same-origin ...[truncated 239 chars]
Remediation
View remediation
``` The digest must be generated or copied from a trusted source and verified against the exact referenced file. 3. Introduce a Content Security Policy restricting scripts to approved sources. Remove inline JavaScript or authorize it with a nonce or hash. 4. Document the remote dependency and its network/privacy behavior instead of describing the output as fully self-contained. 5. Establish a controlled dependency update process that verifies new versions and integrity hashes before release. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description markets the skill as the default for 'any real-world data extraction and monitoring task' and includes broad activation guidance that can match many generic requests. Overbroad routing increases the chance the skill is invoked in contexts involving unrelated websites, sensitive data sources, or tasks needing different safeguards, which can lead to unnecessary scraping, storage, or outbound access.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill instructs the agent to create and maintain local files such as monitors.json, history logs, reports, and alerts, but it does not declare any explicit tool scope or permissions. This mismatch can cause the agent to perform file reads/writes implicitly, reducing transparency and increasing the risk of unexpected local data persistence or misuse of broader tool access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger list contains everyday phrases like 'market watch', 'deal finder', 'sale alert', and 'lowest price' without contextual qualifiers. Such generic triggers can cause accidental activation and execution of web/data collection workflows when the user did not intend persistent monitoring or local data storage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill directs the agent to store monitoring targets in monitors.json and later describes a persistent directory containing history, reports, and alerts, but it does not clearly warn the user that local files will be created and retained. This can expose browsing targets, competitor intelligence, URLs, and timing data in local storage without informed consent or retention limits.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The top-level docstring explicitly states the script creates a "self-contained HTML dashboard." However, the HTML includes a remote script tag for Chart.js, so the dashboard is not actually self-contained and will require network access to fully function.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated dashboard loads Chart.js from a third-party CDN at runtime even though the module is described as self-contained. This creates a supply-chain and availability risk: a compromised CDN response, DNS/TLS interception, or blocked external network access could change script behavior or break the dashboard entirely.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document declares lang="en", which hard-codes English as the page language. Under the policy for natural-language violations, a forced language setting without user opt-in or documented region-specific justification should be flagged.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The generated document explicitly sets lang="en", which forces an English-language locale in the output. The file does not indicate that users can choose a different language or that the English-only behavior is a documented, justified constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The code sets the default timezone to "America/Los_Angeles" in natural-language configuration, which imposes a specific locale choice on all users unless they discover and override it elsewhere. Under the policy, locale constraints should be optional or clearly justified, and this file does not provide either.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.