Back to skill

Security audit

Canva Connect

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Canva CLI integration, but it grants and stores powerful Canva permissions while under-disclosing some destructive actions and token-handling risks.

Review this skill before installing. Use it only with a Canva integration you are comfortable granting write access to, avoid using it for sensitive Canva accounts, and treat ~/.clawdbot/canva-tokens.json as a plaintext secret. Be especially careful with delete and upload commands because they can remove Canva resources or send local files to Canva without an additional confirmation step.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/canva.sh:159
Finding

OAuth callback does not validate the state parameter

Content
View full analysis
/dev/null; then xdg-open "$auth_url" 2>/dev/null & elif command -v open &> /dev/null; then open "$auth_url" 2>/dev/null & fi # Start simple HTTP server to catch callback echo "Waiting for OAuth callback on port $OAUTH_PORT..." # Save code_verifier to temp file for the callback handler local verifier_file=$(mktemp) local code_file=$(mktemp) echo "$code_verifier" > "$verifier_file" # Use Python for the callback server (simpler, more reliable) python3 << PYEOF import http.server import socketserver import urllib.parse code_file = "$code_file" port = $OAUTH_PORT class Handler(http.server.BaseHTTPRequestHandler): def do_GET(self): parsed = urllib.parse.urlparse(self.path) if parsed.path == '/oauth/redirect': p ...[truncated 2458 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/canva.sh:188
Finding

OAuth callback server listens on all network interfaces

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/canva.sh:86
Finding

OAuth access and refresh tokens are stored in plaintext

Content
View full analysis
"$TOKENS_FILE" chmod 600 "$TOKENS_FILE" } ``` The documentation incorrectly describes this file as encrypted: ```markdown | `~/.clawdbot/canva-tokens.json` | OAuth tokens (encrypted) | ``` ### Technical Analysis The complete OAuth token response is serialized directly into `canva-tokens.json`. This response can contain both an access token and a long-lived refresh token. The code applies mode `0600` only after shell redirection has created and populated the file. Mode `0600` is an important access-control measure, but it is not encryption. Moreover, unless the process has a restrictive `umask`, the file can initially be created with broader permissions before `chmod` executes. The write is also non-atomic, which can leave a truncated token file after interruption. The documentation's encryption claim is inconsistent with the implementation and may cause users to underestimate the consequences of filesystem compromise. ### Attack Path 1. The user completes Canva OAuth authentication. 2. `save_tokens` writes the complete token response as plaintext JSON under the configured state directory. 3. A malicious local process running as the same user, a privileged local attacker, or an attacker with access during an overly permissive creation window reads the token file. 4. The attacker extracts the access token or refresh token. 5. The attacker uses the access token against Canva APIs or exchanges the refresh token using the relevant client credentials ...[truncated 769 chars]
Remediation
View remediation
"$tmp" mv -f "$tmp" "$TOKENS_FILE" ``` 5. Ensure `$CONFIG_DIR` is owned by the current user and has mode `0700`. 6. Avoid retaining unnecessary OAuth response fields. 7. Provide clear token-revocation instructions and revoke the token remotely during logout when supported, rather than only deleting the local file. 8. Update `SKILL.md` to remove the false encryption claim unless encryption is actually implemented. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (31)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documentation says the skill cannot add or edit design content, yet it requests design:content read/write scope and documents destructive operations like deleting designs and assets. This mismatch can mislead users into granting broader permissions than necessary, enabling unintended modification or deletion of Canva resources if the skill or its scripts are abused.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
96% confidence
Finding

The documented DELETE /v1/designs/{designId} operation is a high-risk primitive that can be abused if an agent is induced to act on attacker-supplied identifiers or ambiguous instructions. In this skill context, the danger is elevated because deletion is not part of the declared user-facing scope, so users may not anticipate that the agent can destroy content.

Content

Scanner excerpt · references/api.md (reported line 60)May include surrounding context.

Delete Design

text
DELETE /v1/designs/{designId}

Export

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill metadata says only images can be uploaded, but the API reference permits additional formats including PDF and video types. This contradiction can lead users or downstream agents to transfer broader classes of files than intended, creating privacy, compliance, and data exfiltration risk.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
96% confidence
Finding

The documented DELETE /v1/assets/{assetId} endpoint enables destructive action on user assets and is susceptible to parameter abuse if an attacker can influence which asset ID is supplied. Because the skill description does not declare deletion as a supported action, this hidden capability increases the chance of unauthorized or unexpected data loss.

Content

Scanner excerpt · references/api.md (reported line 126)May include surrounding context.

Delete Asset

text
DELETE /v1/assets/{assetId}

Brand Templates

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/canva.sh (reported line 37)May include surrounding context.

sh
fi
}

# Load access token
load_token() {
    if [[ ! -f "$TOKENS_FILE" ]]; then
        echo -e "${RED}Error: Not authenticated. Run: canva.sh auth${NC}" >&2

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/canva.sh (reported line 54)May include surrounding context.

sh
fi
}

# Load access token
load_token() {
    if [[ ! -f "$TOKENS_FILE" ]]; then
        echo -e "${RED}Error: Not authenticated. Run: canva.sh auth${NC}" >&2

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The OAuth scope request includes broad design:content:write and design:content:read permissions even though the manifest says the skill cannot add or edit design content. Over-scoping violates least privilege and, if the token is misused or the code is later extended, grants access beyond the stated purpose.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/canva.sh (reported line 300)May include surrounding context.

sh
;;
        delete)
            local id="$1"
            api_request DELETE "/v1/designs/$id"
            echo -e "${GREEN}Design moved to trash${NC}"
            ;;
        *)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/canva.sh (reported line 390)May include surrounding context.

sh
;;
        delete)
            local id="$1"
            api_request DELETE "/v1/assets/$id"
            echo -e "${GREEN}Asset deleted${NC}"
            ;;
        *)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documents shell execution, network access to the Canva API, and local file writes/token storage, but it does not declare any explicit tool scope or allowed-tools boundary. That weakens least-privilege controls and increases the chance the runtime grants broader capabilities than users expect, especially for a skill that handles OAuth credentials and persistent files.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Contradictory statements about design creation/editing scope can cause operators to misunderstand what the skill is authorized to do and approve it under false assumptions. In a skill that uses OAuth and write-capable API scopes, ambiguity around editing permissions increases the risk of accidental over-trust and misuse.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 66)May include surrounding context.

3. Design Organization 📁

text
Create project folders → move related designs → keep Canva tidy

4. Brand Template Autofill 📋

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest says the skill can export finished designs only as PNG/PDF/JPG and can upload images only, but the command documentation also exposes designs delete, assets delete, export formats gif, pptx, and mp4, and a generic assets upload <file> command without an image-only restriction. These are material behavior claims beyond the declared scope in the manifest.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documented designs delete and assets delete commands are destructive, yet the skill provides no warning, confirmation step, or safety guidance. In agent-driven or automated contexts, this raises the chance of irreversible deletion from mistaken prompts, command misuse, or prompt injection into higher-level workflows.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The reference documents capabilities that exceed the skill's declared scope, including destructive deletion operations and comment creation. This creates a dangerous mismatch between user/operator expectations and actual reachable functionality, increasing the risk of unauthorized or socially engineered actions through the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

A destructive delete endpoint is presented without any warning, confirmation requirement, or cautionary guidance. In an agent context, undocumented destructive operations are more dangerous because an agent may invoke them based on ambiguous user requests or prompt manipulation.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
BASE_DIR="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="${CLAWDBOT_STATE_DIR:-$HOME/.clawdbot}"
TOKENS_FILE="$CONFIG_DIR/canva-tokens.json"
API_BASE="https://api.canva.com/rest"
OAUTH_PORT=3001

# Colors

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 3)May include surrounding context.

md
BASE_DIR="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="${CLAWDBOT_STATE_DIR:-$HOME/.clawdbot}"
TOKENS_FILE="$CONFIG_DIR/canva-tokens.json"
API_BASE="https://api.canva.com/rest"
OAUTH_PORT=3001

# Colors

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/canva.sh (reported line 11)May include surrounding context.

sh
BASE_DIR="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="${CLAWDBOT_STATE_DIR:-$HOME/.clawdbot}"
TOKENS_FILE="$CONFIG_DIR/canva-tokens.json"
API_BASE="https://api.canva.com/rest"
OAUTH_PORT=3001

# Colors

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/canva.sh (reported line 64)May include surrounding context.

sh
BASE_DIR="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="${CLAWDBOT_STATE_DIR:-$HOME/.clawdbot}"
TOKENS_FILE="$CONFIG_DIR/canva-tokens.json"
API_BASE="https://api.canva.com/rest"
OAUTH_PORT=3001

# Colors

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/canva.sh (reported line 238)May include surrounding context.

sh
BASE_DIR="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="${CLAWDBOT_STATE_DIR:-$HOME/.clawdbot}"
TOKENS_FILE="$CONFIG_DIR/canva-tokens.json"
API_BASE="https://api.canva.com/rest"
OAUTH_PORT=3001

# Colors

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/canva.sh (reported line 64)May include surrounding context.

sh
exit 1
    fi
    
    RESPONSE=$(curl -s -X POST "https://api.canva.com/rest/v1/oauth/token" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "grant_type=refresh_token" \
        -d "refresh_token=$REFRESH_TOKEN" \

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/canva.sh (reported line 87)May include surrounding context.

sh
local expires_at=$(($(date +%s) + expires_in - 60))
    
    echo "$response" | jq --arg exp "$expires_at" '. + {expires_at: ($exp | tonumber)}' > "$TOKENS_FILE"
    chmod 600 "$TOKENS_FILE"
}

# Make API request

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The upload path sends the contents of a local file to a remote API using curl --data-binary, and the help text does not explicitly warn that local files are uploaded off-system. While upload is implied by the command name, there is no disclosure about remote transmission of file data or metadata.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/canva.sh (reported line 127)May include surrounding context.

sh
load_token
    
    curl -s -X POST "${API_BASE}${endpoint}" \
        -H "Authorization: Bearer $ACCESS_TOKEN" \
        -H "Asset-Upload-Metadata: $metadata" \
        -H "Content-Type: application/octet-stream" \

Static analysis

No suspicious patterns detected.