T09 · Insecure Skill Coding Practices
- Location
internal/api/client.go:170- Finding
Credentials May Be Submitted to an Unvalidated Form Action
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Canvas CLI matches its stated purpose, but it handles login secrets in risky ways that could expose a Canvas or school account.
Install only if you trust this code with your Canvas or school credentials, run it on a private machine, avoid debug-login unless you can protect and delete its temporary files, use only HTTPS Canvas URLs, and consider changing credentials or clearing sessions if the config file or debug output is exposed. The skill is not judged malicious, but its current credential, session, debug, and download handling deserve review before use.
internal/api/client.go:170Credentials May Be Submitted to an Unvalidated Form Action
internal/config/config.go:12Plaintext Passwords and Session Cookies Are Persisted on Disk
internal/config/config.go:71Authentication Over Plain HTTP Is Permitted
internal/api/client.go:110Debug Login Leaks Authentication Artifacts Through Logs and Predictable Temporary Files
internal/config/config.go:83Password Entry Is Visible in the Terminal
cmd/files.go:112File Downloads Lack Transport, Status, and Resource Validation
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
go build -o canvas-cli .
sudo ln -s $(pwd)/canvas-cli /usr/local/bin/canvas-cli
## Quick Start
The README explicitly documents storing the user's Canvas password in a local JSON config file alongside session cookies. Even with 0600 permissions, plaintext credential-at-rest storage materially increases risk from local compromise, backups, endpoint malware, shell access by the same user, or accidental disclosure, and the README does not clearly warn users about that tradeoff or promote safer alternatives.
The skill explicitly states that session cookies are saved after first login and reused until expiration, but it does not warn users about the security implications of persistent authenticated session storage. If the local machine, home directory, backups, or other processes are compromised, an attacker may be able to reuse the cached session to access Canvas without re-entering TOTP, weakening the protection users expect from MFA.
The courses <id> users command explicitly requests include[]=email and then displays every user's email address in the course roster. In a course-viewing CLI, exposing personally identifiable information for all course members may exceed least-privilege expectations and can enable unwanted contact, phishing, or privacy violations, especially if students can invoke this command against courses they can access.
The postReply function sends the provided message to the remote discussion endpoint, which modifies course discussion data. Although it prints a success message afterward, there is no confirmation prompt, pre-action disclosure, or warning before performing the POST request.
This code performs a POST request that transmits the user's submission body or URL to a remote service. Although submission is the command's purpose, the file itself does not provide a clear user-facing disclosure at the point of transmission beyond a success message after the fact.
In debug mode, the code writes raw authentication pages to fixed paths under /tmp with mode 0644. Those pages can contain SAML assertions, hidden form fields, error details, and other login artifacts; on multi-user systems, other local users may be able to read them, and fixed filenames also increase the chance of accidental overwrite or unintended exposure.
The client persists live session cookies into configuration storage for automatic session restoration. If the config file is readable by other users, backed up insecurely, or exposed by malware, those cookies may allow session hijacking without needing the user's password or MFA step.
This code file performs a safety-relevant file write of sensitive credentials and persisted session cookies, but the only user-facing disclosure is that the data will be stored locally at a path. It does not warn that the stored data includes the user's password and cookies or explain the security implications of persisting them on disk.
This code prints the full API response for courses and grades directly to stdout when jsonOutput is enabled. Because the data contains student academic information, this is a user-data exposure path, and this file provides no warning, confirmation, or disclosure around that behavior.
When jsonOutput is enabled for a course, the code prints the complete assignments response, including submission details, directly to stdout. This exposes potentially sensitive educational records without any in-code disclosure or warning to the user.
This code performs an HTTP GET to retrieve the user's to-do items, which transmits and processes user-associated account data. In this file there is no confirmation prompt, print/log disclosure, or comment/docstring warning that the command contacts a remote service and accesses personal coursework information.
The command issues a network request to fetch /users/self/upcoming_events, which accesses user calendar and assignment information. No prompt, user-facing notice, or explanatory comment in this file warns that personal schedule data will be requested from the server.
This function calls a remote endpoint for /users/self/missing_submissions?include[]=course, which accesses potentially sensitive academic progress data. The file contains no visible warning, confirmation, or explanatory comment indicating that the command will query the user's account data from the network.
This code makes a network request to fetch the current user's profile and then prints personally identifiable information such as email and login ID. While the command name suggests identity lookup, there is no inline warning, comment, or user-facing disclosure about accessing and displaying account data.
The generated device fingerprint forces locale-related fields such as "en-US" and related accept-language values rather than reflecting user choice or environment. This is a natural-language locale policy concern because the skill imposes a specific language/locale profile without offering any opt-in or justification in the file.