Back to skill

Security audit

Agent Council

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with OpenClaw agent and Discord management, but it makes durable gateway, workspace, Discord, and optional cron changes with weak scoping and some misleading safety claims.

Review the scripts before installing, use it only with trusted operators, avoid sensitive health or personal data in Discord channels and agent memory, back up OpenClaw gateway config first, and treat agent names, IDs, models, workspaces, and channel IDs as trusted input until the JSON construction and confirmation gaps are fixed.

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/create-agent.sh:162
Finding

Unescaped Agent Metadata Allows JSON Injection into Privileged Gateway Configuration

Content
View full analysis

Vulnerability Details

File Location: scripts/create-agent.sh, lines 162–209
Vulnerability Type: JSON injection into privileged configuration
Risk Level: Medium

Vulnerable Code

bash
# Build new agent object
NEW_AGENT=$(cat <<EOF
{
  "id": "$ID",
  "name": "$NAME",
  "workspace": "$WORKSPACE",
  "model": {
    "primary": "$MODEL"
  },
  "identity": {
    "name": "$NAME",
    "emoji": "$EMOJI"
  }
}
EOF
)

# Merge existing agents with new agent
ALL_AGENTS=$(echo "$EXISTING_AGENTS" | jq --argjson new "$NEW_AGENT" '. + [$new]')

echo -e "${GREEN}✓ Prepared agent config${NC}"
echo ""

# 5. Build config patch
echo -e "${YELLOW}⚙️  Building config patch...${NC}"

# Start with agents list
CONFIG_PATCH=$(cat <<EOF
{
  "agents": {
    "list": $ALL_AGENTS
  }
}
EOF
)

# Add binding if Discord channel specified
if [[ -n "$DISCORD_CHANNEL" ]]; then
  echo -e "${BLUE}Adding Discord channel binding for #$DISCORD_CHANNEL${NC}"

  # Get existing bindings
  EXISTING_BINDINGS=$(echo "$CURRENT_CONFIG" | jq -c '.bindings // []')

  # Build new binding
  NEW_BINDING=$(cat <<EOF
{
  "agentId": "$ID",
  "match": {
    "channel": "discord",
    "peer": {
      "kind": "channel",
      "id": "$DISCORD_CHANNEL"
    }
  }
}
EOF
)

  # Merge bindings
  ALL_BINDINGS=$(echo "$EXISTING_BINDINGS" | jq --argjson new "$NEW_BINDING" '. + [$new]')

The generated patch is subsequently applied at line 245:

bash
openclaw gateway config.patch --raw "$(cat $TEMP_CONFIG)" --note "Add $NAME agent via agent-creator skill"

Technical Analysis

The script embeds command-line values such as ID, NAME, WORKSPACE, MODEL, EMOJI, and DISCORD_CHANNEL directly into JSON documents. These values are not JSON-escaped and are not validated against restrictive formats.

An input containing quotation marks and JSON structur ...[truncated 2674 chars]

Remediation
View remediation

Remediation Suggestions

  1. Construct JSON exclusively with jq string arguments instead of interpolated here-documents:

    bash
    NEW_AGENT=$(jq -n \
      --arg id "$ID" \
      --arg name "$NAME" \
      --arg workspace "$WORKSPACE" \
      --arg model "$MODEL" \
      --arg emoji "$EMOJI" \
      '{
         id: $id,
         name: $name,
         workspace: $workspace,
         model: {primary: $model},
         identity: {name: $name, emoji: $emoji}
       }')
    
  2. Build Discord bindings the same way:

    bash
    NEW_BINDING=$(jq -n \
      --arg agent_id "$ID" \
      --arg channel_id "$DISCORD_CHANNEL" \
      '{
         agentId: $agent_id,
         match: {
           channel: "discord",
           peer: {kind: "channel", id: $channel_id}
         }
       }')
    
  3. Apply strict format validation before creating files or modifying configuration:

    • Agent IDs: allow only lowercase letters, digits, and hyphens.
    • Discord channel IDs: allow digits only.
    • Model identifiers: validate against the expected provider/model syntax.
    • Workspace paths: canonicalize the path and enforce an approved parent directory where appropriate.
    • Names and emoji: impose reasonable length limits and reject control characters.
  4. Validate the final patch against the expected schema and explicitly reject unknown properties before calling config.patch.

  5. Display the proposed change and require confirmation before applying it when arguments may originate from an untrusted or automated source.

  6. Add regression tests containing quotes, backslashes, newlines, JSON delimiters, and control characters to confirm that every argument remains a JSON string and cannot change document structure.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
Findings (28)

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · README.md (reported line 314)May include surrounding context.

})

text

### Send Messages to Agents

**Direct communication:**
```typescript

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

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

})

text

### Send Messages to Agents

**Direct communication:**
```typescript

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · README.md (reported line 394)May include surrounding context.

text

**4. Agent-to-agent communication:**
Agents can send messages to each other:
```typescript
// In Watson's context
sessions_send({

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

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

text

**4. Agent-to-agent communication:**
Agents can send messages to each other:
```typescript
// In Watson's context
sessions_send({

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description is substantially broader than the supplied code. The code chunk is specifically a channel renaming script for Discord/OpenClaw, plus related reference updates in config prompts and markdown workspace files. It does support one slice of Discord channel organization, but it does not provide agent creation, autonomous AI agent tooling, or multi-agent system setup. Its primary purpose is materially narrower and different from the claimed 'complete toolkit.' Therefore the description does not accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The supplied code only implements Discord channel setup and related OpenClaw gateway configuration guidance. It does not create autonomous AI agents, manage multi-agent systems, or provide a 'complete toolkit' as declared. The Discord channel organization portion of the description is accurate, but the broader declared purpose materially overstates the code's capabilities and primary scope. There are no obvious unrelated or hidden behaviors beyond channel querying/creation and config handling, but the description does not accurately represent this code chunk as a whole.

Content

No source excerpt is available for this finding.

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · README.md (reported line 470)May include surrounding context.

md
### Finding Discord IDs

**Enable Developer Mode:**
- Settings → Advanced → Developer Mode

**Copy IDs:**

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

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

md
### Finding Discord IDs

**Enable Developer Mode:**
- Settings → Advanced → Developer Mode

**Copy IDs:**

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

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

md
1. **Organize channels in categories** - Group related agent channels
2. **Use descriptive channel names** - Clear purpose from the name
3. **Set specific system prompts** - Give each channel clear context
4. **Document agent responsibilities** - Keep SOUL.md updated
5. **Set up memory cron jobs** - For agents with ongoing work
6. **Test agents individually** - Before integrating into team

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
90% confidence
Finding

The function returns the full systemPrompt value from configuration when it contains the old channel name, and later the script uses that secret-bearing content to construct and print a patch command. System prompts can contain sensitive operational instructions, tokens, internal references, or other confidential context, so exposing them to stdout or shell history can leak privileged information.

Content

Scanner excerpt · scripts/rename_channel.py (reported line 126)May include surrounding context.

python
try:
        prompt = config['channels']['discord']['guilds'][guild_id]['channels'][channel_id].get('systemPrompt', '')
        if old_name in prompt:
            return prompt
    except (KeyError, TypeError):
        pass
    return None

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · README.md (reported line 16)May include surrounding context.

md
- Optional cron job setup

**Discord Channel Management:**
- Create Discord channels via API
- Configure OpenClaw gateway allowlists
- Set channel-specific system prompts
- Rename channels and update references

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README explicitly promotes a health-tracking agent but does not warn about handling sensitive personal health data, consent, retention, or security controls. In a multi-agent and Discord-integrated environment, this can lead users to collect or transmit health information through channels and workspaces that may not be appropriate for regulated or sensitive data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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 · README.md (reported line 489)May include surrounding context.

md
- `--emoji` (required) - Agent emoji
- `--specialty` (required) - What the agent does
- `--model` (required) - LLM to use (provider/model-name)
- `--workspace` (required) - Where to create agent files
- `--discord-channel` (optional) - Discord channel ID to bind

### setup-channel.py

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly describes capabilities involving shell execution, file creation/modification, environment use, and Discord/network actions, but it does not declare any explicit tool scope such as allowed-tools or permissions. That makes the operational boundary ambiguous and increases the chance an agent will invoke powerful tools without least-privilege constraints.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

This duplicate RA2 finding points to the same persistence concern: the skill is designed to create durable agent files and optional automation. In context, that is more dangerous than ordinary documentation because the package is specifically about autonomous multi-agent operation with memory and Discord bindings.

Content

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

md
- **Emoji** (e.g., "🔬")
- **Specialty** (what the agent does)
- **Model** (which LLM to use)
- **Workspace** (where to create agent files)
- **Discord channel ID** (optional)

#### 2. Run Creation Script

Session Persistence

Medium
Category
Rogue Agent
Confidence
74% confidence
Finding

This duplicate RA2 finding points to the same persistence concern: the skill is designed to create durable agent files and optional automation. In context, that is more dangerous than ordinary documentation because the package is specifically about autonomous multi-agent operation with memory and Discord bindings.

Content

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

md
- **Emoji** (e.g., "🔬")
- **Specialty** (what the agent does)
- **Model** (which LLM to use)
- **Workspace** (where to create agent files)
- **Discord channel ID** (optional)

#### 2. Run Creation Script

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

This section states that running the tool creates agent workspaces and related persistent configuration. Persistence itself is not malicious, but in an agent skill it materially increases risk because generated agents may retain memory, bindings, and scheduled behavior beyond the user's immediate awareness.

Content

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

md
- `--emoji` (required) - Agent emoji
- `--specialty` (required) - What the agent does
- `--model` (required) - LLM to use (provider/model-name)
- `--workspace` (required) - Where to create agent files
- `--discord-channel` (optional) - Discord channel ID to bind

**Output:**

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script applies a gateway configuration patch and triggers an automatic restart immediately after printing the patch, but it does not require an explicit confirmation from the operator before making the live change. In an agent-management skill, this creates a real operational security risk because a mistaken invocation, malformed parameters, or unintended agent binding can alter routing behavior and disrupt service availability without a final safety check.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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/create-agent.sh (reported line 294)May include surrounding context.

sh
echo -e "${YELLOW}📅 Memory System${NC}"
echo ""
echo "Would you like to set up a daily memory cron job for $NAME?"
echo "This will create a job that reviews and updates the agent's daily memory file."
echo ""
read -p "Create daily memory cron? (y/n): " -n 1 -r
echo ""

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring for load_config says it loads configuration via CLI and is "safe, no direct file access." However, when the CLI call fails, the code invokes openclaw config file, resolves the returned path, and opens that file directly with open(). This is an active contradiction between the inline documentation and the implemented behavior.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/rename_channel.py (reported line 36)May include surrounding context.

python
capture_output=True, text=True, timeout=10
        )
        if result.returncode != 0:
            path_result = subprocess.run(
                ["openclaw", "config", "file"],
                capture_output=True, text=True, timeout=10
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup_channel.py (reported line 37)May include surrounding context.

python
capture_output=True, text=True, timeout=10
        )
        if result.returncode != 0:
            path_result = subprocess.run(
                ["openclaw", "config", "file"],
                capture_output=True, text=True, timeout=10
            )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This script performs bulk file modifications through update_workspace_files when a workspace is provided, and those writes occur automatically via write_text without an interactive confirmation step. Although the script logs what it is doing, there is no pre-write warning or opt-in for the file changes themselves, which is a safety-relevant operation affecting user data.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring at L029 says the configuration is loaded via CLI with 'safe, no direct file access'. However, on CLI failure the code invokes openclaw config file, constructs a filesystem path, and opens that file directly at L041-L044. This is an active contradiction between the inline documentation and actual behavior.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/rename_channel.py (reported line 31)May include surrounding context.

python
def load_config() -> Dict[str, Any]:
    """Load OpenClaw configuration via CLI (safe, no direct file access)."""
    try:
        result = subprocess.run(
            ["openclaw", "config", "get", ""],
            capture_output=True, text=True, timeout=10
        )

Static analysis

No suspicious patterns detected.