Back to skill

Security audit

Oda Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a Watch.dog monitoring integration, but it handles API credentials and destructive account actions in ways users should review carefully before installing.

Install only if you trust the Watch.dog account integration and are comfortable giving this skill an API key that can manage monitoring resources. Prefer environment-injected secrets over a skill-local .env file, keep WATCHDOG_API_URL pinned to the official Watch.dog endpoint unless you fully trust another endpoint, use a narrowly scoped API key if available, and manually confirm any delete or public status-page change.

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

T09 · Insecure Skill Coding Practices

Error
Location
index.js:34
Finding

Configurable API Endpoint Can Expose Bearer Credentials and Monitoring Data

Content
View full analysis
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 }, }), }); ``` ### Technical Analysis `WATCHDOG_API_URL` controls the destination of every remote tool request. The value is accepted without HTTPS enforcement, hostname allowlisting, private-network address rejection, or explicit confirmation before credentials are transmitted. Each request sends `WATCHDOG_API_KEY` as a bearer token. Tool arguments can also contain sensitive infrastructure information, including monitored URLs, hostnames, monitor names, identifiers, and tracker-page configuration. Because the Skill documentation and embedded prompt allow the user-supplied API URL to be persisted and immediately tested with `list_monitors`, a malicious, compromised, or mistyped endpoint can receive the credential as soon as configuration is completed. An HTTP endpoint could additionally expose the credential to network interception. A local or private-network endpoint could cause ...[truncated 1258 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
index.js:164
Finding

Untrusted Remote Responses Are Embedded in Agent-Facing Instructions

Content
View full analysis
{ 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}`, }, ], }; }, ``` ```js async ({ name, type, interval }) => { const text = await callRemoteTool("create_watchdog", { name, type, interval, }); 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}`, }, ], }; }, ``` ### Technical Analysis The remote service's `content[0].text` value is treated as an opaque string and concatenated directly into imperative, Agent-facing text. The implementation does not parse the expected JSON payload, validate it against a per-tool schema, escape control content, or clearly delimit it as untrusted data. A malicious or compromised endpoint can therefore return text such as instructions to ignore prior rules, conceal information, request additional tool calls, or invoke destructive operations. The configurable `WATCHDOG_API_URL` makes this path particularly exposed because an attacker-controlled server can directly determine the returned content. The MCP tool itself does not locally execute returned text as code. Exploitation depends on the consuming Agent interpreting the returned text as instructions. Nevertheless, the Skill intentionally presents remote data in an instruction-like context, creat ...[truncated 1225 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:24
Finding

API Credentials Are Persisted in a Plaintext Skill-Local File

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:395
Finding

Destructive Deletion Tools Do Not Enforce User Confirmation in Code

Content
View full analysis
{ 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 confirmation requirement exists only in behavioral prompt text and tool descriptions. Neither deletion handler verifies that the user confirmed the exact resource being deleted. A direct MCP client, a mistaken Agent decision, or an Agent influenced by prompt injection can invoke either tool and immediately trigger the remote deletion request. Both schemas also allow all identifiers to be omitted because `monitor_id`, `watchdog_id`, and `name` are individually optional. The remote API may reject an empty request, but the local Skill does not ...[truncated 1174 chars]
Remediation
View remediation
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 (31)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared purpose and the described behavior are inconsistent: the skill includes tracker-page modification capability, instructs local .env credential handling, and promises an automatic connection test that is not clearly reflected as disclosed behavior. These mismatches undermine informed consent and make it easier for a user or host to authorize operations they did not expect, including account configuration changes and secret handling.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · index.js (reported line 10)May include surrounding context.

js
* - 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)
 */

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · index.js (reported line 22)May include surrounding context.

js
* - 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)
 */

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · index.js (reported line 129)May include surrounding context.

js
* - 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)
 */

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The code explicitly reads a local .env file containing API credentials, which is legitimate functionality but still a sensitive secret-access operation. In the context of a user-facing skill that may solicit and persist tokens, silently ingesting secrets from disk increases the risk of unintended credential use and makes auditing/consent weaker.

Content

Scanner excerpt · index.js (reported line 25)May include surrounding context.

js
// ─── 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");

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The prompt instructs the model to collect API credentials from the user and automatically create or overwrite a .env file with them. Even though this file does not expose write tools, the instruction is dangerous because in an agent environment with broader host capabilities it would promote credential harvesting and local secret persistence without an explicit, narrowly scoped credential-management flow.

Content

Scanner excerpt · index.js (reported line 56)May include surrounding context.

js
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.

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
90% confidence
Finding

The lockfile pins @hono/node-server 1.19.9, and the reported advisories are relevant because this package is an HTTP server adapter that may expose static content or routing behavior if used by the skill or its SDK. Even though the vulnerable code may be transitive via @modelcontextprotocol/sdk, server-side path traversal or auth-bypass issues can become exploitable if any static-serving or protected path handling is enabled.

Content

No source excerpt is available for this finding.

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
88% confidence
Finding

express-rate-limit 8.2.1 is reported vulnerable to bypass via IPv4-mapped IPv6 handling, which can let clients evade per-client throttling. In a monitoring skill that may expose MCP/HTTP endpoints, weakened rate limiting can materially increase brute-force, scraping, or resource exhaustion risk.

Content

No source excerpt is available for this finding.

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
80% confidence
Finding

fast-uri 3.1.0 has multiple URI parsing and canonicalization advisories including host confusion and possible SSRF-relevant parsing discrepancies. Because this skill works with website/API monitor targets and user-supplied URLs are central to its purpose, unsafe URI handling is more dangerous in this context than in a package that never processes external URLs.

Content

No source excerpt is available for this finding.

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
89% confidence
Finding

hono 4.12.3 is associated with numerous advisories affecting cookies, routing, and path handling, which are core HTTP framework functions. Since the package under analysis includes the MCP SDK that depends on Hono, these issues represent a genuine framework-level exposure if the skill is run as a networked service.

Content

No source excerpt is available for this finding.

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 is flagged for address parsing inconsistencies and an HTML-emitting XSS issue. The rate-limiting dependency chain suggests IP parsing may influence client identification, so parsing mismatches could contribute to security-control bypasses, though the XSS aspect is less likely unless IP-derived HTML is rendered.

Content

No source excerpt is available for this finding.

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
83% confidence
Finding

path-to-regexp 8.3.0 is reported vulnerable to ReDoS patterns, which can let crafted paths consume excessive CPU during route matching. Because this dependency sits in the routing stack, an exposed HTTP service could be made unavailable by maliciously structured requests.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares network and environment-variable capabilities but does not define an explicit tool scope such as permissions or allowed-tools. This weakens least-privilege boundaries and makes it harder for a host to constrain what the skill may access, especially since it can use user-supplied API credentials and reach an external service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs an automatic credential-verification API call immediately after credentials are provided or changed, without an explicit warning that the supplied secrets will be used to contact a third-party service. That creates a consent and privacy problem because users may think they are only storing configuration, while the skill silently transmits data and authenticates externally.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

A silent test triggered by credential entry causes the agent to process and use user-provided secrets automatically, outside the user's explicit operational request. Even if the intent is benign, this increases the risk of accidental secret exposure, unintended external actions, and poor auditability of when credentials were used.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
90% confidence
Finding

The instruction to automatically execute list_monitors on credential changes grants the skill autonomous authority to perform an external authenticated action without a direct user request at that moment. In a credential-handling context, this is more dangerous because it couples secret submission with immediate network use and reduces meaningful user control.

Content

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

md
"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.0"
author: Oda Monitor Team

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

md
*
 * 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";

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

md
*
 * 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";

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 · index.js (reported line 12)May include surrounding context.

js
*
 * 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";

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 · index.js (reported line 39)May include surrounding context.

js
*
 * 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";

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill loads credentials from a local .env file or environment variables and then uses them operationally, but the executable code path provides no built-in disclosure, consent flow, or visibility to the user about how those secrets are handled. In this skill context, that matters because the prompt also encourages collecting and persisting API credentials, increasing the chance users provide sensitive tokens without clear runtime notice.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The embedded behavioral instructions explicitly tell the assistant to use native file writing tools to create or overwrite a .env file and then run list_monitors. However, this skill file only registers Watch.dog proxy tools and contains no file-writing tool or implementation that can perform that action. This is an active contradiction between the documented behavior and the actual code capabilities.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
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.

Content

Scanner excerpt · index.js (reported line 59)May include surrounding context.

js
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.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The system prompt states it is forbidden to show raw JSON and requires friendly presentation. But tool wrappers later tell the model to 'Transmit this JSON result' or summarize 'using this JSON', creating contradictory instructions about whether raw JSON output is acceptable. This mismatch can lead to behavior that violates the skill's stated interaction contract.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This function transmits the user's API bearer token and monitoring-related arguments to a remote HTTP endpoint, but the code itself does not provide runtime disclosure or confirmation to the user when this happens. In a monitoring skill, external transmission is expected, but silent credentialed transmission to a third-party service still creates privacy and trust risk if users are not clearly informed.

Content

No source excerpt is available for this finding.