Back to skill

Security audit

Web Monitor

Security checks for vulnerabilities and agentic risk

Overview

This web page monitor mostly matches its stated purpose, but it disables HTTPS verification and can run unrestricted local shell commands when a page changes.

Install only if you are comfortable reviewing and controlling every URL and notification command. Avoid --notify with untrusted or generated input, do not run watch mode with privileged accounts, and treat HTTPS results as unauthenticated unless the TLS verification issue is fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/monitor.py:29
Finding
HTTPS Certificate Validation Is Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monitor.py`, lines 29-32 **Vulnerability Type**: Improper certificate validation **Risk Level**: High ### Vulnerable Code ```python # Create SSL context that doesn't verify certificates ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE with urlopen(req, timeout=30, context=ctx) as resp: ``` ### Technical Analysis The monitor explicitly disables both TLS certificate verification and hostname validation. Consequently, HTTPS connections provide encryption without reliable server authentication. The application will accept expired, self-signed, forged, or hostname-mismatched certificates. This behavior contradicts the documented claim that HTTPS fetching is secure. An attacker with a privileged network position—such as control over a proxy, gateway, DNS response, or hostile wireless network—can impersonate the monitored server and return arbitrary content. ### Attack Path 1. A user configures the monitor to retrieve an HTTPS page. 2. An attacker obtains a network position capable of intercepting or redirecting the connection. 3. The attacker presents a forged or self-signed TLS certificate. 4. The monitor accepts the certificate because certificate and hostname checks are disabled. 5. The attacker supplies modified page content. 6. The altered content produces a different hash and can trigger false change notifications or be stored in the configured output file. ### Impact Assessment An attacker can compromise the integrity and authenticity of every HTTPS response processed by the monitor. This can produce false monitoring results, suppress legitimate changes, trigger notification commands, and contaminate persisted snapshots. The issue does not directly grant local privileges, but it allows remote manipulation of security-relevant application behavior. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the assignments to `check_hostname` and `verify_mode`. - Use Python's default verified TLS context: ```python ctx = ssl.create_default_context() with urlopen(req, timeout=30, context=ctx) as resp: ... ``` - Do not offer an insecure mode by default. If a development-only override is necessary, require an explicit option, display a prominent warning, and prevent its use in production automation. - Add tests confirming that self-signed, expired, and hostname-mismatched certificates are rejected. - Update the documentation to describe the actual TLS verification behavior. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/monitor.py:24
Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery and Local Resource Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monitor.py`, lines 24-32 and 137 **Vulnerability Type**: Unrestricted URL and destination handling **Risk Level**: High ### Vulnerable Code ```python def fetch_page(url, selector=None): """Fetch page content, optionally extracting specific element.""" try: req = Request(url, headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }) # Create SSL context that doesn't verify certificates ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE with urlopen(req, timeout=30, context=ctx) as resp: ``` The URL is accepted directly from the command line: ```python parser.add_argument('--url', required=True, help='URL to monitor') ``` ### Technical Analysis The application passes a user-supplied URL directly to `urllib.request.Request` and `urlopen` without validating its scheme, hostname, resolved address, port, or redirect destination. This permits requests to destinations that are not legitimate public web pages, including loopback addresses, private network services, link-local services, and potentially local resources supported by the URL handling library. Redirects can also be used to bypass checks unless each redirect target is independently validated. The risk is particularly significant when command-line arguments are generated by another agent, web service, scheduler, or any workflow that accepts untrusted task content. ### Attack Path 1. An attacker gains influence over the value supplied to `--url`. 2. The attacker supplies a URL targeting an internal service, loopback interface, cloud metadata endpoint, or accessible local resource. 3. The monitor retrieves the destination using the privileges and network access of its host process. 4. The response is hashed and, unless `--hash-only` is enabled, placed in the `content` field. 5. When `--output ...[truncated 729 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse URLs with `urllib.parse.urlsplit` and allow only `http` and `https`. - Reject URLs containing embedded credentials. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses using Python's `ipaddress` module. - Validate every resolved address rather than only the first result. - Disable automatic redirects or validate the complete destination again after every redirect. - Block cloud metadata destinations explicitly, including link-local metadata addresses. - Consider an allowlist of approved domains when the monitor is deployed in an automated or multi-user environment. - Apply outbound firewall or proxy restrictions as defense in depth. - Restrict output paths and file permissions so fetched content cannot be exposed unintentionally. - Add tests for loopback, private-address, link-local, alternate-IP-notation, DNS-rebinding, redirect, and unsupported-scheme cases. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/monitor.py:101
Finding
Notification Hooks Execute Arbitrary Commands Through the System Shell<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monitor.py`, lines 101-102, 120-121, and 142 **Vulnerability Type**: OS command injection and unsafe shell execution **Risk Level**: High ### Vulnerable Code The comparison path invokes the notification string through a shell: ```python if args.notify: os.system(args.notify) ``` The watch-mode path performs the same operation: ```python if args.notify: os.system(args.notify) ``` The value is accepted as unrestricted command-line input: ```python parser.add_argument('--notify', help='Command to run on change') ``` ### Technical Analysis `os.system()` passes its argument to the operating-system command shell. Shell metacharacters, command substitutions, redirections, pipelines, and chained commands are interpreted rather than treated as literal executable arguments. The command hook is an advertised feature, so a trusted operator can intentionally execute commands. However, the implementation creates command-injection exposure whenever an untrusted user, task description, configuration generator, or upstream automation can influence `--notify`. Execution occurs when a change is detected, potentially delaying the malicious behavior until after configuration review. ### Attack Path 1. An attacker influences the command-line arguments used to start the monitor. 2. The attacker supplies shell syntax in `--notify`, such as a chained or substituted command. 3. The attacker changes the monitored page, waits for a legitimate page change, or selects content likely to change. 4. The monitor detects a hash difference. 5. `os.system()` passes the complete attacker-controlled string to the system shell. 6. The injected command executes with the operating-system identity, environment, filesystem access, and network permissions of the monitor process. ### Impact Assessment Successful exploitation provides arbitrary command execution with the privileges of the account running the monitor. An att ...[truncated 315 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove unrestricted shell-command notification hooks. - Prefer built-in, structured notifier implementations with explicit fields, such as a webhook URL and a fixed JSON message body. - If external programs must be supported, accept an executable and arguments as separate structured values. - Invoke them with `subprocess.run(argument_list, shell=False, check=True, timeout=...)`. - Enforce an allowlist of approved notification executables and reject shell metacharacters or ambiguous configurations. - Run notifier processes under a dedicated, least-privileged account with a minimal environment and restricted filesystem/network access. - Do not pass fetched page content into command arguments or environment variables without strict encoding and validation. - Add tests confirming that shell syntax is treated as literal input and cannot create files or launch secondary commands. ]]>

T08 · Insecure Dependencies

Warning
Location
references/examples.md:51
Finding
Documentation Recommends Installing an Unpinned Third-Party Package<![CDATA[ ## Vulnerability Details **File Location**: `references/examples.md`, lines 51-55 **Vulnerability Type**: Unpinned dependency and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```bash ### Telegram (using telegram-send) ```bash pip install telegram-send telegram-send "Page changed!" ``` ``` ### Technical Analysis The documentation instructs users to install `telegram-send` from the active Python package index without specifying a reviewed version, integrity hash, trusted index, or reproducible lock file. Package installation can execute package-controlled build logic, and later releases can differ from the version originally reviewed. A compromised maintainer account, malicious package release, index substitution, or dependency compromise could therefore introduce arbitrary code into the user's environment. The core monitor itself uses the Python standard library; this finding concerns the optional installation guidance rather than a mandatory runtime dependency. ### Attack Path 1. A user follows the notification setup instructions. 2. `pip` resolves the latest available release and its transitive dependencies from the configured package index. 3. A package or dependency has been compromised, maliciously replaced, or altered after the documentation was reviewed. 4. Package-controlled code executes during installation, build, or later invocation. 5. The malicious package obtains the permissions available to the user performing the installation or running the notification command. ### Impact Assessment A compromised package can execute arbitrary code with the installing user's privileges. It may access files, environment credentials, Python configuration, and network resources available to that account. The practical likelihood depends on the security of the package index, package maintainer, and transitive dependency chain. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the dependency to a specifically reviewed version. - Provide a requirements or lock file containing cryptographic hashes and install it with hash verification enabled. - Document the expected trusted package index or verified upstream source. - Review and pin transitive dependencies where applicable. - Recommend installation in an isolated virtual environment under a non-privileged account. - Prefer a built-in webhook implementation using the Python standard library if that avoids the optional third-party package entirely. - Establish a dependency update process that includes security review before changing pinned versions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a true vulnerability because the documented purpose omits materially risky behavior: arbitrary shell execution via --notify and disabled SSL certificate verification during page fetches. The mismatch increases the chance that a user will run the skill in a more trusted way than warranted, while SSL bypass enables man-in-the-middle tampering and shell execution can turn a content change into code execution in the operator's environment.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
Allowing arbitrary shell commands as a notification mechanism exceeds the stated capability of simple web-page monitoring and effectively turns the tool into a command runner. This broadens the attack surface significantly, especially in automation contexts where arguments may be templated, copied from examples, or influenced by untrusted sources.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
print(f"Previous: {prev['hash'][:16]}...")
                print(f"Current:  {current_hash[:16]}...")
                if args.notify:
                    os.system(args.notify)
                return 2
        else:
            print(f"No previous data to compare (file: {args.compare})")
Confidence
98% confidence
Finding
The script executes the user-supplied --notify value with os.system(), which invokes a shell and permits arbitrary command execution. In a skill whose purpose is web page monitoring, this creates a dangerous command-execution capability unrelated to the core function and can be abused if untrusted input reaches this argument or if users misunderstand the risk.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
In watch mode, the arbitrary notification command can be triggered repeatedly on each detected change, creating a persistent command-execution path beyond the monitoring purpose. In context, a web-monitor skill polling attacker-controlled content makes this more dangerous because remote content changes can indirectly trigger repeated local actions.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
if new_hash != current_hash:
                        print(f"\n[{datetime.now().isoformat()}] CHANGE DETECTED!")
                        if args.notify:
                            os.system(args.notify)
                        current_hash = new_hash
                        data['hash'] = new_hash
                        data['content'] = new_content if not args.hash_only else None
Confidence
98% confidence
Finding
This watch-mode path repeatedly executes the user-provided notification command whenever content changes, again via os.system() and a shell. That increases exposure because an attacker controlling page content or triggering frequent changes can repeatedly cause command execution once a dangerous notify string is configured.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises behavior that implies network access, file writes, and shell execution, but it does not declare any tool scope or permissions. This is dangerous because users and policy layers cannot accurately assess or restrict the skill's capabilities, especially given the presence of a notification feature that can invoke shell commands.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The documentation explicitly encourages running an arbitrary command when a page changes but provides no warning that this results in shell execution. In the context of a web-monitoring skill, this is more dangerous because remote web content can influence when the command fires, creating a bridge from untrusted network input to local command execution workflows.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The manifest describes monitoring web pages and notifying on changes, but the examples instruct users to pass free-form shell commands via `--notify`, such as `telegram-send ...`. Allowing arbitrary command execution is a substantially broader capability than page monitoring itself and is not justified by the stated purpose alone.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The job posting example shows `--notify "echo 'New jobs posted!'"`, again implying that notification handling executes arbitrary shell commands. While notifications are within scope, exposing them as unrestricted command execution is not an obvious requirement of a web monitoring skill.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The watch-mode example uses `--notify "telegram-send 'Product is now available!'"`, reinforcing that the skill's notification path likely executes external commands. This is a broader operational capability than the manifest's monitoring-and-notification description suggests.

External Transmission

Medium
Category
Data Exfiltration
Content
### Webhook
```bash
curl -X POST "https://hooks.slack.com/services/XXX" -d "{\"text\":\"Change detected\"}"
```

### Email (using msmtp)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The comment understates the insecurity of the TLS configuration: the code disables both certificate validation and hostname verification. This mismatch can mislead maintainers or reviewers into believing the risk is narrower than it is, increasing the likelihood that insecure transport remains unnoticed in production.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
TLS certificate and hostname verification are disabled for all HTTPS fetches, allowing man-in-the-middle attackers to spoof monitored sites and alter the content being hashed or stored. For a web monitoring tool, this directly undermines the integrity of the monitored data and can cause false alerts, missed changes, or trust in attacker-supplied content.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The tool executes a user-provided shell command for notifications without presenting any safety warning, making it easy for users to enable dangerous behavior unintentionally. Because os.system() uses a shell, metacharacters and chained commands are interpreted, which magnifies the risk beyond simply launching a program.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
In watch mode, the absence of a warning is more dangerous because the shell command may run repeatedly over long periods, potentially causing persistent unintended actions or amplification of damage. The skill context increases risk because a monitor is expected to run unattended, so unsafe notification behavior can be overlooked after initial setup.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This markdown file shows repeated examples that fetch remote web pages and send notifications via Telegram, Slack webhooks, and email, but it does not include any warning that these actions transmit data to third-party services or generate external network traffic. Under the markdown-specific warning criterion, skills that may affect privacy or system/network behavior should disclose that behavior.

Static analysis

Detected: suspicious.insecure_tls_verification

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/monitor.py:29