Back to skill

Security audit

Codecast

Security checks for vulnerabilities and agentic risk

Overview

Codecast does stream coding-agent sessions to Discord, but it also encourages broad permission bypass and includes under-scoped remote control paths that can expose sensitive work or affect local processes.

Install only after reviewing the scripts and using a private, trusted Discord destination. Avoid global permission bypass, do not run PR review or parallel task mode on untrusted input until eval usage is fixed, disable the bridge unless channel and user allowlists are mandatory, and assume streamed sessions may reveal secrets, source code, paths, and command output.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/review-pr.sh:69
Finding
Arbitrary Shell Command Injection Through Pull Request Metadata and Review Prompts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/review-pr.sh:69-82, 113-150, 156-164` **Vulnerability Type**: Shell command injection through `eval` **Risk Level**: Critical ### Vulnerable Code ```bash PR_TITLE=$(echo "$PR_JSON" | python3 -c "import json,sys;print(json.load(sys.stdin).get('title',''))") PR_BRANCH=$(echo "$PR_JSON" | python3 -c "import json,sys;print(json.load(sys.stdin).get('headRefName',''))") PR_BASE=$(echo "$PR_JSON" | python3 -c "import json,sys;print(json.load(sys.stdin).get('baseRefName','main'))") PR_BODY=$(echo "$PR_JSON" | python3 -c "import json,sys;d=json.load(sys.stdin);print(d.get('body','')[:500])") if [ -n "$CUSTOM_PROMPT" ]; then REVIEW_PROMPT="$CUSTOM_PROMPT" else REVIEW_PROMPT="Review this pull request thoroughly. PR #${PR_NUM}: ${PR_TITLE} Branch: ${PR_BRANCH} → ${PR_BASE} Changes: +${PR_ADDITIONS} -${PR_DELETIONS} ${PR_BODY:+Description: ${PR_BODY}} Review guidelines: 1. Check for bugs, logic errors, and edge cases 2. Review code style and consistency 3. Look for security vulnerabilities 4. Check test coverage 5. Evaluate naming and documentation 6. Note any performance concerns Read the changed files, understand the context, and provide a structured review with: - Summary of changes - Issues found (critical, major, minor) - Suggestions for improvement - Overall assessment (approve, request changes, or comment) Write your final review to /tmp/pr-review-${PR_NUM}.md When completely finished, run: openclaw system event --text 'Done: PR #${PR_NUM} review complete' --mode now" fi case "$AGENT" in claude*) AGENT_CMD="claude -p --dangerously-skip-permissions --output-format stream-json --verbose '${REVIEW_PROMPT}'" ;; codex*) AGENT_CMD="codex exec --json --full-auto '${REVIEW_PROMPT}'" ;; *) AGENT_CMD="${AGENT} '${REVIEW_PROMPT}'" ;; esac RELAY_FLAGS="-w $WORKDIR -t $TIMEOUT -n '${AGENT} Review'" [ "$THREAD_MODE" = true ] && RELAY_FLAGS="$RELAY_FLAGS --thread" [ "$SKIP_REA ...[truncated 1898 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `eval` entirely. - Build every command as a Bash array, with each prompt and option stored as a distinct array element. - Pass PR metadata only as data, never as shell source. - Restrict `AGENT` to an explicit allowlist such as `claude` or `codex`. - Validate numeric options before use. - Avoid global permission-bypass flags. A safe construction should follow this pattern: ```bash case "$AGENT" in claude) AGENT_CMD=( claude -p --output-format stream-json --verbose "$REVIEW_PROMPT" ) ;; codex) AGENT_CMD=(codex exec --json "$REVIEW_PROMPT") ;; *) echo "Unsupported agent" >&2 exit 1 ;; esac RELAY_ARGS=(-w "$WORKDIR" -t "$TIMEOUT" -n "$AGENT Review") [ "$THREAD_MODE" = true ] && RELAY_ARGS+=(--thread) [ "$SKIP_READS" = true ] && RELAY_ARGS+=(--skip-reads) [ -n "$RATE_LIMIT" ] && RELAY_ARGS+=(-r "$RATE_LIMIT") bash "$SCRIPT_DIR/dev-relay.sh" "${RELAY_ARGS[@]}" -- "${AGENT_CMD[@]}" ``` ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/parallel-tasks.sh:59
Finding
Arbitrary Shell Command Injection Through Parallel Task Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/parallel-tasks.sh:59-75, 133-157` **Vulnerability Type**: Shell command injection through task-file content and `eval` **Risk Level**: Critical ### Vulnerable Code ```bash while IFS= read -r line || [ -n "$line" ]; do line=$(echo "$line" | sed 's/#.*//' | xargs) [ -z "$line" ] && continue TASK_DIR=$(echo "$line" | cut -d'|' -f1 | xargs) TASK_PROMPT=$(echo "$line" | cut -d'|' -f2- | xargs) [ -z "$TASK_DIR" ] || [ -z "$TASK_PROMPT" ] && { echo "⚠️ Skipping invalid line: $line" >&2 continue } TASK_DIR="${TASK_DIR/#\~/$HOME}" TASK_DIRS+=("$TASK_DIR") TASK_PROMPTS+=("$TASK_PROMPT") TASK_NAMES+=("$(basename "$TASK_DIR")") TASK_COUNT=$((TASK_COUNT + 1)) done < "$TASKS_FILE" COMPLETION_MSG="When completely finished, run: openclaw system event --text 'Done: ${TASK_NAME} - task complete' --mode now" case "$AGENT" in claude*) AGENT_CMD="claude -p --dangerously-skip-permissions --output-format stream-json --verbose '${TASK_PROMPT}. ${COMPLETION_MSG}'" ;; codex*) AGENT_CMD="codex exec --json --full-auto '${TASK_PROMPT}. ${COMPLETION_MSG}'" ;; *) AGENT_CMD="${AGENT} '${TASK_PROMPT}'" ;; esac RELAY_FLAGS="-w $WORK_DIR -t $TIMEOUT -n '${AGENT} [$TASK_NAME]'" RELAY_FLAGS="$RELAY_FLAGS --thread" [ "$SKIP_READS" = true ] && RELAY_FLAGS="$RELAY_FLAGS --skip-reads" [ -n "$RATE_LIMIT" ] && RELAY_FLAGS="$RELAY_FLAGS -r $RATE_LIMIT" eval "bash '$SCRIPT_DIR/dev-relay.sh' $RELAY_FLAGS -- $AGENT_CMD" & ``` ### Technical Analysis Each task prompt is read from a user-selected file and interpolated into a command string. The string is subsequently executed using `eval`. A malicious prompt containing a single quote and shell operators can escape the intended argument and introduce arbitrary shell commands. The task directory, task name, agent option, timeout, and rate-limit values also participate in strings later reparsed by `eval`, creating additional injec ...[truncated 763 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace all command strings and `eval` calls with Bash arrays. - Treat task directories, prompts, names, and agent selections as untrusted data. - Restrict the agent option to a fixed allowlist. - Validate `TIMEOUT` and `RATE_LIMIT` as bounded positive integers. - Resolve task directories with `realpath` and optionally restrict them to approved project roots. - Do not append executable completion instructions to untrusted prompts. - Run parallel agents with scoped filesystem permissions rather than global bypass modes. Example: ```bash AGENT_CMD=( claude -p --output-format stream-json --verbose "${TASK_PROMPT}. ${COMPLETION_MSG}" ) RELAY_ARGS=(-w "$WORK_DIR" -t "$TIMEOUT" -n "$AGENT [$TASK_NAME]" --thread) bash "$SCRIPT_DIR/dev-relay.sh" "${RELAY_ARGS[@]}" -- "${AGENT_CMD[@]}" & ``` ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/discord-bridge.py:67
Finding
Discord Bridge Allows Process Control Without Mandatory Channel or User Authorization<![CDATA[ ## Vulnerability Details **File Location**: `scripts/discord-bridge.py:67-69, 150-160, 247-255, 279-287, 424-435` **Vulnerability Type**: Fail-open authorization and unrestricted PID termination **Risk Level**: High ### Vulnerable Code ```python BOT_TOKEN = get_bot_token() CHANNEL_ID = os.environ.get("BRIDGE_CHANNEL_ID", "") ALLOWED_USERS = set(filter(None, os.environ.get("BRIDGE_ALLOWED_USERS", "").split(","))) def kill_session(pid): """Kill a codecast session.""" try: pid = int(pid) os.kill(pid, signal.SIGTERM) time.sleep(1) try: os.kill(pid, 0) os.kill(pid, signal.SIGKILL) except OSError: pass return True, f"Session {pid} terminated" except (ValueError, OSError) as e: return False, f"Failed to kill {pid}: {e}" # Check channel filter if CHANNEL_ID and channel_id != CHANNEL_ID: return # Check user filter if ALLOWED_USERS and user_id not in ALLOWED_USERS: return if content.lower().startswith("!kill"): parts = content.split() if len(parts) < 2: reply(channel_id, "Usage: `!kill <PID>`") return ok, msg = kill_session(parts[1]) reply(channel_id, f"{'✅' if ok else '❌'} {msg}") return if not CHANNEL_ID: print("⚠️ Warning: No BRIDGE_CHANNEL_ID set — listening on all channels", file=sys.stderr) print(f" Allowed users: {', '.join(ALLOWED_USERS) if ALLOWED_USERS else 'all'}", flush=True) ``` ### Technical Analysis Both access-control settings are optional and fail open. An empty channel configuration accepts messages from every channel visible to the bot, while an empty user allowlist accepts every non-bot user. The `!kill` handler passes an arbitrary numeric PID directly to `os.kill`. Unlike log and input operations, `kill_session` does not verify that the PID appears in the active Codecast session registry. Consequently, any authorized Discord message sender—or any visible user under default confi ...[truncated 1032 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Refuse to start unless a specific channel and nonempty user allowlist are configured. - Validate guild, channel, and user IDs using exact identifier syntax. - Associate each session with an explicit authorized channel and set of users. - Before signaling a PID, require that it is present in `get_active_sessions()`, owned by the current user, and still corresponds to the expected process start time. - Prefer opaque session identifiers over operating-system PIDs. - Require confirmation or a short-lived authorization token for destructive commands. - Disable plain-text forwarding by default. - Rate-limit commands and record an audit log containing user ID, channel ID, session ID, and action. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/parse-stream.py:202
Finding
Sensitive Source Code, Command Output, and Reasoning Are Transmitted Without Redaction<![CDATA[ ## Vulnerability Details **File Location**: `scripts/parse-stream.py:202-225, 320-378` **Vulnerability Type**: Sensitive-data disclosure to Discord **Risk Level**: High ### Vulnerable Code ```python if itype == "command_execution": cmd = item.get("command", "?") if started: post(f"🖥️ **Exec** `{truncate(cmd, 300)}`") bash_commands.append(cmd) tools_used["command_execution"] = tools_used.get("command_execution", 0) + 1 else: output = item.get("output", "") exit_code = item.get("exit_code") if output: output = truncate(output.strip(), 800) post(f"📤 **Output** ```\n{output}\n```") elif itype == "reasoning": text = item.get("text", "").strip() if text and not started: post(f"🧠 *{truncate(text, 400)}*") if tool == "Write": fp = inp.get("file_path", "?") content = inp.get("content", "") preview, total = format_file_preview(content) preview = truncate(preview, 800) post(f"📝 **Write** `{fp}` ({total} lines)\n```\n{preview}\n```") elif tool == "Bash": cmd = truncate(inp.get("command", "?"), 300) post(f"🖥️ **Bash** `{cmd}`") bash_commands.append(cmd) elif tool == "Read": fp = inp.get("file_path", "?") if not skip_reads: post(f"👁️ **Read** `{fp}`") elif tool == "WebFetch": url = inp.get("url", "?") post(f"🌐 **Fetch** `{url}`") if sub.get("type") == "text" and _last_tool_name == "Bash": stdout = sub.get("text", "").strip() if stdout: stdout = truncate(stdout, 800) post(f"📤 **Output** ```\n{stdout}\n```") ``` ### Technical Analysis The parser forwards file-write previews, commands, command output, agent responses, web targets, and Codex reasoning traces to Discord. It performs only length truncation; it has no secret scanning, content classification, repository allowlist, or destination-specific disclosure policy. The `--skip-reads` setting hides only read-event notific ...[truncated 1071 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Default to metadata-only reporting: tool name, status, and redacted relative path. - Do not transmit reasoning traces. - Disable file-content previews and command-output forwarding unless explicitly enabled per session. - Add secret detection for common token formats, private keys, authorization headers, connection strings, `.env` values, and high-entropy strings. - Allow users to define approved files, command classes, and repository roots. - Redact absolute paths and query-string credentials. - Display a clear preflight summary of what data will leave the machine and require explicit consent. - Add an emergency local-only mode and a per-event confirmation mode for sensitive projects. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dev-relay.sh:140
Finding
Unrestricted Webhook URL Can Redirect Session Data to Arbitrary Endpoints<![CDATA[ ## Vulnerability Details **File Location**: `scripts/dev-relay.sh:140-147, 188-195` **Vulnerability Type**: Unvalidated outbound destination and potential SSRF/data exfiltration **Risk Level**: High ### Vulnerable Code ```bash SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" WEBHOOK_URL=$(cat "$SCRIPT_DIR/.webhook-url" 2>/dev/null | tr -d '\n') [ -z "$WEBHOOK_URL" ] && { echo "❌ Error: .webhook-url not found in $SCRIPT_DIR" >&2 echo " Create it: echo 'https://discord.com/api/webhooks/ID/TOKEN' > $SCRIPT_DIR/.webhook-url" >&2 exit 1 } if ! curl -s -o /dev/null -w "%{http_code}" "$WEBHOOK_URL" 2>/dev/null | grep -q "^200$"; then echo "❌ Error: Webhook URL appears invalid or unreachable" >&2 echo " Check: $SCRIPT_DIR/.webhook-url" >&2 exit 1 fi post() { local msg="$1" name="${2:-$AGENT_NAME}" [ ${#msg} -gt 1950 ] && msg="${msg:0:1900}…*(truncated)*" local jmsg jname jmsg=$(python3 -c "import json,sys;print(json.dumps(sys.stdin.read()))" <<< "$msg") jname=$(python3 -c "import json;print(json.dumps('$name'))") curl -s -X POST "$WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d "{\"content\":${jmsg},\"username\":${jname}}" -o /dev/null 2>/dev/null || true } ``` The platform adapter also trusts the destination directly: ```python webhook_url = os.environ.get("WEBHOOK_URL", "") subprocess.run( ["curl", "-s", "-X", "POST", url, "-H", "Content-Type: application/json", "-d", json.dumps(payload)], capture_output=True, timeout=10, text=True ) ``` ### Technical Analysis The validation verifies only that the configured URL returns HTTP 200. It does not require HTTPS, verify that the hostname is an approved Discord domain, validate the webhook path, or reject local and private-network addresses. If the configuration file or environment can be modified, all streamed development content can be redirected to an attacker-controlled endpoint. The initial GET and subsequent POST requests can also target internal ...[truncated 756 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse the URL before use and require `https`. - Allowlist only documented Discord webhook hosts, such as `discord.com`, and validate the expected `/api/webhooks/<id>/<token>` path. - Reject embedded credentials, IP literals, localhost, link-local addresses, and private-network destinations. - Disable redirects with `curl --max-redirs 0`. - Use certificate verification explicitly and fail closed on TLS errors. - Protect `.webhook-url` with mode `0600`, verify ownership, and reject symbolic links. - Prefer a trusted configuration store and show the normalized destination before the first transmission. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/setup.md:29
Finding
Skill Requires Global Coding-Agent Permission Bypass<![CDATA[ ## Vulnerability Details **File Location**: `references/setup.md:29-38` **Additional Locations**: `SKILL.md:20-21`, `scripts/review-pr.sh:143-149`, `scripts/parallel-tasks.sh:135-141` **Vulnerability Type**: Excessive privileges and disabled approval controls **Risk Level**: High ### Vulnerable Code and Instructions ```json { "permissions": { "defaultMode": "bypassPermissions", "allow": ["*"] } } ``` ```bash exec background:true command:"{baseDir}/scripts/dev-relay.sh -w ~/projects/myapp -- claude -p --dangerously-skip-permissions --output-format stream-json --verbose 'Your task here'" ``` ```bash AGENT_CMD="claude -p --dangerously-skip-permissions --output-format stream-json --verbose '${REVIEW_PROMPT}'" AGENT_CMD="codex exec --json --full-auto '${REVIEW_PROMPT}'" ``` ### Technical Analysis Streaming an agent session does not inherently require granting unrestricted command and filesystem permissions. The setup guide changes the default Claude configuration globally to bypass permission checks and allow every operation. Review and parallel modes reinforce this behavior with dangerous noninteractive flags. This removes approval boundaries for all future Claude sessions using that configuration, not only Codecast sessions. It also magnifies the consequences of malicious repositories, prompt injection, and the command-injection vulnerabilities elsewhere in the project. ### Attack Path 1. A user follows the setup guide and configures global `bypassPermissions` with `allow: ["*"]`. 2. The user launches a review or task against untrusted content. 3. Repository text, PR content, or Discord-forwarded instructions influence the coding agent. 4. The agent executes shell commands or modifies files without asking for approval. 5. The operation runs with all privileges available to the user account. ### Impact Assessment A compromised or manipulated agent can access any user-readable file, modify writable projects and configuration, execut ...[truncated 180 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the instruction to configure global `bypassPermissions`. - Remove `--dangerously-skip-permissions` and avoid `--full-auto` for untrusted repositories. - Use per-project, least-privilege allowlists. - Require approval for shell execution, network access, credential access, and writes outside the selected workspace. - Run agents in containers or sandboxes with read-only mounts where practical. - Use short-lived, minimally scoped credentials. - Clearly distinguish trusted local tasks from reviews of attacker-controlled pull requests. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/dev-relay.sh:217
Finding
Codecast Session Metadata Is Stored Insecurely in a Shared Temporary Directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/dev-relay.sh:217-221` **Vulnerability Type**: Unsafe temporary state and plaintext sensitive metadata **Risk Level**: Medium ### Vulnerable Code ```bash SESSION_DIR="/tmp/dev-relay-sessions" mkdir -p "$SESSION_DIR" SESSION_FILE="$SESSION_DIR/$$.json" cat > "$SESSION_FILE" <<EOF {"pid":$$,"command":"$COMMAND","workdir":"$WORKDIR","agent":"$AGENT_NAME","relayDir":"$RELAY_DIR","platform":"$PLATFORM","startTime":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"} EOF ``` The bridge trusts records from this location: ```python SESSION_DIR = "/tmp/dev-relay-sessions" for fname in os.listdir(SESSION_DIR): if not fname.endswith(".json"): continue fpath = os.path.join(SESSION_DIR, fname) with open(fpath) as f: data = json.load(f) ``` ### Technical Analysis The session directory is created under a globally shared temporary location without an explicit restrictive mode. Session files are also created without an explicit `0600` mode or ownership and symlink checks. Their content includes complete command strings, prompts, working directories, PIDs, and relay-directory paths. Values are inserted into JSON using shell interpolation rather than a JSON serializer. Quotes, backslashes, or newlines in commands and paths can create malformed records. On a multi-user system, default umask settings may permit other local users to inspect metadata. If directory permissions permit tampering, forged or altered records may also influence bridge session discovery and log access. ### Attack Path 1. A Codecast session starts. 2. The script creates or reuses `/tmp/dev-relay-sessions`. 3. It writes command and project metadata using default process permissions. 4. Another local user reads the files to obtain sensitive commands, prompts, paths, and process identifiers. 5. Where permissions allow modification, the user may attempt to replace or forge records consumed by the bridge. ### Impact Assessment The p ...[truncated 279 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Store state under a user-private runtime directory such as `$XDG_RUNTIME_DIR/codecast`. - Create the directory with mode `0700` and verify that it is owned by the current user. - Set `umask 077` before creating session state. - Create records atomically with mode `0600`. - Reject symbolic links and files not owned by the current user. - Serialize records through Python or another real JSON encoder rather than shell interpolation. - Include and verify process start time or a random session nonce to prevent PID-reuse confusion. - Avoid storing full prompts and commands unless required; redact sensitive arguments. ]]>

T08 · Insecure Dependencies

Note
Location
references/advanced-modes.md:81
Finding
Discord Bridge Dependency Is Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `references/advanced-modes.md:81` **Vulnerability Type**: Unpinned third-party runtime dependency **Risk Level**: Low ### Vulnerable Instruction ```markdown **Requires:** `websocket-client` (`pip install websocket-client`) and a Discord bot token. ``` ### Technical Analysis The installation command resolves the latest package available from the user’s active Python package index. It does not pin a reviewed version, verify artifact hashes, or require an isolated environment. This is not evidence that `websocket-client` is malicious. The issue is that the effective dependency can change after the Skill is reviewed, which weakens reproducibility and supply-chain assurance. ### Attack Path 1. A user follows the documented installation command. 2. `pip` resolves a mutable package version from the configured index or mirror. 3. A compromised index, mirror, account, or future vulnerable release supplies unsafe code. 4. The package is imported by `discord-bridge.py` and executes in the bridge process. ### Impact Assessment A compromised dependency would execute with the privileges of the Codecast user and would have access to the Discord bot token, gateway messages, session metadata, local files available to the process, and outbound network connectivity. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Add a reviewed, version-pinned dependency file. - Use hash checking, for example `pip install --require-hashes -r requirements.txt`. - Install dependencies inside a dedicated virtual environment. - Document the approved package index. - Use automated vulnerability and dependency-update monitoring. - Re-review dependency changes before updating the pinned version. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (65)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
PR review automation involving gh CLI access, repository checkout, review prompt generation, and potential comment posting introduces source-code access and write actions against external systems. Those capabilities go well beyond Discord streaming and could expose private repository data or perform unintended actions if users are not explicitly warned.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
PR review automation involving gh CLI access, repository checkout, review prompt generation, and potential comment posting introduces source-code access and write actions against external systems. Those capabilities go well beyond Discord streaming and could expose private repository data or perform unintended actions if users are not explicitly warned.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
PR review automation involving gh CLI access, repository checkout, review prompt generation, and potential comment posting introduces source-code access and write actions against external systems. Those capabilities go well beyond Discord streaming and could expose private repository data or perform unintended actions if users are not explicitly warned.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
PR review automation involving gh CLI access, repository checkout, review prompt generation, and potential comment posting introduces source-code access and write actions against external systems. Those capabilities go well beyond Discord streaming and could expose private repository data or perform unintended actions if users are not explicitly warned.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
PR review automation involving gh CLI access, repository checkout, review prompt generation, and potential comment posting introduces source-code access and write actions against external systems. Those capabilities go well beyond Discord streaming and could expose private repository data or perform unintended actions if users are not explicitly warned.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
PR review automation involving gh CLI access, repository checkout, review prompt generation, and potential comment posting introduces source-code access and write actions against external systems. Those capabilities go well beyond Discord streaming and could expose private repository data or perform unintended actions if users are not explicitly warned.

Missing User Warnings

High
Confidence
97% confidence
Finding
The description promotes observability and zero token burn but does not prominently warn that agent session content is transmitted to Discord via webhook, potentially including commands, file paths, outputs, and other sensitive development data. In a security context, undisclosed external transmission is a serious data-leakage risk because users may invoke the skill without informed consent.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The Discord bridge turns a one-way session streaming tool into a bidirectional remote-control channel by forwarding Discord messages to agent stdin and exposing process-management commands. This materially changes the risk profile: anyone with access to the Discord channel or bot workflow may be able to influence agent behavior, trigger sensitive actions, or manipulate active development sessions remotely.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Exposing a `!kill <PID>` command through Discord allows remote termination of local processes, which can be abused for denial of service, interruption of reviews, or disruption of unrelated work if process targeting is weak. This is especially risky in a tool whose stated purpose is session visibility, because remote process control is a separate privileged capability with destructive effects.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The setup directs users to globally disable Claude Code's permission safeguards by setting bypassPermissions with allow:["*"], which removes approval gates for all actions, not just Discord streaming. This creates a broad privilege expansion that could let any future prompt, tool invocation, or compromised workflow perform sensitive operations without user review.

Missing User Warnings

High
Confidence
98% confidence
Finding
The documentation tells users to disable permission prompts but provides no warning that this weakens a core security control across all Claude Code activity. Users may apply the setting believing it is required for streaming, unaware that it enables unattended execution of sensitive actions far beyond the skill's stated purpose.

Agent Config Directory Access

High
Category
Agent Snooping
Content
## 3. Skip the permissions prompt (Claude Code only)

Create `~/.claude/settings.json` if it doesn't exist:
```json
{
  "permissions": {
Confidence
93% confidence
Finding
Directing users to create or modify ~/.claude/settings.json changes the agent's global configuration in its home directory, affecting behavior outside this skill. In this case, the modification is especially dangerous because it weakens approval controls for all future agent sessions, not just codecast usage.

Agent Config Directory Access

High
Category
Agent Snooping
Content
#   --parallel <f>  Parallel tasks mode: run tasks from file across worktrees
#
# For Claude Code: uses -p --output-format stream-json --verbose for clean JSON output
# Prerequisites: ~/.claude/settings.json with defaultMode: "bypassPermissions"

set -uo pipefail
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Credential Access

High
Category
Privilege Escalation
Content
fi

# Bot token (optional, needed for --thread mode in text channels)
# Priority: CODECAST_BOT_TOKEN env var > macOS Keychain > .bot-token file
BOT_TOKEN="${CODECAST_BOT_TOKEN:-}"
if [ -z "$BOT_TOKEN" ] && command -v security &>/dev/null; then
  BOT_TOKEN=$(security find-generic-password -s discord-bot-token -a codecast -w 2>/dev/null || true)
Confidence
90% confidence
Finding
The script accesses sensitive credentials from the macOS Keychain to obtain a Discord bot token. Although this may support legitimate thread creation, credential retrieval increases the blast radius because the script now handles reusable secrets that may grant broader Discord access than a single webhook URL.

Unvalidated Output Injection

High
Category
Output Handling
Content
done
  wait "$RELAY_PID" 2>/dev/null
else
  # Non-Claude agents: use raw output relay with ANSI stripping
  script -q "$OUTPUT_FILE" "$CMD_FILE" &
  AGENT_PID=$!
  echo "$AGENT_PID" > "$RELAY_DIR/agent.pid"
Confidence
92% confidence
Finding
In raw-output mode, the script captures arbitrary agent terminal output and forwards it with only partial ANSI stripping. Untrusted output can still include mentions, deceptive formatting, URLs, embedded secrets, or control-like content that causes downstream abuse in Discord, and the relay lacks robust sanitization or content filtering.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The skill is described as a streaming/visibility tool, but this file implements a bidirectional control bridge from Discord into local agent sessions. That creates a remote command-and-control path for coding agents, allowing anyone with channel access and bot reachability to influence local development actions beyond passive observability.

Credential Access

High
Category
Privilege Escalation
Content
python3 discord-bridge.py [--channel CHANNEL_ID] [--users USER_ID,...] [--verbose]

Environment:
    CODECAST_BOT_TOKEN   Discord bot token (or macOS Keychain: discord-bot-token/codecast)
    BRIDGE_CHANNEL_ID    Discord channel ID to watch
    BRIDGE_ALLOWED_USERS Comma-separated Discord user IDs (empty = all users)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
python3 discord-bridge.py [--channel CHANNEL_ID] [--users USER_ID,...] [--verbose]

Environment:
    CODECAST_BOT_TOKEN   Discord bot token (or macOS Keychain: discord-bot-token/codecast)
    BRIDGE_CHANNEL_ID    Discord channel ID to watch
    BRIDGE_ALLOWED_USERS Comma-separated Discord user IDs (empty = all users)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
python3 discord-bridge.py [--channel CHANNEL_ID] [--users USER_ID,...] [--verbose]

Environment:
    CODECAST_BOT_TOKEN   Discord bot token (or macOS Keychain: discord-bot-token/codecast)
    BRIDGE_CHANNEL_ID    Discord channel ID to watch
    BRIDGE_ALLOWED_USERS Comma-separated Discord user IDs (empty = all users)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def get_bot_token():
    """Get bot token from env, keychain, or file."""
    token = os.environ.get("CODECAST_BOT_TOKEN", "")
    if token:
        return token
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The code forwards Discord content directly into agent stdin via a named pipe or `/proc/<pid>/fd/0`, enabling remote prompt injection and indirect command execution through the agent. In the context of coding agents that can edit files and run shell commands, this effectively gives remote parties operational influence over the local environment.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The `!kill` command allows Discord messages to terminate local sessions, which exceeds the stated purpose of relaying output. This gives remote users an immediate denial-of-service primitive against active agent processes, and if channel/user scoping is misconfigured the effect can be triggered broadly.

Missing User Warnings

High
Confidence
98% confidence
Finding
Using claude with --dangerously-skip-permissions disables approval safeguards and allows the agent to act without interactive permission checks. Because the same script also feeds arbitrary task prompts and can target working directories containing valuable code, this materially increases the chance of destructive file changes, unintended command execution, or broader compromise from prompt mistakes or malicious instructions.

Ssd 3

High
Confidence
99% confidence
Finding
The file header and implementation show that this utility is designed to forward agent output, command output, file previews, and summaries to an external chat platform in plain language. In a coding-agent context, these streams frequently contain highly sensitive workspace data, making the skill inherently risky if used without strict disclosure, minimization, and redaction controls.

Ssd 3

High
Confidence
98% confidence
Finding
The helper functions are used to prepare and truncate file-content previews before posting, which confirms that content exposure is intentional and normalized rather than accidental. Truncation reduces size but does not reduce sensitivity; the first or last lines of files often contain credentials, headers, internal endpoints, or personally sensitive data.

Static analysis

No suspicious patterns detected.