Back to skill

Security audit

Nex Pricewatch

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent price-monitoring tool, but it needs Review because it can fetch unrestricted URLs, including local or internal resources, and then store or export the results.

Install only if you are comfortable with a local CLI that stores pricing data and fetched HTML snapshots on disk. Do not add untrusted URLs, localhost/private-network URLs, cloud metadata URLs, or file-like URLs as targets. Enable Telegram only if alert content may be sent to Telegram, and review ~/.local/bin/nex-pricewatch and ~/.nex-pricewatch after setup.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
lib/scraper.py:99
Finding

Unrestricted URL Fetching Enables SSRF and Local Resource Access

Content
View full analysis
Optional[str]: """HTTP GET with urllib, proper headers, timeout, retry.""" for attempt in range(MAX_RETRIES): try: req = Request(url, headers={'User-Agent': USER_AGENT}) with urlopen(req, timeout=REQUEST_TIMEOUT) as response: html = response.read().decode('utf-8', errors='ignore') return html except (URLError, HTTPError, TimeoutError) as e: if attempt < MAX_RETRIES - 1: time.sleep(2 ** attempt) # Exponential backoff else: return None ``` ### Technical Analysis The CLI accepts an arbitrary URL and stores it as a monitoring target. The stored value is subsequently passed directly to `urllib.request.Request` and `urlopen` without validating: - The URL scheme - The destination hostname or resolved IP address - Whether the destination is loopback, link-local, private, multicast, or reserved - Redirect destinations - Whether the URL contains embedded credentials - Whether the selected URL handler accesses a local resource, such as through a `file://` URL Although `_fetch_page` is described as performing an HTTP GET, `urlopen` supports URL schemes beyond HTTP and HTTPS. Consequently, an attacker who can influence commands supplied to the Agent may cause the process to read local files or connect to services that are reachable from the host but not from the attacker. The fetched response is then processed as webpage content. Extracted content can be written to the SQLite database through `save_price`. The related `t ...[truncated 1706 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
lib/scraper.py:148
Finding

Arbitrary Regular Expression Evaluation Enables Denial of Service

Content
View full analysis
str: """Custom regex extraction.""" try: matches = re.findall(pattern, html, re.IGNORECASE | re.DOTALL) if matches: if isinstance(matches[0], tuple): # Multiple groups - return first non-empty for group in matches[0]: if group: return group else: return matches[0] except re.error: pass return '' ``` ### Technical Analysis The application permits arbitrary user-controlled regular expressions as selectors and evaluates them against complete remote webpage responses using Python's standard backtracking regular-expression engine. No safeguards restrict: - Pattern length or complexity - Nested or ambiguous repetition - Backreferences and other expensive constructs - Webpage response size - Regex execution time - CPU or memory consumption A pattern containing catastrophic backtracking can require exponential processing time for a carefully selected input. The `REQUEST_TIMEOUT` setting only applies to network retrieval and does not limit `re.findall` execution. Catching `re.error` handles invalid syntax but does not mitigate valid, computationally expensive patterns. ### Attack Path 1. An attacker induces an Agent or operator to create a target with `--selector-type regex`. 2. The attacker supplies a catastrophically backtracking selector, s ...[truncated 1203 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (18)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · README.md (reported line 327)May include surrounding context.

BotFather:

  • Message: /newbot
  • Follow prompts to get bot token
  1. Get your chat ID:

  2. Set environment variables:

bash
export NEX_PRICEWATCH_TELEGRAM_BOT_TOKEN="your_bot_token"
export NEX_PRICEWATCH_TELEGRAM_CHAT_ID="your_chat_id"
  1. Add to shell profile (~/.bashrc or ~/.zshrc):
bash
echo 'export NEX_PRICEWATCH_TELEGRAM_BOT_TOKEN="token"' >> ~/.bashrc
echo 'export NEX_PRICEWATCH_TELEGRAM_CHAT_ID="id"' >> ~/.bashrc
  1. Enable in config (lib/config.py):
python
TELEGRAM_ENABLED = True
  1. Use in commands:
bash
nex-pricewatch check --alerts --telegram

Data Storage

All data stored locally in ~/.nex-pricewatch/:

text
~/.nex-pricewatch/
├── pricewatch.db          # SQLite database
├── snapshots/             # HTML snapshots for comparison
│   └── target_1_abc123.html
│   └── target_2_def456.html
└── ...

**Databas

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · README.md (reported line 417)May include surrounding context.

bash
# Remove database and reinitialize
rm ~/.nex-pricewatch/pricewatch.db
python3 -c "from lib.storage import init_db; init_db()"

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · nex-pricewatch.py (reported line 432)May include surrounding context.

python
int("=" * 70)
    print(f"Data directory: {DATA_DIR}")
    print(f"Check interval: {CHECK_INTERVAL_HOURS} hours")
    print(f"Price increase alert threshold: {5}%")
    print(f"Price decrease alert threshold: {10}%")
    print("=" * 70)
    print(FOOTER)
    return True


def main():
    """Main entry point."""
    # Initialize database
    init_db()

    parser = argparse.ArgumentParser(
        description="Nex PriceWatch - Competitive Price Monitor",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=FOOTER
    )

    subparsers = parser.add_subparsers(dest='command', help='Commands')

    # add command
    add_parser = subparsers.add_parser('add', help='Add price target')
    add_parser.add_argument('--name', required=True, help='Target name')
    add_parser.add_argument('--url', required=True, help='URL to monitor')
    add_parser.add_argument('--competitor', help='Competitor name')
    add_parser.add_argument('--type', default='competitor', choices=['com

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 35)May include surrounding context.

md
This will:
1. Check Python 3 installation
2. Create data directory (~/.nex-pricewatch/)
3. Initialize SQLite database
4. Make `nex-pricewatch` command available

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README encourages Telegram alerts but does not clearly warn that monitored pricing data and alert contents are sent to Telegram, a third-party service. Users may assume all data remains local based on earlier claims, causing unintended external disclosure of business-sensitive monitoring information.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger phrases are very broad, including common words like 'price', 'monitor', and 'competitor', which can cause the skill to activate in ordinary conversations unrelated to this tool. In an agent environment, over-broad activation increases the chance the skill is invoked unexpectedly and may steer user workflows, collect URLs, or prompt setup steps when not intended.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

To enable Telegram alerts:

  1. Create a Telegram bot via @BotFather
  2. Set environment variables:
    bash
    export NEX_PRICEWATCH_TELEGRAM_BOT_TOKEN="your_bot_token"
    

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code transmits alert messages to Telegram via an HTTP POST request, which sends potentially sensitive business or pricing data to a third-party service. Although the function name and docstring indicate Telegram usage, there is no confirmation prompt or explicit user-facing disclosure about external data transmission.

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 · README.md (reported line 315)May include surrounding context.

md
return False

    try:
        url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
        payload = {
            'chat_id': TELEGRAM_CHAT_ID,
            'text': message,

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 · lib/alerter.py (reported line 203)May include surrounding context.

python
return False

    try:
        url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
        payload = {
            'chat_id': TELEGRAM_CHAT_ID,
            'text': message,

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · lib/alerter.py (reported line 209)May include surrounding context.

python
'text': message,
            'parse_mode': 'HTML'
        }
        response = requests.post(url, json=payload, timeout=10)
        return response.status_code == 200
    except Exception as e:
        print(f"Telegram send failed: {e}")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The function fetches full page HTML and writes it to a snapshot file, which can store remote page content on disk and affect user data/storage. While there is an internal docstring, there is no confirmation prompt, logging, or other visible user disclosure in the code about this persistent write behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

This routine iterates through targets, fetches remote webpages, saves snapshots, and persists price data, but provides no confirmation or user-visible notice while doing so. These operations affect privacy, network usage, and local stored data, and the file itself does not disclose them beyond internal comments/docstrings.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code writes exported price history to a user-specified filesystem path, which is a safety-relevant file write operation. While the CLI later prints the destination after writing, there is no prior warning in this file's help text, docstrings, or comments that the export command will create or overwrite a local file when --output is used.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · nex-pricewatch.py (reported line 492)May include surrounding context.

python
# remove command
    remove_parser = subparsers.add_parser('remove', help='Remove target')
    remove_parser.add_argument('name', help='Target name')
    remove_parser.add_argument('--force', action='store_true', help='Skip confirmation')
    remove_parser.set_defaults(func=cmd_remove)

    # export command

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · LICENSE.txt (reported line 12)May include surrounding context.

text
permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The README states the skill uses 'Python stdlib only' with 'No External Dependencies', but later troubleshooting guidance instructs users to install Playwright to handle JavaScript-heavy sites. That is an active contradiction in the documentation about what dependencies the skill may require for advertised use cases.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This shell script creates a new executable file at $HOME/.local/bin/nex-pricewatch and changes its permissions, which modifies the user's environment. Although the script prints progress messages, it does not clearly disclose ahead of time in usage text or comments that installation will place a command in the user's PATH-like bin directory.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.