Back to skill

Security audit

Observability

Security checks for vulnerabilities and agentic risk

Overview

The skill matches an observability purpose, but it needs Review because its dashboard and alerting can expose sensitive operational logs and telemetry without adequate access controls or redaction.

Install only if you are comfortable treating its logs and dashboard as sensitive. Run the dashboard on loopback or behind authentication, avoid logging secrets or raw prompts/tool payloads, disable or restrict webhooks to trusted HTTPS destinations, and consider adding redaction before using it with real agent traffic.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/dashboard.js:492
Finding
Unauthenticated Network Exposure of Logs and Operational Data<![CDATA[ ## Vulnerability Details **File Location**: `src/dashboard.js:492-518` **Vulnerability Type**: Unauthenticated monitoring API exposure and unsafe default network binding **Risk Level**: High ### Vulnerable Code ```javascript const server = http.createServer((req, res) => { if (req.url === '/' || req.url === '/dashboard') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(dashboardHTML); } else if (req.url === '/api/status') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.getStatus(), null, 2)); } else if (req.url === '/api/metrics') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.exportMetrics(), null, 2)); } else if (req.url === '/api/logs') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.exportLogs({ limit: 100 }))); } else if (req.url === '/api/prometheus') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(obs.exportMetrics('prometheus')); } else if (req.url === '/api/alerts') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obs.getAlertHistory({ limit: 50 }), null, 2)); } else { res.writeHead(404); res.end('Not Found'); } }); const PORT = process.env.OBSERVABILITY_PORT || 3001; server.listen(PORT, () => { ``` ### Technical Analysis The dashboard exposes system status, metrics, logs, Prometheus data, and alert history without authentication or authorization. The HTTP server also calls `server.listen(PORT)` without specifying a host. In Node.js, omitting the host normally causes the server to listen on an unspecified address, potentially accepting connections through non-loopback interfaces. This conflicts with the console output and documentation suggesting that the service is available only through `localhost`. The network exposure is broader than the minimum privileges required for a lo ...[truncated 1984 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind the dashboard to loopback by default: ```javascript const HOST = process.env.OBSERVABILITY_HOST || '127.0.0.1'; server.listen(PORT, HOST, () => { console.log(`Observability Dashboard running at http://${HOST}:${PORT}`); }); ``` 2. Require authentication and authorization before returning any dashboard or API response. Use a securely generated API token, authenticated reverse proxy, mutual TLS, or an established identity provider. 3. Apply separate authorization rules to sensitive endpoints. In particular, restrict `/api/logs` and `/api/alerts` more heavily than aggregate metrics. 4. Require TLS whenever the service is exposed beyond loopback. Do not transmit authentication tokens or monitoring data over plaintext HTTP. 5. Implement structured redaction before data is logged or exported. At minimum, redact fields matching names such as `authorization`, `cookie`, `token`, `secret`, `password`, `apiKey`, and `credential`. 6. Make log export disabled by default and require an explicit configuration option to enable it. 7. Add deployment documentation warning that binding to `0.0.0.0` or `::` exposes monitoring information to the network. 8. Add tests confirming that: - The default listener is loopback-only. - Unauthenticated requests are rejected. - Users without log-viewing permission cannot access `/api/logs`. - Sensitive metadata is redacted. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/dashboard.js:469
Finding
Stored Cross-Site Scripting Through Unescaped Log Rendering<![CDATA[ ## Vulnerability Details **File Location**: `src/dashboard.js:469-475` **Vulnerability Type**: Stored cross-site scripting in the dashboard log viewer **Risk Level**: High ### Vulnerable Code ```javascript logViewer.innerHTML = logs.slice(0, 50).map(log => { const levelClass = log.level === 'error' ? 'log-error' : log.level === 'warn' ? 'log-warn' : log.level === 'debug' ? 'log-debug' : 'log-info'; return '<div class="log-entry"><span class="' + levelClass + '">[' + (log.timestamp || 'N/A') + '] ' + (log.level || 'info').toUpperCase() + '</span>: ' + (log.message || log.raw || 'N/A') + '</div>'; }).join(''); ``` ### Technical Analysis The dashboard builds HTML strings from log fields and assigns the resulting value to `innerHTML`. The values of `log.timestamp`, `log.level`, `log.message`, and `log.raw` are not HTML-escaped. Several public observability methods accept caller-controlled operation names, error messages, alert messages, and metadata that can reach the structured log file. A malicious value containing HTML markup can therefore be stored in `combined.log`, returned by `/api/logs`, and interpreted as executable markup when an operator views the dashboard. For example, a log message containing an image element with an event handler would be parsed as HTML rather than displayed as text. Because the dashboard automatically refreshes the log view every five seconds, exploitation does not require the victim to select or interact with the malicious entry after opening the dashboard. This is a stored XSS vulnerability because the payload can persist in the log file and execute in each dashboard viewer's browser. ### Attack Path 1. An attacker causes attacker-controlled content to be passed to an operation name, alert message, error message, or other field that is written to the observability log. 2. The logger serializes the malicious content into `combined.log`. 3. An admi ...[truncated 1189 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not use `innerHTML` for log data. Create DOM elements and assign untrusted values through `textContent`: ```javascript logViewer.replaceChildren(); for (const log of logs.slice(0, 50)) { const entry = document.createElement('div'); entry.className = 'log-entry'; const level = document.createElement('span'); const levelClass = log.level === 'error' ? 'log-error' : log.level === 'warn' ? 'log-warn' : log.level === 'debug' ? 'log-debug' : 'log-info'; level.className = levelClass; level.textContent = `[${log.timestamp || 'N/A'}] ${(log.level || 'info').toUpperCase()}`; entry.append(level, document.createTextNode(`: ${log.message || log.raw || 'N/A'}`)); logViewer.appendChild(entry); } ``` 2. If HTML generation is unavoidable, apply a well-reviewed contextual escaping library to every untrusted field. Escaping should cover at least `&`, `<`, `>`, `"`, and `'`. 3. Add a restrictive Content Security Policy, for example by disallowing inline scripts and limiting script sources to the dashboard itself. The current inline JavaScript would need to be moved into a separate static file or authorized with a nonce or hash. 4. Sanitize or redact log fields at ingestion as defense in depth. This should supplement, not replace, safe browser rendering. 5. Add regression tests with payloads containing script tags, image event handlers, malformed markup, quotation marks, and encoded HTML entities. Verify that payloads appear as literal text and never execute. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/alert-manager.js:447
Finding
Unrestricted Webhook Destination Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `src/alert-manager.js:447-465` **Vulnerability Type**: Server-side request forgery and uncontrolled alert-data transmission **Risk Level**: Medium ### Vulnerable Code ```javascript async _notifyWebhook(alert, rule) { if (!rule.webhookUrl) { return; } try { const payload = { alert: alert, rule: rule.toJSON(), timestamp: new Date().toISOString() }; // 使用 fetch 发送 webhook const fetch = global.fetch || require('node-fetch'); await fetch(rule.webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); } catch (error) { this.logger?.error('[AlertManager] Webhook notification failed', { alertId: alert.id, webhookUrl: rule.webhookUrl, error: error.message }); } } ``` ### Technical Analysis Webhook notifications are part of the declared alerting functionality, so the network transmission is not covert. However, `rule.webhookUrl` is passed directly to `fetch` without validating: - The URL scheme - The destination hostname - The resolved IP address - Loopback, link-local, or private network ranges - Redirect destinations - Approved webhook domains - The sensitivity of the payload A caller able to add or influence an alert rule can make the process send an HTTP POST request to an arbitrary URL accessible from the Node.js host. This creates a blind SSRF primitive that operates with the network reachability of the observability process. The payload includes the complete alert object and the serialized rule. Alert messages are caller-controlled through `fireAlert`, so they may contain sensitive operational details or secrets supplied by the integrating application. Those values can consequently be transmitted to an attacker-controlled destination. The request does not inspect or return the response body, which limits direct response disclosure. Nev ...[truncated 1829 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable webhooks by default and require an explicit configuration option to enable outbound alert delivery. 2. Maintain an allowlist of approved webhook hostnames or exact endpoint URLs. Reject destinations outside that list. 3. Require HTTPS for external webhook destinations. 4. Resolve the destination hostname before connecting and reject addresses in loopback, private, link-local, multicast, reserved, and unspecified ranges for both IPv4 and IPv6. 5. Protect against DNS rebinding by ensuring the validated address is the address used for the actual connection. Consider a dedicated outbound proxy with enforced destination policy. 6. Disable redirects when possible. If redirects are required, validate the scheme, hostname, and resolved address of every redirect target. 7. Add short connection and response timeouts and a maximum response-body policy to prevent resource exhaustion. 8. Redact sensitive alert fields before transmission and document the exact webhook schema. Avoid sending arbitrary caller-provided messages unless explicitly permitted. 9. Do not log complete webhook URLs because URLs may contain credentials or secret query parameters. Log a redacted hostname or destination identifier instead. 10. Add security tests covering loopback addresses, IPv6 loopback, private ranges, link-local ranges, encoded IP representations, DNS rebinding scenarios, redirects to internal addresses, and non-HTTPS schemes. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (27)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
threshold: rule.threshold
    });

    return rule.id;
  }

  /**
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The skill documentation is written entirely in Chinese, including headings, instructions, and usage guidance, with no indication that users may choose another language or that the skill is intentionally region-specific. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation promotes structured logging, LLM/MCP/A2A monitoring, file output, dashboard exposure, and webhook/export paths without warning that prompts, tool arguments, responses, file paths, tokens, session metadata, and other sensitive data may be collected and transmitted. In an observability skill, this omission is materially risky because users may enable telemetry broadly and leak secrets or personal data to logs, local files, dashboards, or third-party endpoints without realizing it.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The webhook notifier transmits full alert and rule data to an arbitrary configured URL with no validation, allowlisting, transport enforcement, redaction, or operator-facing disclosure. In practice this can leak internal metric names, thresholds, rule metadata, and potentially sensitive operational context to untrusted destinations, and if non-HTTPS URLs are allowed it also risks interception in transit.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The dashboard exposes operational logs through an unauthenticated HTTP endpoint (`/api/logs`). Logs commonly contain sensitive data such as prompts, tokens, internal errors, file paths, identifiers, or user content, so making them remotely readable can disclose secrets and internal state to anyone who can reach the service.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The server publishes status, metrics, logs, Prometheus output, and alert history over plain HTTP with no authentication, authorization, or network restriction visible in this file. This materially increases attack surface by enabling reconnaissance and data disclosure; depending on what `obs` records, the endpoints may leak sensitive operational, user, or secret-bearing telemetry.

Missing User Warnings

Medium
Confidence
77% confidence
Finding
This code enables LLM, MCP, and A2A monitoring by default and later exposes export/status methods that can surface collected telemetry, but the file provides no user-facing warning or disclosure about what data may be captured. For safety-sensitive observability code, monitoring and telemetry collection should be clearly disclosed when enabled, especially when it may include request metadata or message contents.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The monitor logs `...options` at debug level in `startCall`, and those options commonly include prompts, system messages, API parameters, or user-supplied context sent to the LLM. If debug logs are enabled or collected centrally, sensitive prompt contents, secrets, or personal data can be exposed to operators and downstream logging systems.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
On error, the code logs the full `result.error` object, which may contain provider request metadata, prompt fragments, response bodies, stack traces, headers, or identifiers. Error paths are especially risky because providers and wrappers often embed original request/response context in exception objects, causing unintended disclosure in logs.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This logger writes structured metadata to persistent files by default, and the API encourages callers to attach arbitrary context, errors, stack traces, metrics, and trace identifiers. In practice, this can easily capture secrets, tokens, personal data, or internal system details and retain them on disk without redaction, retention controls, or any explicit warning, increasing the risk of sensitive-data exposure if logs are accessed or exfiltrated.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
Natural-language content in the header and comments is written in Chinese, which imposes a specific language on maintainers or operators without any opt-in or justification in this file. Under the policy, forcing a specific language or locale without user choice can be a language/locale policy violation.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The monitor logs and retains operational metadata including server names, tool names, call IDs, execution timing, result sizes, and raw error objects in memory/history. In practice, error objects and operational traces often contain secrets, internal topology, file paths, tokens, prompts, or user-derived data, so storing and logging them without redaction or access controls can expose sensitive information to logs, dashboards, or other components.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The header explicitly describes a distributed tracing capability across multiple agents. However, the code only creates local trace/span objects in Maps and logs them through a local logger; there is no code for propagating trace context, exchanging data with other agents, or correlating spans across process or network boundaries.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
`setError()` stores full error messages and stack traces inside spans, which can capture file paths, internal implementation details, request contents, tokens embedded in exception text, or other sensitive diagnostics. In an observability component for multi-agent task execution, these records may later be exported or logged broadly, increasing unintended data disclosure risk.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The tracer logs arbitrary context data directly via `this.logger.debug('Trace started', { traceId, name, context })` with no filtering or redaction. If callers include secrets, tokens, prompts, user data, or agent-to-agent payloads in `context`, those values can be persisted to logs and exposed to operators, downstream log processors, or anyone with log access.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The natural-language content of the skill is predominantly in Chinese, including setup and usage instructions, which effectively imposes a language requirement on users. The policy allows locale constraints only when the skill offers user choice or clearly documents and justifies the restriction, which is not present here.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "小蒲萄 (Clawd)",
  "license": "MIT",
  "dependencies": {
    "winston": "^3.11.0"
  },
  "engines": {
    "node": ">=18.0.0"
Confidence
93% confidence
Finding
The dependency uses a caret range (^3.11.0) rather than a fully pinned version, which allows automatic adoption of newer compatible releases. While common in JavaScript projects, this increases supply-chain risk because a compromised or flawed upstream release could be pulled into installs without explicit review.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The primary natural-language documentation for the skill is written in Chinese, while the file does not indicate that this locale is optional or that the skill is specifically intended for a Chinese-only environment. Under the policy for language/locale handling, forcing a specific language without user opt-in can be a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The primary descriptive comments for the skill are written in Chinese, with no indication that language is configurable or intentionally constrained to a specific audience or region. Under the stated policy, language-specific natural-language guidance can be a locale-policy issue when it does not offer user choice or documented justification.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The file header comments and the rendered HTML interface are written in Chinese, and the HTML document is explicitly marked with lang="zh-CN". There is no indication that users can opt into another language or that the locale restriction is a documented, justified requirement, which creates a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The file's human-facing documentation and several runtime log messages are written in Chinese, which imposes a specific language choice without any visible opt-in or stated locale constraint. The policy only permits a fixed language when the user is given a choice or the locale restriction is clearly justified.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
Comments and descriptive text in the file are primarily Chinese, and the file does not indicate that this language choice is optional or justified by a region-specific constraint. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The file’s human-facing documentation and runtime messages are predominantly in Chinese, with no indication that the user can choose another language or that the skill is intentionally limited to a Chinese-speaking context. This can violate a language/locale policy when a skill imposes a specific language without opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This code file mixes English identifiers with Chinese-only descriptive comments and headings such as the feature list, with no indication that the language choice is optional or region-specific. Under the language/locale policy rule, a skill that implicitly fixes a specific language without opt-in can create accessibility and policy issues for users expecting neutral or selectable localization.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The comment at L002 and console output at L008 present user-facing natural language in Chinese only. Under the policy rule for language/locale, this forces a specific language without any opt-in, fallback, or documentation that the skill is intentionally region-specific.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/dashboard.js:516