Back to skill

Security audit

Canva Skill

Security checks for vulnerabilities and agentic risk

Overview

This Canva API skill is mostly purpose-aligned, but it needs review because it stores reusable OAuth tokens locally and can upload or change Canva account content.

Review before installing. Use a dedicated Canva integration with the minimum scopes needed, protect or avoid the ~/.canva/tokens.json token file, revoke tokens if exposed, and only upload or autofill content you are comfortable sending to Canva.

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
SKILL.md:24
Finding

OAuth Access Token Stored in a Plaintext File Without Required Permission Controls

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 24–37
Vulnerability Type: Plaintext storage of sensitive authentication material
Risk Level: Medium

Vulnerable Code

markdown
Authenticate on first use and store tokens in `~/.canva/tokens.json`.

## API Base URL

```bash
https://api.canva.com/rest/v1

Authentication

Get access token from local token file:

bash
ACCESS_TOKEN=$(cat ~/.canva/tokens.json | jq -r '.access_token')
text

### Technical Analysis

The skill directs users to persist Canva OAuth tokens in `~/.canva/tokens.json` as plaintext and later read the access token directly from that file. It does not require restrictive permissions for either the containing directory or the token file, nor does it recommend an operating-system credential store.

OAuth access and refresh tokens are bearer credentials: possession may be sufficient to authenticate API requests without knowing the user's password. If local permissions, backups, development-environment sharing, or host isolation are misconfigured, another account or process could obtain the token. The skill also does not specify token-safe logging, lifecycle, rotation, or revocation practices.

This issue does not by itself grant an external attacker access to the file. Exploitation requires an existing ability to read the user's filesystem, such as access through another local account, an untrusted process running under the same account, an exposed backup, or overly permissive file permissions.

### Attack Path

1. The user completes OAuth authentication, and the integration stores access or refresh tokens in `~/.canva/tokens.json`.
2. The file or its containing directory is created with permissions that allow an unauthorized local principal or process to read it, or the file is exposed through an insecure backup or shared workspace.
3. The attacker reads the JSON file and extracts the access token or refresh token
...[truncated 932 chars]
Remediation
View remediation

Remediation Suggestions

  1. Store OAuth credentials in an operating-system credential manager or another encrypted secret store rather than a plaintext JSON file.

  2. If file-based storage is unavoidable, create the directory and file with owner-only permissions before writing credentials:

    bash
    install -d -m 0700 "$HOME/.canva"
    install -m 0600 /dev/null "$HOME/.canva/tokens.json"
    
  3. Validate file ownership and permissions before reading the token, and refuse to proceed when the file is accessible by group or other users.

  4. Never print, log, commit, or include access or refresh tokens in command output, diagnostics, backups, or shared artifacts.

  5. Use the minimum Canva scopes necessary for each workflow and avoid requesting write scopes for read-only operations.

  6. Document token expiration, secure refresh, rotation, revocation, and incident-response procedures.

  7. Revoke affected credentials and repeat OAuth authorization if unauthorized file access is suspected.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (14)

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The skill instructs reading a bearer access token directly from a persistent local file, which exposes a reusable credential to local compromise, shell history/process inspection patterns, and accidental leakage through logging or debugging. Because this token authorizes Canva account actions, theft could allow unauthorized access to designs and assets.

Content

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

Authentication

Get access token from local token file:

bash
ACCESS_TOKEN=$(cat ~/.canva/tokens.json | jq -r '.access_token')

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 3)May include surrounding context.

md
---
name: canva-skill
description: Create, export, upload assets to, and manage Canva designs via the Canva Connect API. Use when the user wants to create social posts, posters, PPT/slide visuals, export Canva designs as PNG/JPG/PDF, list recent Canva designs, upload local images to Canva, or autofill brand templates with content.
---

# Canva Skill

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description says it uploads local images and autofills/export designs via Canva Connect API, but it does not clearly warn that user-provided files and design content are transmitted to a third-party external service. This can cause unintentional disclosure of sensitive business, personal, or copyrighted material.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill explicitly instructs users to store OAuth tokens in ~/.canva/tokens.json but does not warn that this creates a persistent local secret containing reusable bearer credentials. Users may unknowingly leave tokens on shared machines, back them up insecurely, or expose them to other local processes, increasing risk of account compromise.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 29)May include surrounding context.

API Base URL

bash
https://api.canva.com/rest/v1

Authentication

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 47)May include surrounding context.

API Base URL

bash
https://api.canva.com/rest/v1

Authentication

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 54)May include surrounding context.

API Base URL

bash
https://api.canva.com/rest/v1

Authentication

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 90)May include surrounding context.

API Base URL

bash
https://api.canva.com/rest/v1

Authentication

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 107)May include surrounding context.

API Base URL

bash
https://api.canva.com/rest/v1

Authentication

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The presence of the Canva autofill endpoint confirms outbound transmission of user content to a third party. Because this operation can include arbitrary text/body content, it creates a meaningful confidentiality risk if users are not clearly informed or if sensitive content is sent by default.

Content

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

Create Design from Template

bash
curl -X POST "https://api.canva.com/rest/v1/autofills" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The presence of the Canva autofill endpoint confirms outbound transmission of user content to a third party. Because this operation can include arbitrary text/body content, it creates a meaningful confidentiality risk if users are not clearly informed or if sensitive content is sent by default.

Content

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

Create Design from Template

bash
curl -X POST "https://api.canva.com/rest/v1/autofills" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

Starting an export job sends design identifiers and export parameters to Canva and may initiate creation of downloadable artifacts on a third-party platform. In this context the behavior is expected, but it still represents external processing of potentially sensitive design content and should be disclosed.

Content

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

Start export job:

bash
curl -X POST "https://api.canva.com/rest/v1/exports" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This endpoint specifically uploads raw local file content to Canva, making it the strongest external transmission concern in the skill. The context makes it more dangerous because the examples encourage direct binary upload from disk, which can lead to accidental disclosure of sensitive local files.

Content

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

Upload Asset

bash
curl -X POST "https://api.canva.com/rest/v1/asset-uploads" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  -H 'Asset-Upload-Metadata: {"name": "my-image.png"}' \

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This endpoint specifically uploads raw local file content to Canva, making it the strongest external transmission concern in the skill. The context makes it more dangerous because the examples encourage direct binary upload from disk, which can lead to accidental disclosure of sensitive local files.

Content

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

Upload Asset

bash
curl -X POST "https://api.canva.com/rest/v1/asset-uploads" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  -H 'Asset-Upload-Metadata: {"name": "my-image.png"}' \