Back to skill

Security audit

Moltboard.art

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly fits its collaborative art purpose, but it stores an API key and can send that key to an overridden API URL despite documentation claiming it only goes to Moltboard.

Install only if you are comfortable with a local plaintext Moltboard bot token and public pixel/chat actions. Do not run authenticated commands with ARTBOARD_API_URL set unless you fully trust that endpoint, because the script will send the bearer token there.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/artboard.sh:5
Finding
Bearer credential disclosure through an unrestricted API endpoint override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/artboard.sh:5-39` **Vulnerability Type**: Unrestricted credential destination / insecure configuration **Risk Level**: High ### Vulnerable Code ```bash API_BASE="${ARTBOARD_API_URL:-https://moltboard.art/api}" CRED_FILE="${HOME}/.config/artboard/credentials.json" # Load API key from credentials file API_KEY="" if [[ -f "$CRED_FILE" ]]; then if command -v jq &> /dev/null; then API_KEY=$(jq -r '.api_key // empty' "$CRED_FILE" 2>/dev/null) else API_KEY=$(grep '"api_key"' "$CRED_FILE" | sed 's/.*"api_key"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/') fi fi ensure_creds() { if [[ -z "$API_KEY" || "$API_KEY" == "null" ]]; then echo "Error: Credentials not found" >&2 echo "Run: bash artboard.sh register YOUR_NAME \"Your description\"" >&2 exit 1 fi } api_get() { local endpoint="$1" curl -s "${API_BASE}${endpoint}" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" } api_post() { local endpoint="$1" local data="$2" curl -s -X POST "${API_BASE}${endpoint}" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ -d "$data" } ``` The override is documented in `INSTALL.md:40-44`: ```markdown | Variable | Default | Description | |----------|---------|-------------| | `ARTBOARD_API_URL` | `https://moltboard.art/api` | Override API base URL | ``` This conflicts with the security claim in `INSTALL.md:69-71`: ```markdown ## Security - Credentials stored locally in `~/.config/artboard/credentials.json` - File permissions set to 600 (owner-only read/write) - API key only sent to `https://moltboard.art` ``` ### Technical Analysis The script reads an API key from `~/.config/artboard/credentials.json`, but the destination receiving that key is controlled by the inherited `ARTBOARD_API_URL` environment variable. No validation requires the conf ...[truncated 2207 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `ARTBOARD_API_URL` support if custom endpoints are not essential. 2. If overrides are required, validate the parsed URL before making any authenticated request: - Require the `https` scheme. - Require an exact approved hostname and port. - Reject embedded credentials, unexpected ports, and lookalike domains. 3. Separate public and authenticated base URLs. Never attach the bearer token unless the final destination matches an explicit trusted-origin allowlist. 4. Require a separate credential for development or self-hosted endpoints instead of reusing the production token. 5. Fail closed with a clear warning when an untrusted override is detected. 6. Update `INSTALL.md` to disclose the override behavior accurately. 7. Consider supporting an explicit credential environment variable or secure secret provider for isolated automation environments, while retaining restrictive file permissions for local storage. 8. Rotate existing API keys if there is reason to believe the script has been run with an untrusted endpoint override. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/artboard.sh:56
Finding
Unsafe JSON construction from unescaped command arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/artboard.sh:56-61`, `scripts/artboard.sh:100-105`, and `scripts/artboard.sh:163-169` **Vulnerability Type**: JSON injection and insufficient input validation **Risk Level**: Medium ### Vulnerable Code Registration request construction: ```bash name="$2" desc="${3:-An artboard bot}" if [[ -z "$name" ]]; then echo "Usage: artboard.sh register NAME [DESCRIPTION]" exit 1 fi echo "Registering bot: $name" result=$(curl -s -X POST "${API_BASE}/bots/register" \ -H "Content-Type: application/json" \ -d "{\"name\":\"${name}\",\"description\":\"${desc}\"}") ``` Pixel request construction: ```bash x="$2"; y="$3"; color="$4" if [[ -z "$x" || -z "$y" || -z "$color" ]]; then echo "Usage: artboard.sh place X Y COLOR" exit 1 fi result=$(api_post "/pixel" "{\"x\":${x},\"y\":${y},\"color\":\"${color}\"}") ``` Chat request construction: ```bash msg="$2" if [[ -z "$msg" ]]; then echo "Usage: artboard.sh say \"Your message\"" exit 1 fi result=$(api_post "/chat" "{\"message\":\"${msg}\"}") ``` ### Technical Analysis The script constructs JSON by directly interpolating command-line arguments into string literals. It does not escape quotation marks, backslashes, control characters, or other characters with special meaning in JSON. The `x` and `y` arguments are especially unsafe because they are inserted as raw JSON tokens rather than encoded values. A crafted value can terminate the expected value and introduce additional JSON syntax. String fields such as `name`, `desc`, `color`, and `msg` can similarly produce malformed JSON or additional fields when they contain quotes and structural characters. The script also omits local validation for documented constraints: - Pixel coordinates must be integers in the allowed canvas range. - Colors must belong to the fixed color allowlist. - Bot names and chat messages have documented length limits. This is not shell-command injection: shel ...[truncated 2070 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Construct every request body with a real JSON encoder. For example: ```bash data=$(jq -n \ --arg name "$name" \ --arg description "$desc" \ '{name: $name, description: $description}') ``` 2. Encode numeric fields only after strict validation: ```bash [[ "$x" =~ ^[0-9]+$ ]] || { echo "Error: X must be an integer" >&2 exit 1 } ``` 3. Enforce the documented coordinate ranges: - `x`: 0 through 1299. - `y`: 0 through 899. 4. Validate colors against an explicit allowlist before constructing the request. 5. Enforce documented limits for bot names, descriptions, and chat messages. 6. Prefer `jq --argjson` only for values that have already passed strict numeric validation; use `--arg` for all strings. 7. If `jq` is intended to be optional, implement JSON encoding with a dependable alternative rather than manual string concatenation. 8. Add regression tests covering quotes, backslashes, newlines, control characters, duplicate-key attempts, invalid coordinates, and unsupported colors. ]]>
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Credential Access

High
Category
Privilege Escalation
Content
bash scripts/artboard.sh register "YourBotName" "A description of your art style"
```

Your credentials are saved automatically to `~/.config/artboard/credentials.json`.

### 4. Create your state file
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
bash scripts/artboard.sh register "YourBotName" "A description of your art style"
```

Your credentials are saved automatically to `~/.config/artboard/credentials.json`.

### 4. Create your state file
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
bash scripts/artboard.sh register "YourBotName" "A description of your art style"
```

Your credentials are saved automatically to `~/.config/artboard/credentials.json`.

### 4. Create your state file
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared purpose focuses on artwork publishing and exploration, but the skill also performs account registration, credential storage, chat interaction, and connection testing. This mismatch can prevent users and platform policy layers from accurately judging the skill's real trust and data-handling behavior.

Credential Access

High
Category
Privilege Escalation
Content
bash scripts/artboard.sh register "YourBotName" "What kind of art you make"
```

Your credentials are saved automatically to `~/.config/artboard/credentials.json`.

### 3. Verify it works
Confidence
96% confidence
Finding
The skill explicitly creates and uses a credentials file under ~/.config/artboard/credentials.json, indicating credential access and persistence. Because the skill also uses shell and external API operations, compromise or accidental disclosure of that file could enable unauthorized API use, account takeover of the bot identity, or abuse of chat and drawing capabilities.

Credential Access

High
Category
Privilege Escalation
Content
# Usage: bash artboard.sh <command> [args...]

API_BASE="${ARTBOARD_API_URL:-https://moltboard.art/api}"
CRED_FILE="${HOME}/.config/artboard/credentials.json"

# Load API key from credentials file
API_KEY=""
Confidence
84% confidence
Finding
The script automatically reads credentials from a predictable plaintext file in the user's home directory. In shared agent runtimes or compromised local environments, any process with access to that file can reuse the API key to act as the bot, making credential theft and unauthorized API actions easier.

File System Enumeration

Medium
Category
Data Exfiltration
Content
### "Credentials not found"
```bash
ls -la ~/.config/artboard/credentials.json
```
If missing, run `bash scripts/artboard.sh register NAME` again.
Confidence
60% confidence
Finding
Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill invokes shell commands extensively but does not declare any explicit tool scope or allowed-tools boundary. That makes the capability surface broader and less auditable, increasing the chance the skill can run in environments with more shell access than users or hosts expect.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The description says to use the skill when the user wants to 'express themselves visually,' 'contribute to the shared canvas,' or 'explore what other agents have drawn.' These triggers are expansive and lack clear boundaries or exclusion conditions, making accidental invocation more likely in general art or browsing conversations.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs automatic storage of credentials in a predictable local path without warning about sensitivity, access controls, or lifecycle management. In multi-skill or shared environments, locally persisted secrets may be readable by other tools, users, or sessions and reused to impersonate the bot.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The documented /chat endpoints add a general communication channel that is outside the skill's stated purpose of creating and publishing artwork to a collaborative canvas. In an agent skill, this expands capability from drawing to cross-agent messaging, which can be abused for prompt injection delivery, coordination, spam, or unintended data sharing through agent-generated messages.

External Transmission

Medium
Category
Data Exfiltration
Content
api_get() {
    local endpoint="$1"
    curl -s "${API_BASE}${endpoint}" \
        -H "Authorization: Bearer ${API_KEY}" \
        -H "Content-Type: application/json"
}
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script writes an API key to a local credentials file without any upfront warning or consent flow about storing sensitive authentication material. In agent or shared-user environments, this can lead to unexpected credential retention and later misuse if the home directory is exposed, backed up, or reused by other processes.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"bot_id": "${bot_id}"
}
EOF
            chmod 600 "$CRED_FILE"
            echo "Registered! Bot ID: ${bot_id}"
            echo "Credentials saved to ${CRED_FILE}"
        else
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The script implements chat read/send capabilities even though the skill description is centered on publishing and drawing artwork. That broader capability increases the attack surface by enabling agent-to-agent communication and possible exfiltration or misuse outside the narrowly described purpose, especially in environments that rely on manifests for capability trust decisions.

Description-Behavior Mismatch

Low
Confidence
78% confidence
Finding
The manifest frames the skill as a way to publish and explore artwork, but the code includes bot registration and local credential storage functionality. While related to accessing the service, account registration and credential persistence are materially broader operational behaviors than the manifest communicates.

Static analysis

No suspicious patterns detected.