Back to skill

Security audit

Canvas LMS Student Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent Canvas helper, but its file download code can expose the Canvas token or write files outside the chosen folder, so it needs review before installation.

Review this skill before installing. It requires a Canvas API token that can access private course information, stores that token in plaintext if you use the config-file method, and can write downloaded or exported files locally. Avoid the file-download feature until the token-forwarding and path-traversal issues are fixed; prefer environment variables or a secure secret store, limit use to trusted Canvas URLs, and be cautious with essay-generation workflows under your school’s academic-integrity rules.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/download_files.py:16
Finding

Canvas Bearer Token Sent to an Unvalidated Download URL

Content
View full analysis
bool: """Download a file from URL to local path.""" try: headers = {"Authorization": f"Bearer {token}"} response = requests.get(url, headers=headers, stream=True, timeout=60) response.raise_for_status() ``` ```python # Get download URL try: file_obj = canvas.get_file(file.id) download_url = file_obj.url if download_file(download_url, filepath, token): ``` ### Technical Analysis The download URL comes from remotely supplied Canvas API data. The code does not validate its scheme, hostname, port, or relationship to the configured Canvas instance before attaching the password-equivalent Canvas API token to the request. Consequently, the `Authorization: Bearer ` header may be sent to a non-Canvas host. The code also does not explicitly require HTTPS. Although `requests` provides TLS verification for HTTPS by default, it does not protect credentials when the original URL itself points to an unauthorized host or uses plaintext HTTP. This behavior conflicts with the documented claim that API tokens are never exposed. Cross-origin download URLs should generally be treated as signed URLs and requested without the Canvas bearer token unless the destination has been explicitly verified as a trusted Canvas API host. ### Attack Path 1. The victim configures the Skill to use a compromised or malicious Canvas-compatible endpoint. 2. The victim invokes the course-file download feature. 3. The remote service returns a file object whose `url` points to an attacker-controlled server. 4. `download_files.py` retrieves that URL without validating its origin. 5. The script attaches the victim's Canvas API token to ...[truncated 755 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/download_files.py:34
Finding

Path Traversal Through Canvas-Controlled Folder Names

Content
View full analysis
str: """Remove invalid characters from filename.""" invalid_chars = '<>:"/\\|?*' for char in invalid_chars: filename = filename.replace(char, '_') return filename ``` ```python def get_folder_path(folder_id: int, folders_map: dict, cache: dict = None) -> str: """ Get the full path for a folder, preserving Canvas structure. """ if cache is None: cache = {} if folder_id in cache: return cache[folder_id] if folder_id not in folders_map: return "" folder = folders_map[folder_id] folder_name = sanitize_filename(folder.name) # Handle root folder (no parent or parent is root) if not hasattr(folder, 'parent_folder_id') or folder.parent_folder_id is None: cache[folder_id] = folder_name return folder_name parent_path = get_folder_path(folder.parent_folder_id, folders_map, cache) if parent_path: result = f"{parent_path}/{folder_name}" else: result = folder_name cache[folder_id] = result return result ``` ```python # Build filepath if relative_path: filepath = output_dir / relative_path / filename else: filepath = output_dir / filename # Handle duplicates (unless --no-id-prefix) if not args.no_id_prefix: filepath = generate_unique_filename(filepath, file.id) # Skip if already exists and same size if filepath.exists() and filepath.stat().st_size == file.size: folder_display = f"[{relative_path}] " if relative_path else "" print(f" ⏭ Skipped: {folder_display}{filename}") skipped_count += 1 continue folder_display = f"[{relative_path}] " if relative_path else "" print(f" ⬇ Downloading ...[truncated 2629 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Permit Uncontrolled Supply-Chain Drift

Content
View full analysis
=3.0.0 requests>=2.25.0 ``` ```bash # Install pip dependencies echo "" echo "Installing Python dependencies..." if [ -f "$SCRIPT_DIR/requirements.txt" ]; then pip3 install -q -r "$SCRIPT_DIR/requirements.txt" && echo "✓ Dependencies installed" else echo "⚠ No requirements.txt found, skipping pip install" fi ``` ### Technical Analysis Both dependencies use unrestricted lower bounds. There are no exact version pins, upper bounds, cryptographic hashes, or lock file. Each setup execution may therefore install a different future release from the configured Python package index. Python packages can execute code during installation and later when imported. If a dependency's release channel or package-index account is compromised, the setup script may install and execute attacker-controlled code with the user's privileges. This finding does not establish that `canvasapi` or `requests` is currently malicious. It identifies the absence of reproducibility and integrity controls around security-sensitive dependencies. ### Attack Path 1. A dependency publisher account, release process, or configured package index is compromised, or an unsafe future version is released. 2. The attacker publishes a version satisfying the unrestricted `>=` requirement. 3. A user runs `setup.sh`. 4. pip resolves the malicious or unsafe version because no reviewed exact version or hash is required. 5. Package installation code executes, or the package executes when imported by the Skill. 6. The dependency operates with the privileges and environment of the user running the Skill, potentially including access to Canvas credentials. ### Impact Assessment A compromised dependency can execute arbitrary code with the privileges of the user r ...[truncated 546 chars]
Remediation
View remediation
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The top-level description frames the skill as a read-only homework/materials assistant, but the body expands behavior into broader cross-course search, announcements, and potentially discussion-related content retrieval. This mismatch can mislead users and routing systems into granting access to more educational records and communications than the narrow description suggests.

Content

No source excerpt is available for this finding.

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

md
**Setup Guide (if not configured):**
1. Guide user to: Canvas → Account → Settings → Approved Integrations
2. Click "+ New Access Token"
3. Configure using ONE of these methods:
   - **Environment variables:**
     ```bash

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

md
**Setup Guide (if not configured):**
1. Guide user to: Canvas → Account → Settings → Approved Integrations
2. Click "+ New Access Token"
3. Configure using ONE of these methods:
   - **Environment variables:**
     ```bash

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/canvas_client.py (reported line 66)May include surrounding context.

python
**Setup Guide (if not configured):**
1. Guide user to: Canvas → Account → Settings → Approved Integrations
2. Click "+ New Access Token"
3. Configure using ONE of these methods:
   - **Environment variables:**
     ```bash

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The workflow explicitly promotes AI-assisted essay generation after collecting assignment requirements, without guardrails for academic integrity, user consent, or policy checks. In an educational context, this can facilitate cheating or unauthorized ghostwriting using course-specific prompts and rubric details obtained from the LMS.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
OpenClaw discovers the skill from `SKILL.md`. The added `manifest.json` and

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The skill instructs users to persist a password-equivalent API token in a plaintext config file under the home directory. While convenient, plaintext storage materially increases exposure to local compromise, accidental inclusion in backups, or unintended access by other tools or processes on the system.

Content

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

echo '{"base_url": "https://...", "api_token": "..."}' > ~/.config/canvas-lms/config.json

text

Get API token: Canvas → Account → Settings → Approved Integrations → + New Access Token

### Available Tools

Context Leakage

High
Category
Data Exfiltration
Confidence
90% confidence
Finding

The context extraction helper is used to return surrounding text from assignment descriptions, announcements, and discussions, which can leak more educational content than the user strictly searched for. In a multi-course academic context, this increases inadvertent disclosure risk because snippets may contain grades, accommodations, meeting links, or other sensitive details adjacent to the match.

Content

Scanner excerpt · scripts/search_canvas.py (reported line 24)May include surrounding context.

python
def extract_context(text: str, query: str, context_chars: int = 100) -> str:
    """Extract context around the search match."""
    if not text:
        return ""

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README instructs users to place a Canvas API token in environment variables or a local config file, but it does not warn that this token is sensitive, should be protected with restrictive file permissions, and must never be committed or shared. Because this skill grants access to student course data, exposed tokens could allow unauthorized access to assignments, files, deadlines, and other academic information.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares broad capabilities to access environment variables, local files, network resources, and shell commands but does not constrain or disclose them with an explicit tool scope. That increases the chance an orchestrator invokes the skill with more privilege than users expect, especially since the skill handles password-equivalent Canvas tokens and writes downloaded data locally.

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

md
- "Show my grades" / "how am I doing in CS101"
- "Find the syllabus" / "search for project requirements"
- "Export deadlines to my calendar"
- "Help me write my essay" (will gather assignment requirements)

**Key indicators:** Canvas, course, assignment, homework, deadline, grade, syllabus, lecture notes, materials.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger phrases and key indicators are broad enough to match ordinary academic conversation, such as homework, grades, or essay help, even when the user did not ask to access Canvas. Over-broad routing can cause unnecessary access to institutional data, token use, network activity, or local downloads without a clear Canvas-specific user intent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The documented use of ~/.config/canvas-lms/config.json creates persistent local storage of sensitive authentication material across sessions. Persisting a Canvas API token in a standard config path increases the blast radius of local compromise and can expose access to grades, assignments, files, and other course data over time.

Content

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

export CANVAS_API_TOKEN="your-api-token"

Method 2: Config file

mkdir -p ~/.config/canvas-lms echo '{"base_url": "https://...", "api_token": "..."}' > ~/.config/canvas-lms/config.json

text

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes the skill as providing read-only access to Canvas courses, assignments, files, and deadlines. While the Canvas API usage is read-only, this script additionally persists retrieved course/assignment content to a user-specified local path, which is a broader behavior than simply interacting with Canvas in read-only mode.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill metadata promises read-only access to courses, assignments, files, and deadlines, but this code also searches discussion content. That expands data access beyond the declared scope and can expose student/instructor communications that may contain more sensitive educational or personal information than expected.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

These lines enable discussion-forum search from the CLI, making the overbroad access reachable in normal operation. Because discussions are not part of the stated student workflow or declared access scope, this creates a scope-creep data exposure risk rather than a purely theoretical issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code outputs assignment descriptions, announcement/discussion message excerpts, course names, and links directly to stdout, and can search across all active courses by default. There is no confirmation prompt or user-facing warning that results may reveal potentially sensitive course or student-related content on screen or in JSON output.

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 · setup.sh (reported line 53)May include surrounding context.

sh
echo '  export CANVAS_API_TOKEN="your-api-token"'
    echo ""
    echo "Method 2: Config File"
    echo "  mkdir -p ~/.config/canvas-lms"
    echo '  echo '\''{"base_url": "https://...", "api_token": "..."}'\'' > ~/.config/canvas-lms/config.json'
    echo ""
    echo "Get your API token from: Canvas → Account → Settings → Approved Integrations"

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 · wrapper.py (reported line 161)May include surrounding context.

python
try:
        # Run script
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest exposes a file-download capability that writes to the local filesystem but does not warn that invoking the tool will create files and directories on disk. In an agent setting, this can lead to surprising side effects, disk usage, or writes into unintended paths if the output parameter is passed through without clear user confirmation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The calendar export tool creates a local .ics file, but the manifest does not warn users that running it will write or potentially overwrite an output file. In an autonomous or semi-autonomous agent workflow, undisclosed file creation is a safety issue because it introduces persistent side effects and possible accidental overwrites.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation encourages exporting assignment data into .ics files and importing them into third-party calendar services, but it does not warn that assignment titles, descriptions, course names, URLs, and deadlines may contain sensitive academic information. In a student-focused Canvas skill, this can lead to unintended disclosure of course metadata or private coursework details when files are stored locally, synced, or uploaded to external calendar providers.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This markdown file documents commands that return user-specific academic information such as current grades and detailed course data. Under the markdown-file criteria for missing user warnings, it should disclose that the skill may access personal or potentially sensitive educational information.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.