Back to skill

Security audit

Activity Control Ui

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local activity dashboard, but it exposes agent status through an unauthenticated server with file-serving and dependency risks.

Review this before installing. Run it only on a trusted machine and network, prefer binding it to 127.0.0.1, add authentication before exposing it, fix the static file serving path containment, remove the external font request if privacy matters, and update the ws dependency from a trusted registry.

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/start-server.js:55
Finding

Arbitrary Local File Disclosure Through Directory Traversal

Content
View full analysis
{ if (err) { res.writeHead(404); res.end('Not Found'); return; } const contentType = mimeTypes[ext] || 'application/octet-stream'; res.writeHead(200, { 'Content-Type': contentType }); res.end(data); }); ``` ### Technical Analysis The server uses the request URL as a filesystem path and passes it to `path.join()` without first restricting it to an approved static directory. It does not canonicalize and validate the resulting path against an allowed root. Traversal components such as `../` can therefore cause the normalized path to escape `skillDir`. If the HTTP client preserves traversal components in the request path, `fs.readFile()` can read any file accessible to the Node.js process. The implementation also serves files from the entire project root rather than limiting access to the declared `assets` directory. There is no allowlist of static resources. ### Attack Path 1. The attacker obtains network access to the HTTP server. 2. The attacker sends a request containing preserved traversal segments, for example using a client option that does not normalize the URL path. 3. `path.join(skillDir, filePath)` resolves the traversal outside the project directory. 4. `fs.readFile()` opens the resulting operating-system path. 5. The server returns the file contents in the HTTP response. The exact number of traversal segments depends on the installation path and the target file. ### Impact Assessment An unauthenticated attacker may read files available to the Node.js process. Depending on the host configuration, this may expose: - Application source and configuration files - Environment or ...[truncated 245 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/start-server.js:72
Finding

Unauthenticated Exposure of Agent Telemetry and WebSocket Actions

Content
View full analysis
{ connectedClients.add(ws); // Send current state on connect ws.send(JSON.stringify({ type: 'status', ...currentStatus })); if (activityHistory.length > 0) { activityHistory.forEach(activity => { ws.send(JSON.stringify({ type: 'activity', ...activity })); }); } ws.send(JSON.stringify({ type: 'tasks', tasks: currentStatus.tasks })); ws.on('message', (data) => { try { const msg = JSON.parse(data); if (msg.action === 'compact') { // Tell all clients we're compacting - the actual compact is handled by OpenClaw broadcastActivity('Initiating context compaction...', 'info'); // In real integration, this would call the OpenClaw API } } catch (e) { console.error('WS message error:', e); } }); ws.on('close', () => { connectedClients.delete(ws); }); }); ``` ```javascript server.listen(port, () => { console.log(`Activity Control UI running at http://localhost:${port}`); console.log('WebSocket endpoint: ws://localhost:${port}/ws/activity'); }); ``` ### Technical Analysis The HTTP status endpoint and WebSocket server have no authentication or authorization. Every WebSoc ...[truncated 2431 chars]
Remediation
View remediation
{ console.log(`Activity Control UI running at http://127.0.0.1:${port}`); }); ``` - Require a cryptographically random authentication token for both HTTP and WebSocket access. - Authorize every control action separately; viewing status must not automatically grant maintenance privileges. - Validate WebSocket upgrade paths and reject paths other than `/ws/activity`. - Validate `Origin` against an explicit allowlist. - Use TLS whenever access is permitted beyond loopback. - Add security headers and disable permissive cross-origin behavior. - Minimize transmitted status fields and redact session identifiers or sensitive task content unless explicitly requested. - Add message-size limits, rate limits, and a strict schema for WebSocket messages. - Require explicit user confirmation before connecting the compact handler to an actual OpenClaw operation. ]]>

T08 · Insecure Dependencies

Warning
Location
package-lock.json:14
Finding

Dependency Locked to a Third-Party Package Mirror

Content
View full analysis
Remediation
View remediation

other

Note
Location
assets/control-ui.html:7
Finding

Undisclosed External Request to Google Fonts from the Local Dashboard

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `assets/control-ui.html` - Main dashboard HTML with inline SVG avatar

Known Vulnerable Dependency: ws==8.20.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding

The lockfile pins ws to 8.20.0, and the supplied advisory data indicates this version is affected by an uninitialized memory disclosure and a memory-exhaustion denial of service. Because this skill is a real-time activity dashboard and likely exposes or consumes WebSocket traffic, the vulnerable dependency sits directly in a relevant attack surface, making remote exploitation more plausible than in a package that does not use WebSockets at runtime.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.20.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding

The package references ws 8.20.0, which is flagged with advisories for uninitialized memory disclosure and memory exhaustion denial of service. This skill is a real-time activity dashboard and is likely to expose or consume WebSocket traffic, so a vulnerable WebSocket library is directly relevant and could allow remote attackers to crash the UI/backend connection or potentially leak process memory.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The heading and introductory description switch to Chinese and do not indicate that the user can choose another language. This can violate language/locale policy when a skill effectively forces one language without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document sets lang="zh-CN", and the visible interface text is entirely in Chinese, with no indication that users can opt into another language. Under the policy, forcing a specific language or locale without user choice or clear justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The dashboard is not purely observational: it includes a control path that sends a compact action over the WebSocket, allowing the UI to alter agent/session state. In a monitoring skill, exposing state-changing controls increases risk because any user with access to the page, or any script able to drive the page/session, can trigger context compaction and potentially affect agent behavior or lose useful context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Clicking the compaction button immediately sends a state-changing command with no confirmation, warning, or undo path. Because compaction can discard or restructure active context, accidental clicks or UI-driven misuse can disrupt ongoing tasks and reduce traceability of what the agent was using.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The HTTP handler maps req.url directly into path.join(skillDir, filePath) and reads the resulting path without restricting requests to an intended static assets directory or validating path traversal sequences. This allows the server to expose arbitrary files within the skill directory, which can leak source code or embedded secrets/configuration and exceeds the stated dashboard-only purpose.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a caret range (^8.20.0), which permits automatic installation of newer 8.x releases and reduces build reproducibility. In security-sensitive agent skills, unpinned dependencies increase supply-chain risk and make it harder to guarantee which code is deployed or audited.

Content

Scanner excerpt · package.json (reported line 14)May include surrounding context.

json
"license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "ws": "^8.20.0"
  }
}

Static analysis

No suspicious patterns detected.