Back to skill

Security audit

Red Alert

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned for Israeli alert data, but it ships a long-running listener with unbounded local log growth and vulnerable network-facing websocket dependencies.

Review before installing if you plan to run the real-time listener or daemon. Prefer updating the Socket.IO dependency tree first, run the listener under storage and process limits, and add log rotation or retention for /data/clawd/tmp/redalert-*.jsonl. The skill does not show clear malicious behavior, but its current real-time mode is under-scoped for unattended use.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/listener-daemon.mjs:42
Finding
Unbounded Persistence of Attacker-Controlled Socket.IO Event Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/listener-daemon.mjs:42-58` and `scripts/listener.mjs:26-32` **Vulnerability Type**: Unbounded file growth and synchronous processing of untrusted remote data **Risk Level**: Medium ### Vulnerable Code `scripts/listener-daemon.mjs:42-58`: ```js socket.onAny((eventName, ...args) => { if (eventName === "connect" || eventName === "disconnect" || eventName === "connect_error") return; for (const alertData of args) { if (!alertData || typeof alertData !== "object") continue; const record = { event: alertData.type || eventName, cities: alertData.cities || [], title: alertData.title || "", instructions: alertData.instructions || "", cityCount: (alertData.cities || []).length, receivedAt: new Date().toISOString() }; const line = JSON.stringify(record); fs.appendFileSync(ALERTS_FILE, line + "\n"); fs.appendFileSync(PENDING_FILE, line + "\n"); console.log(line); } }); ``` `scripts/listener.mjs:26-32`: ```js socket.onAny((event, ...args) => { if (event === "connect" || event === "disconnect") return; for (const alert of args) { const record = { event, ...alert, receivedAt: new Date().toISOString() }; const line = JSON.stringify(record); console.log(line); fs.appendFileSync(ALERTS_FILE, line + "\n"); } }); ``` ### Technical Analysis Both persistent listeners consume events from an external Socket.IO service and append the received content to local JSONL files. Although the daemon performs a basic object-type check, neither implementation enforces: - A maximum event or serialized-record size - Maximum lengths or counts for fields such as `cities`, `title`, and `instructions` - A write-rate limit - A maximum file size or storage quota - Log rotation or retention - Available-disk-space checks - Backpressure or bounded buffering The daemon writes each accepted record to two files using synchronous filesys ...[truncated 2045 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Enforce a strict event allowlist and schema** - Process only documented alert event names. - Require `cities` to be an array of bounded strings. - Require `title`, `instructions`, and event names to be strings. - Reject unexpected nested objects and excessive array lengths. 2. **Limit input and record sizes** - Set maximum lengths for every remote string. - Limit the number of cities per alert. - Serialize the validated record and reject it if its byte length exceeds a conservative threshold. 3. **Rate-limit persistence** - Cap accepted events per time window. - Deduplicate repeated alert identifiers or equivalent records. - Drop or aggregate excess events while recording a bounded diagnostic counter. 4. **Use bounded storage** - Implement size- and time-based log rotation. - Configure retention and deletion of old JSONL files. - Place alert files on a dedicated volume with a filesystem quota. - Define a maximum pending-file size and an acknowledgement or truncation process. 5. **Avoid synchronous writes** - Replace `appendFileSync` with asynchronous, backpressure-aware writes. - Use a bounded queue and define an explicit overflow policy. - Ensure write failures are handled without crashing or indefinitely retrying. 6. **Monitor resource thresholds** - Check available disk space before writing. - Stop persistence or enter a degraded mode when storage reaches a defined threshold. - Emit local metrics or alerts for dropped events, oversized records, queue saturation, and write failures. 7. **Harden runtime isolation** - Run the listener as an unprivileged service account. - Restrict filesystem access to a dedicated data directory. - Apply process memory, CPU, and storage limits through the service manager or container runtime. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (12)

Known Vulnerable Dependency: socket.io-parser==4.2.5 — 2 advisory(ies): CVE-2026-69185 (Socket.IO: Zero-attachment Memory Exhaustion); CVE-2026-33151 (socket.io allows an unbounded number of binary attachments)

High
Category
Supply Chain
Confidence
98% confidence
Finding
The lockfile pins socket.io-parser to 4.2.5, and the finding cites published advisories for unbounded or zero-attachment handling that can lead to memory exhaustion. In this skill, the parser is part of the real-time Socket.IO client stack consuming untrusted network data, so a malicious or malformed server response could trigger denial of service in the agent process.

Known Vulnerable Dependency: ws==8.18.3 — 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
97% confidence
Finding
The lockfile includes ws 8.18.3, which the finding associates with memory disclosure and memory exhaustion issues. Because this skill connects to external websocket infrastructure for real-time alert data, the dependency processes attacker-controllable frames from the network, making denial of service and possible data exposure more relevant than in an offline-only package.

External Script Fetching

High
Category
Supply Chain
Content
#!/bin/bash
# Quick status check for RedAlert API
curl -s -H "Accept: application/json" "https://redalert.orielhaim.com/api/status" | python3 -m json.tool
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill exposes shell and environment-variable usage but does not declare any explicit tool scope or allowed-tools boundary. That omission weakens least-privilege controls and can let an agent invoke broader capabilities than reviewers or operators expect, especially since the skill includes executable setup and runtime commands.

External Transmission

Medium
Category
Data Exfiltration
Content
## 1) REST Endpoints Used by Skill

### `GET https://api.tzevaadom.co.il/alerts-history`
- **Used by:** `scripts/analyze.mjs`
- **Purpose:** Pull recent alert history (nationwide), then filter locally by city/time (`--city`, `--since`).
- **Auth:** None
Confidence
50% 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
## 1) REST Endpoints Used by Skill

### `GET https://api.tzevaadom.co.il/alerts-history`
- **Used by:** `scripts/analyze.mjs`
- **Purpose:** Pull recent alert history (nationwide), then filter locally by city/time (`--city`, `--since`).
- **Auth:** None
Confidence
50% 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
## 1) REST Endpoints Used by Skill

### `GET https://api.tzevaadom.co.il/alerts-history`
- **Used by:** `scripts/analyze.mjs`
- **Purpose:** Pull recent alert history (nationwide), then filter locally by city/time (`--city`, `--since`).
- **Auth:** None
Confidence
50% 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
## 1) REST Endpoints Used by Skill

### `GET https://api.tzevaadom.co.il/alerts-history`
- **Used by:** `scripts/analyze.mjs`
- **Purpose:** Pull recent alert history (nationwide), then filter locally by city/time (`--city`, `--since`).
- **Auth:** None
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This code explicitly documents and performs persistent writes of all received alerts to JSONL files, including a secondary pending file, but provides no user-facing disclosure beyond internal comments. Under SQP-2 for code files, file writes that affect local data handling should have some visible warning, confirmation, or accompanying documented disclosure.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The daemon authenticates a network connection using process.env.RED_ALERT_API_KEY, which is access to sensitive credentials. Although the header comment describes the remote connection, there is no visible warning or documentation in this file about reading credentials from the environment.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The file's natural-language documentation and CLI examples are centered on Hebrew city names and Israel-specific formatting, which effectively impose a locale-specific usage pattern without any opt-in or stated regional scope. Under the policy, locale constraints should either be explicitly justified as region-specific or offer a user choice.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"version": "1.0.0",
  "type": "module",
  "dependencies": {
    "socket.io-client": "^4.7.0"
  }
}
Confidence
94% confidence
Finding
The dependency uses a caret range (^4.7.0), which allows automatic installation of newer minor and patch releases. This can introduce supply-chain risk because a compromised upstream release or an unexpected breaking change could be pulled in without explicit review, especially for a network-facing library like socket.io-client.

Static analysis

No suspicious patterns detected.