Back to skill

Security audit

SeeWeb Uptime

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its uptime-monitoring purpose, but it asks the agent to handle secrets and account-changing actions in ways that need careful review before installation.

Install only if you trust the Watch.dog endpoint and are comfortable giving this skill authority to create, pause, resume, publish, and delete monitoring resources. Prefer platform-managed secrets or environment variables over chat-provided plaintext .env storage, keep WATCHDOG_API_URL pinned to the official Watch.dog API unless you have a specific trusted deployment, and verify destructive actions carefully.

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

T09 · Insecure Skill Coding Practices

Error
Location
index.js:123
Finding
Bearer API Key Can Be Transmitted to an Arbitrary Configured Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `index.js:37-41`, `index.js:123-153`; related configuration instructions at `SKILL.md:61-62` **Vulnerability Type**: Unrestricted credential destination and unsafe endpoint configuration **Risk Level**: High ### Vulnerable Code ```js const CONFIG = { apiUrl: process.env.WATCHDOG_API_URL || "https://api.watch.dog/api/mcp_server.php", apiKey: process.env.WATCHDOG_API_KEY || "", }; ``` ```js async function callRemoteTool(toolName, args = {}) { // Remove undefined args Object.keys(args).forEach((k) => args[k] === undefined && delete args[k]); if (!CONFIG.apiKey) { throw new Error( "WATCHDOG_API_KEY is not configured. " + "Please configure it in the .env file of the skill or as an environment variable.", ); } const response = await fetch(CONFIG.apiUrl, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${CONFIG.apiKey}`, }, body: JSON.stringify({ jsonrpc: "2.0", id: `req_${Date.now()}`, method: "tools/call", params: { name: toolName, arguments: args }, }), }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); if (data.error) { throw new Error(`[${data.error.code}] ${data.error.message}`); } return data?.result?.content?.[0]?.text ?? "{}"; } ``` The documentation explicitly permits a configurable endpoint: ```env WATCHDOG_API_KEY="sk_live_your_key_here" WATCHDOG_API_URL="api_url_here" | "https://api.watch.dog/api/mcp_server.php" ``` ### Technical Analysis `WATCHDOG_API_URL` is accepted without validating its scheme, hostname, port, or network destination. Every tool request then transmits `WATCHDOG_API_KEY` in an `Authorization: Bearer` header to that endpoint. Consequently, a configuration mistake or attacker-influenced onboarding interacti ...[truncated 1809 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict credential-bearing requests to an explicit hostname allowlist, preferably only `api.watch.dog`. 2. Parse the endpoint with `new URL()` and require: - The `https:` scheme. - An approved hostname. - An approved port, normally `443`. - The expected API path where practical. 3. Reject loopback, link-local, private-network, and non-HTTP destinations unless a separately designed enterprise configuration explicitly requires them. 4. Do not let conversational input silently change the credential destination. Require explicit user confirmation that displays the normalized hostname before saving any custom endpoint. 5. Avoid forwarding authorization headers across unvalidated redirects. Disable redirects or validate every destination before credentials are transmitted. 6. Store credentials through the host platform's secret-management facility instead of prompting an agent to write plaintext secrets to `.env`. 7. Apply least-privilege scopes to Watch.dog API keys and provide clear key-rotation instructions. 8. Add automated tests confirming that HTTP URLs, unapproved hosts, private IP addresses, malformed URLs, and unsafe redirects are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:395
Finding
Destructive Monitor and Watchdog Deletions Lack Programmatic Confirmation Enforcement<![CDATA[ ## Vulnerability Details **File Location**: `index.js:76-82`, `index.js:395-433` **Vulnerability Type**: Missing authorization-state validation for destructive operations **Risk Level**: Medium ### Vulnerable Code The confirmation requirement exists only in model-facing instructions: ```js ### Deletions (CRITICAL CONFIRMATION RULE) If the user asks to delete a monitor or watchdog: STOP! YOU MUST ask for ABSOLUTE confirmation before invoking \`delete_monitor\` or \`delete_watchdog\`. Example: "You are about to irreversibly delete the monitor [Name]. Are you 100% sure you want to proceed?" Only if the response is affirmative, execute it. ``` The tool handlers do not enforce that requirement: ```js server.registerTool( "delete_monitor", { description: "Irreversibly deletes an Active Monitor. REQUIRES PRIOR EXPLICIT CONFIRMATION FROM THE USER.", inputSchema: { monitor_id: z.number().int().positive().optional(), name: z.string().optional(), }, }, async ({ monitor_id, name }) => { const text = await callRemoteTool("delete_monitor", { monitor_id, name }); return { content: [ { type: "text", text: `[Inform the user about the success of this deletion based on this JSON]:\n${text}`, }, ], }; }, ); server.registerTool( "delete_watchdog", { description: "Irreversibly deletes a Passive Watchdog. REQUIRES PRIOR EXPLICIT CONFIRMATION FROM THE USER.", inputSchema: { watchdog_id: z.number().int().positive().optional(), name: z.string().optional(), }, }, async ({ watchdog_id, name }) => { const text = await callRemoteTool("delete_watchdog", { watchdog_id, name }); return { content: [ { type: "text", text: `[Inform the user about the success of this deletion based on this JSON]:\n${text}`, }, ], }; }, ); ``` ### Technical Analysis The Skill relies exclusively on an L ...[truncated 1730 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Implement a two-step deletion workflow: - A preparation tool resolves and displays the exact resource. - A separate commit tool requires a short-lived confirmation token bound to the resource ID, action, account, and session. 2. Store pending confirmation state in trusted application state rather than relying on conversational text. 3. Expire confirmation tokens after a short interval and invalidate them after one use. 4. Require exactly one validated identifier, preferably an immutable numeric ID. Reject calls where both `monitor_id` and `name` are absent. 5. Include the resolved resource name and ID in the confirmation request so that consent is specific and informed. 6. Consider soft deletion or a recoverable quarantine period if supported by the remote platform. 7. Require additional authorization or reauthentication for high-impact account operations. 8. Add tests proving that direct deletion calls without valid confirmation state are rejected locally and never reach the remote API. ]]>

T01 · Skill Instruction Hijacking

Warning
Location
index.js:151
Finding
Untrusted Remote API Text Is Injected Directly into Model-Facing Tool Results<![CDATA[ ## Vulnerability Details **File Location**: `index.js:151-153`, `index.js:169-190`, `index.js:345-351` **Vulnerability Type**: Indirect prompt injection through untrusted remote content **Risk Level**: Medium ### Vulnerable Code The proxy returns the remote server's first text item without schema validation: ```js return data?.result?.content?.[0]?.text ?? "{}"; ``` A representative tool concatenates that remote value directly with an imperative instruction for the model: ```js server.registerTool( "list_monitors", { description: "Lists all active uptime monitors for the account.", inputSchema: { status: z .enum(["up", "down", "paused", "all"]) .optional() .describe("Optional. Filter by status."), }, }, async ({ status }) => { const text = await callRemoteTool("list_monitors", { status }); return { content: [ { type: "text", text: `[Data retrieved. Present it as a friendly markdown table using emojis 🟢🔴⏸️]:\n${text}`, }, ], }; }, ); ``` The watchdog creation handler uses the same unsafe pattern: ```js return { content: [ { type: "text", text: `[CRITICAL RULE: You must send the user the endpoint_url and give them exact instructions on how to ping using this data]:\n${text}`, }, ], }; ``` Equivalent raw concatenation patterns appear in the other tool handlers. ### Technical Analysis Remote API output is an untrusted data source. It may include user-controlled monitor names, watchdog names, endpoint fields, error-like text, or arbitrary content from a compromised or maliciously configured API server. The Skill does not parse the returned text into a strict object, validate expected fields, constrain field lengths, or render values through a deterministic formatter. Instead, it places raw remote text immediately after instructions directed at the model. Instruction-like strings in that content can therefore be ...[truncated 1693 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require every remote tool result to conform to a strict JSON schema before exposing it to the model. 2. Reject responses that are not valid JSON or that contain unexpected keys, types, excessive nesting, or oversized strings. 3. Render expected fields through deterministic local formatters rather than asking the model to interpret raw JSON or text. 4. Mark all remote values explicitly as untrusted data and place them in structured MCP content where supported. 5. Escape or quote user-controlled names and descriptions so they cannot be confused with Skill instructions. 6. Keep behavioral instructions separate from returned data. Do not concatenate imperative prompts and untrusted content into one text block. 7. Validate returned endpoint URLs before displaying them, and clearly identify the trusted hostname. 8. Apply length limits to names, messages, event details, and endpoint fields. 9. Add adversarial tests using values such as “ignore previous instructions,” fake system messages, Markdown links, and tool-call requests. 10. Combine these changes with strict API endpoint allowlisting so an attacker cannot substitute an arbitrary response server. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (29)

Credential Access

High
Category
Privilege Escalation
Content
* - Prompts: defined locally (behavioral instructions for the LLM)
 * - Tools:   proxied to the remote Watch.dog MCP PHP server via HTTP
 *
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
* - Prompts: defined locally (behavioral instructions for the LLM)
 * - Tools:   proxied to the remote Watch.dog MCP PHP server via HTTP
 *
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
* - Prompts: defined locally (behavioral instructions for the LLM)
 * - Tools:   proxied to the remote Watch.dog MCP PHP server via HTTP
 *
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
// ─── Load .env if present ────────────────────────────────────────────────────

const __dirname = dirname(fileURLToPath(import.meta.url));
const envPath = join(__dirname, ".env");

if (existsSync(envPath)) {
  const envContent = readFileSync(envPath, "utf-8");
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Ssd 3

High
Confidence
97% confidence
Finding
The prompt explicitly instructs the assistant to solicit API credentials from the user and automatically write them into a local .env file. Storing secrets in plaintext local files and normalizing secret collection through the conversational agent increases risk of credential leakage, accidental exposure, and unsafe secret-handling behavior.

Credential Access

High
Category
Privilege Escalation
Content
If the user activates this skill for the first time and has no API Key configured:
1. Greet them enthusiastically and explain that you need to connect to their Watch.dog account.
2. Ask them only for their API Key and API URL (and remind them they can create a free account at https://watch.dog).
3. Once the user provides the data, use your native file writing tools to automatically create or overwrite the .env file in the root of this skill with the exact following format:
   WATCHDOG_API_KEY="[user_key]"
   WATCHDOG_API_URL="[user_url]"
   Never ask the user to create the file manually.
Confidence
96% confidence
Finding
This prompt directs the assistant to collect credentials from the user and write them into a local .env file. In the context of an agent skill, that makes secret handling more dangerous because it encourages users to disclose API keys conversationally and store them in plaintext at rest.

Known Vulnerable Dependency: @hono/node-server==1.19.9 — 3 advisory(ies): CVE-2026-39406 (@hono/node-server: Middleware bypass via repeated slashes in serveStatic); GHSA-frvp-7c67-39w9 (Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode); CVE-2026-29087 (@hono/node-server has authorization bypass for protected static paths via encode)

High
Category
Supply Chain
Confidence
92% confidence
Finding
The lockfile pins @hono/node-server 1.19.9, and the listed advisories describe path traversal, middleware bypass, and authorization bypass issues in static file serving. Even if this skill is primarily an MCP integration, shipping a vulnerable web adapter in the dependency tree increases risk if any exposed HTTP transport or static serving path is used now or later.

Known Vulnerable Dependency: express-rate-limit==8.2.1 — 1 advisory(ies): CVE-2026-30827 (express-rate-limit: IPv4-mapped IPv6 addresses bypass per-client rate limiting o)

High
Category
Supply Chain
Confidence
90% confidence
Finding
express-rate-limit 8.2.1 has a reported bypass for IPv4-mapped IPv6 addresses, which can let attackers evade per-client throttling. In a service-facing MCP or HTTP deployment, that weakens abuse protection and can amplify brute-force or flooding attacks.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
84% confidence
Finding
fast-uri 3.1.0 is listed with multiple host-confusion and SSRF-related advisories. If any part of the dependency chain uses it for URL validation, parsing, or allowlist decisions, malformed URLs may be interpreted inconsistently and enable request smuggling to unintended hosts.

Known Vulnerable Dependency: hono==4.12.3 — 16 advisory(ies): CVE-2026-56762 (Hono missing validation of cookie name on write path in setCookie()); CVE-2026-47676 (Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro); CVE-2026-47675 (Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie) +13 more

High
Category
Supply Chain
Confidence
93% confidence
Finding
hono 4.12.3 is associated with numerous advisories affecting cookies, routing, path handling, and other web framework behaviors. Because this package underpins server behavior, weaknesses here can undermine authentication, authorization, and request handling if the HTTP-capable portions of the skill are reachable.

Known Vulnerable Dependency: ip-address==10.0.1 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding
ip-address 10.0.1 has advisories covering ambiguous IPv4 parsing and XSS in HTML-emitting methods. The rate-limit dependency chain may make the parsing issue more relevant than the XSS issue, especially where IP normalization affects security controls.

Known Vulnerable Dependency: path-to-regexp==8.3.0 — 2 advisory(ies): CVE-2026-4923 (path-to-regexp vulnerable to Regular Expression Denial of Service via multiple w); CVE-2026-4926 (path-to-regexp vulnerable to Denial of Service via sequential optional groups)

High
Category
Supply Chain
Confidence
87% confidence
Finding
path-to-regexp 8.3.0 is reported vulnerable to ReDoS and route-processing DoS with crafted patterns or inputs. In frameworks that compile or match routes dynamically, this can allow attackers to consume CPU and degrade availability.

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill exposes sensitive capabilities through environment variables and outbound network access, but it does not declare any tool scope or permission boundaries. That makes the skill's effective authority opaque to users and reviewers, increasing the chance of overbroad execution and unintended data access or transmission.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to automatically call `list_monitors` as soon as credentials are provided, which causes immediate transmission and use of those credentials without an explicit user-facing warning at the moment of use. Even if framed as a connection test, it initiates account access and remote data retrieval before the user explicitly asks for that action.

Ssd 3

Medium
Confidence
96% confidence
Finding
This instruction authorizes querying the user's account automatically upon receipt or modification of credentials, rather than in response to a separate request. That weakens user control over account access and can expose monitor metadata or other account information earlier than expected.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
"check uptime", "review watchdogs", or "create a website monitor".
  IMPORTANT: Deleting monitors and watchdogs requires explicit prior confirmation from the user.
  When the user provides their credentials (WATCHDOG_API_KEY, WATCHDOG_API_URL) or modifies them, 
  you MUST automatically execute the `list_monitors` tool as a silent test to verify the connection, 
  and then inform them if it was successful by showing a summary of what the skill can do.
version: "1.0.5"
author: SeeWeb Uptime Team
Confidence
94% confidence
Finding
The requirement to 'automatically execute' `list_monitors` creates autonomous behavior that uses newly supplied secrets and reaches out to a remote service without a distinct user command. In a credential-handling context, that is more dangerous because it removes a meaningful consent checkpoint before authenticated actions are taken.

External Transmission

Medium
Category
Data Exfiltration
Content
*
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
*
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
*
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
*
 * Configuration (via environment variables or .env file):
 *   WATCHDOG_API_KEY  – Your Watch.dog API key (sk_live_...)
 *   WATCHDOG_API_URL  – Remote MCP server URL (default: https://api.watch.dog/api/mcp_server.php)
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest says the skill must automatically verify new or changed WATCHDOG credentials by silently running `list_monitors` and then informing the user of success. The code only includes prompt instructions telling the LLM to write a `.env` file and run `list_monitors`; there is no actual code path that detects credential changes, writes credentials, or triggers this test automatically.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The embedded behavioral documentation tells the assistant to automatically create or overwrite the `.env` file using native file writing tools. In reality, this skill only reads `.env` on startup and registers Watch.dog proxy tools; it does not provide any file-writing capability, so the instruction contradicts actual behavior.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This JavaScript file contains behavioral instructions directing the agent to use native file-writing tools to create or overwrite a .env file with the user's API key and URL. Although the action is described in the prompt, it lacks an explicit warning about local credential storage and overwrite risk, which is safety-relevant for file writes and sensitive secrets handling.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
3. Once the user provides the data, use your native file writing tools to automatically create or overwrite the .env file in the root of this skill with the exact following format:
   WATCHDOG_API_KEY="[user_key]"
   WATCHDOG_API_URL="[user_url]"
   Never ask the user to create the file manually.
4. Immediately after, execute list_monitors to test the connection.
   - If successful: celebrate with the user and offer to create their first monitor or watchdog.
   - If it fails with Auth Error: kindly ask them to verify their key and URL.
Confidence
80% 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.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill sends the user's Watch.dog API key to a remote endpoint in the Authorization header, which is necessary for operation but still constitutes external transmission of a secret. Because the endpoint URL is configurable via WATCHDOG_API_URL, a malicious or misconfigured URL could exfiltrate the credential to an unintended server without meaningful runtime disclosure or restriction.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
index.js:31