Back to skill

Security audit

streaming-obs-bootstrap

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly an OBS setup helper, but it can expose the whole workspace over LAN and can start real recording or streaming without clear safeguards.

Review carefully before installing or running. Only use it in a workspace that contains no secrets, bind the overlay server to a trusted interface or serve only a public overlay directory, and avoid stream_dry_run unless the OBS profile is definitely pointed at a test destination. Back up OBS scenes first, and treat the scripts as live mutations of OBS and agentic-obs configuration.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/start_overlay_server.sh:4
Finding

Unauthenticated LAN Exposure of the Entire Workspace

Content
View full analysis

Vulnerability Details

File Location: scripts/start_overlay_server.sh, lines 4-13
Vulnerability Type: Excessive file exposure and missing network access controls
Risk Level: High

Vulnerable Code

bash
WORKSPACE="${OPENCLAW_WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)}"
PORT="${OVERLAY_PORT:-8787}"
LOG="$WORKSPACE/streaming-tests/http-server.log"

mkdir -p "$WORKSPACE/streaming-tests"

if ss -ltn | grep -q ":$PORT "; then
  echo "Overlay server already listening on :$PORT"
else
  nohup python3 -m http.server "$PORT" --directory "$WORKSPACE" > "$LOG" 2>&1 &

Technical Analysis

The script starts Python's basic HTTP server with the entire workspace as its document root. By default, python3 -m http.server listens on all available network interfaces and provides directory listings. The server has no authentication, authorization, or transport encryption.

The legitimate requirement is to make a small set of OBS overlay assets available to an OBS host. Serving the workspace root exceeds that requirement and may expose unrelated source files, configuration files, logs, agent state, and other material stored beneath the workspace.

The process is also launched through nohup in the background. Although this is not an operating-system startup mechanism, it allows the exposure to continue after the launching shell exits, and the project provides no corresponding shutdown command.

Attack Path

  1. An operator executes scripts/start_overlay_server.sh.
  2. The script starts an HTTP server on port 8787 and binds it to all interfaces by default.
  3. The complete workspace becomes the server's document root.
  4. A host with network access to port 8787 requests / and uses generated directory listings to enumerate files.
  5. The host requests accessible workspace files directly and downloads their contents without authentication.

No local account or OBS WebSocket credential is required for this attack; the attacker onl ...[truncated 602 chars]

Remediation
View remediation

Remediation Suggestions

  1. Serve only a dedicated public directory containing the required overlay files, rather than the workspace root.
  2. Copy or symlink explicitly approved assets into a deployment directory that cannot contain secrets or unrelated project files.
  3. Bind the server to a specific trusted interface using --bind, based on the intended OBS deployment model.
  4. Restrict port 8787 through host firewall rules so that only the OBS host can connect.
  5. Disable directory listing by replacing the development HTTP server with a minimally configured production server or a custom handler.
  6. Use authenticated HTTPS when overlays must cross an untrusted network.
  7. Record the spawned process ID and provide a stop command that reliably terminates the server.
  8. Validate OPENCLAW_WORKSPACE and OVERLAY_PORT before use.
  9. Add documentation warning operators not to place credentials in any directory exposed to OBS.

A safer structure would resemble:

bash
OVERLAY_ROOT="$WORKSPACE/streaming"
python3 -m http.server "$PORT" \
  --bind "$TRUSTED_BIND_ADDRESS" \
  --directory "$OVERLAY_ROOT"

The selected root must contain only files intended for network publication.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/obs_target_switch.sh:4
Finding

SQL Injection in OBS Target Configuration Helper

Content
View full analysis

Vulnerability Details

File Location: scripts/obs_target_switch.sh, lines 4-9
Vulnerability Type: SQL injection through unvalidated command-line arguments
Risk Level: Medium

Vulnerable Code

bash
HOST="${1:-localhost}"
PORT="${2:-4455}"
DB="${AGENTIC_OBS_DB:-$HOME/.agentic-obs/db.sqlite}"

sqlite3 "$DB" "update config set value='$HOST', updated_at=datetime('now') where key='obs_host';"
sqlite3 "$DB" "update config set value='$PORT', updated_at=datetime('now') where key='obs_port';"

Technical Analysis

The first two command-line arguments are inserted directly into SQL string literals. Quoting the overall SQL argument for the shell does not make the values safe for SQLite. A value containing a single quote can terminate the intended SQL literal and change the statement's structure.

Because the script does not validate the host or port, an attacker capable of influencing these arguments can append additional SQLite statements or alter the original update. This can be used to modify or delete data in the selected database.

The database path is also configurable through AGENTIC_OBS_DB. That behavior is not itself injection, but it allows the vulnerable operation to be directed at another SQLite database writable by the invoking account if an attacker controls both the environment and arguments.

Attack Path

  1. An attacker gains control over, or persuades an operator to use, a crafted host or port argument containing a quote and additional SQL syntax.
  2. The script interpolates the argument into the SQL command without escaping or parameter binding.
  3. SQLite parses attacker-supplied syntax as part of the statement rather than as data.
  4. The injected statement modifies, corrupts, or removes records in the target SQLite database.
  5. Subsequent agentic-obs operations use the altered configuration or fail because of database corruption.

This exploitation path requires the attacker to control script arguments or an upstream ...[truncated 638 chars]

Remediation
View remediation

Remediation Suggestions

  1. Validate HOST using a strict allowlist for IPv4, IPv6, or DNS hostname syntax.
  2. Require PORT to contain digits only and enforce the range 1-65535.
  3. Use a database API that supports parameterized queries instead of constructing SQL strings in the shell.
  4. Validate that the database path refers to the expected agentic-obs database and is not a symbolic link to an unintended target.
  5. Fail closed when validation fails and do not invoke SQLite.
  6. Back up the configuration database before changing it if operational recovery is important.
  7. Add tests covering quotes, semicolons, control characters, malformed addresses, and out-of-range ports.

Preferred implementation using parameter binding:

python
import sqlite3

connection = sqlite3.connect(database_path)
connection.execute(
    "UPDATE config SET value = ?, updated_at = datetime('now') WHERE key = 'obs_host'",
    (host,),
)
connection.execute(
    "UPDATE config SET value = ?, updated_at = datetime('now') WHERE key = 'obs_port'",
    (str(port),),
)
connection.commit()

Allowlist validation should still be applied even when parameterized queries are used.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description focuses on scene-pack setup/migration, browser overlay configuration, recording validation, and browser-source troubleshooting. The supplied code does something narrower and materially different: it tunes OBS audio input levels for named inputs via mcporter. While this still touches OBS, audio baseline adjustment is not mentioned as part of the skill’s purpose, and the script does not implement scene rebuilding, validation, overlay wiring, or recording smoke tests. That makes this a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The page presents operational controls such as 'Go Live', 'Stop Stream', and scene switching, but the JavaScript only logs messages and shows placeholder alerts. In a streaming/OBS bootstrap context, this can mislead an operator into believing critical actions were executed when they were not, causing accidental downtime, failed recordings, or unintended live state during production use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Lines L08-L09 perform file-backed configuration writes via sqlite3, changing persistent OBS target settings in the user's database. Although the script prints a message after the fact, there is no confirmation prompt, comment, or other advance disclosure warning that it will modify local state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script deletes a fixed set of OBS scenes before recreating them, but it provides no warning, confirmation, backup, or dry-run mode. In the context of a streaming/bootstrap skill, this can cause accidental loss of an operator's existing scene configuration if run against the wrong OBS instance or at the wrong time, especially since the skill is explicitly used for setup or migration on local or remote OBS.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script starts OBS recording immediately without any confirmation, visible warning, or opt-in gate. In the context of a reusable setup/migration skill that may be run against local or remote OBS instances, this can unintentionally capture sensitive desktop content, audio, notifications, or private scenes if the operator invokes it without realizing recording begins right away.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/start_overlay_server.sh (reported line 13)May include surrounding context.

sh
if ss -ltn | grep -q ":$PORT "; then
  echo "Overlay server already listening on :$PORT"
else
  nohup python3 -m http.server "$PORT" --directory "$WORKSPACE" > "$LOG" 2>&1 &
  sleep 1
  echo "Started overlay server on :$PORT"
fi

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script unconditionally starts and stops a live OBS stream with no interactive confirmation, dry-run guard, or explicit safety check. In the context of streaming software, this can accidentally broadcast to a real configured destination, causing unintended disclosure, reputational harm, or policy violations if run against production OBS instances.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document declares lang="en", which hard-codes English as the language/locale for the skill content. Under the stated policy, locale-specific behavior should either be user-selectable or clearly justified as region-specific, neither of which appears in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document declares lang="en", which hard-codes English as the page language. Under the policy criteria, forcing a specific language without user opt-in or clear region-specific justification is a natural-language locale policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document declares lang="en", which hard-codes English as the page language. Under the policy criteria, a forced language setting without user opt-in or an explicit region-specific justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document declares lang="en", which forces an English locale in the skill asset without any visible opt-in, fallback, or justification that this overlay is region-specific. Under the policy, fixed language settings can be a natural-language locale violation when no user choice is offered.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The HTML overlay presents user-facing text entirely in English ("Thanks for Watching!", "Powered by...", "Built with...") and sets the document language to English. Under the policy rule for natural-language violations, forcing a specific language without user opt-in can be a locale-policy issue when no choice or justification is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The document sets lang="en" on the root HTML element, which hard-codes English as the language for the skill content. Under the stated policy, forcing a specific language without user opt-in or clear region-specific justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The troubleshooting guidance explicitly instructs use of <html lang="en">, which imposes a specific language/locale in natural-language documentation. The file does not indicate that this is optional, user-selected, or required for a region-specific use case, so it may conflict with language/locale choice policy.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The script invokes an external command via mcporter call to change OBS input volume and query mute state. Although it prints a success message afterward, there is no prior warning, confirmation, or comment disclosing that running the script will actively modify audio configuration for the listed inputs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The script changes OBS scenes and stops recording as part of an automated walkthrough, but it contains no comments or user-facing output explaining these actions. While these operations align with a smoke-test purpose, the absence of any disclosure reduces user awareness of changes to live recording/session state.

Content

No source excerpt is available for this finding.