T09 · Insecure Skill Coding Practices
- 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: MediumVulnerable 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, andDISCORD_CHANNELdirectly 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
-
Construct JSON exclusively with
jqstring 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} }') -
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} } }') -
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.
-
Validate the final patch against the expected schema and explicitly reject unknown properties before calling
config.patch. -
Display the proposed change and require confirmation before applying it when arguments may originate from an untrusted or automated source.
-
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.
-
