Back to skill

Security audit

skill-to-http-flash

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-built, but it can expose local skill execution over a network with permissive defaults and persistent job/service behavior that users should review before installing.

Install only if you intend to turn local skills into callable services. Before running a generated server, bind it to localhost or a trusted interface, set an API key, restrict CORS, use HTTPS for cross-host access, avoid enabling LLM schema extraction for skills containing secrets, and treat async job output as persistent local data.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (11)

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill advertises and operationalizes powerful capabilities including filesystem access, environment-variable use, shell execution, and network exposure, yet does not declare permissions or trust boundaries. That mismatch increases the risk of over-broad invocation and unsafe deployment because operators may not realize the skill can create services, read local skills, write persistent state, and expose them over HTTP.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The code sends SKILL.md content to a configurable external LLM endpoint during parameter extraction, which expands the skill's behavior beyond local HTTP wrapping into outbound network exfiltration of potentially sensitive skill content. In this context, the risk is real because the feature is not tightly scoped to the advertised local conversion task and could disclose proprietary prompts, internal instructions, or embedded secrets from the skill file.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The trigger phrases are broad and natural-language-heavy, including generic intents like exposing a skill as an API or structured I/O. That can cause unintended invocation in unrelated contexts, which is risky here because the skill creates runnable HTTP microservices and writes artifacts to disk.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The migration guide instructs users to run a destructive command with `--delete-files` during project recreation, but it does not clearly warn that files may be permanently removed or advise backup/verification steps first. In this skill context, users are performing operational migration tasks, so copy-paste execution is likely; that increases the chance of accidental data loss even though this is not an exploit primitive by itself.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation explicitly supports supplying `FLASH_API_KEY` via an environment variable but does not warn that environment variables can be exposed through process listings, crash dumps, CI logs, shell history, or misconfigured observability tooling. In a standalone HTTP service context, this can lead to accidental credential disclosure and unauthorized access to the generated API.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The K8s guidance recommends persisting certs and API keys across restarts on shared storage but gives no warning about filesystem permissions, encryption, secret scoping, or separating sensitive material from general data. If that storage is broadly mounted or insufficiently protected, attackers or other workloads could read long-lived credentials and TLS private keys.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The implementation transmits skill content to an external LLM service without any visible consent, prompt, or disclosure at the point of use. This is dangerous because SKILL.md may contain proprietary logic, secrets, or sensitive operational instructions, and users of a 'standalone local HTTP flash' tool may reasonably expect processing to remain local.

Unbounded Output

Medium
Category
Output Handling
Content
- **Subprocess direct execution** — no LLM drift, 100% reproducible, `<2s` cold start
- **JSON → CLI mapping** — request JSON auto-maps to long flags (`{"foo_bar": 10}` → `--foo-bar 10`), field-name allowlist `[a-z][a-z0-9_]*` + argv-as-list (no shell injection)
- **Unified envelope** — business failure (`exit_code != 0`) returns HTTP 200 + `success:false`; only framework errors use HTTP status codes
- **Sync + async** — `POST /run` (60s default, 512KB truncation) and `POST /run/async` (no truncation, in-memory + JSONL persistence, logrotate, SQLite export)
- **Multi-agent runtime** — auto-detects skill dirs for OpenClaw / Claude Code / Cursor / generic `./skills` out of the box, or override via `FLASH_SKILL_DIR` / `--skill-dir`
- **HTTP by default, HTTPS on demand** — self-signed SAN cert auto-generation, optional API-Key auth (`hmac.compare_digest` constant-time), configurable CORS
- **Self-contained output** — generated `server.py` has cert / job store / argv builder / envelope inlined; `scp` it to any machine and run
Confidence
93% confidence
Finding
The README documents that the async endpoint stores job output with 'no truncation', which implies a caller can trigger arbitrarily large stdout/stderr capture and persistence. In a service that executes subprocesses on behalf of remote users, unbounded output can exhaust memory, disk, or log storage and become a practical denial-of-service vector, especially because the tool is explicitly designed to expose skills over HTTP.

Unbounded Output

Medium
Category
Output Handling
Content
<tr><td><code>GET /health</code></td><td>Health check</td></tr>
<tr><td><code>GET /schema</code></td><td>Input parameter schema</td></tr>
<tr><td><code>POST /run</code></td><td>Execute skill (sync, 60s default)</td></tr>
<tr><td><code>POST /run/async</code></td><td>Execute skill (async, no truncation)</td></tr>
<tr><td><code>GET /jobs/&lcub;job_id&rcub;</code></td><td>Poll async job</td></tr>
</table></div>
<div class="card"><h3>Sync</h3>
Confidence
82% confidence
Finding
The async path explicitly preserves full subprocess output and persists job results, allowing a called skill to emit arbitrarily large stdout/stderr. An authenticated caller can trigger memory growth, oversized JSONL files, and degraded service or disk exhaustion, especially because async results are retained and retrievable.

Unbounded Output

Medium
Category
Output Handling
Content
| GET | `/health` | Probe entry file + interpreter |
| GET | `/schema` | Parameter schema |
| POST | `/run` | Sync execute (default {timeout}s timeout, 512KB truncation) |
| POST | `/run/async` | Async execute (no truncation) |
| GET | `/jobs/{{job_id}}` | Poll async job |

## Quick Start
Confidence
84% confidence
Finding
The documented async execution path explicitly states 'no truncation', implying job output may be stored or returned without size bounds. In a tool that wraps arbitrary skill subprocesses, unbounded stdout/stderr or result payloads can exhaust memory or disk, leading to denial of service and potentially destabilizing the host service.

Session Persistence

Medium
Category
Rogue Agent
Content
fi

echo "Starting {skill_name} API..."
nohup python3 server.py start > "$DATA_DIR/logs/{skill_name}.log" 2>&1 &

for i in $(seq 1 10); do
    sleep 1
Confidence
81% confidence
Finding
Starting the generated API under `nohup` in the background creates a persistent long-lived service outside the interactive session, and the broader tool is designed to expose arbitrary skills as network services. In this context, easy backgrounding is more sensitive because it can leave an unaudited HTTP wrapper for arbitrary local skill execution running indefinitely, increasing exposure if authentication, binding, or output controls are weak.

Static analysis

No suspicious patterns detected.