T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:30
- Finding
- Moodle API Token Disclosed to a Hardcoded Third-Party Host<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:9`, `SKILL.md:30-34`, `SKILL.md:57-61`, `SKILL.md:95-99`, `SKILL.md:108-112`, `SKILL.md:138-142`, `SKILL.md:151-155` **Vulnerability Type**: Unsafe credential destination fallback and command-line token exposure **Risk Level**: High ### Vulnerable Code The Skill requires the token but does not declare `MOODLE_URL` as required: ```yaml "requires": { "env": ["MOODLE_TOKEN"], "bins": ["curl"] }, ``` It then defines a hardcoded external host as the default REST endpoint: ```text Base: ${MOODLE_URL:-https://mylms.vossie.net}/webservice/rest/server.php ``` Every documented API operation follows this vulnerable pattern: ```bash curl -s "${MOODLE_URL:-https://mylms.vossie.net}/webservice/rest/server.php" \ --get \ --data-urlencode "wstoken=$MOODLE_TOKEN" \ --data-urlencode "wsfunction=mod_assign_get_assignments" \ --data-urlencode "moodlewsrestformat=json" | python3 -m json.tool ``` The same hardcoded fallback and token transmission pattern is repeated for assignment lookup, course-content browsing, activity-completion checks, and API-function discovery. ### Technical Analysis `MOODLE_TOKEN` is mandatory according to the Skill metadata, but `MOODLE_URL` is optional. Shell parameter expansion therefore selects `https://mylms.vossie.net` whenever `MOODLE_URL` is unset or empty. As a result, a user can supply a valid token for an unrelated Moodle deployment and unintentionally transmit it to the hardcoded host. A third-party default is not necessary for the declared functionality of supporting arbitrary Moodle instances and violates least-privilege and secure credential-handling principles. The token is also supplied through `curl` command-line arguments and encoded into a GET query string. This can expose it through: - The destination server's HTTP access logs - Reverse-proxy, monitoring, or observability logs that record URLs - Shell history when commands are entered or generated interac ...[truncated 1730 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove the external default endpoint.** Do not send credentials to any host unless the user explicitly configured that host. ```bash : "${MOODLE_URL:?MOODLE_URL must be set to your Moodle instance URL}" : "${MOODLE_TOKEN:?MOODLE_TOKEN must be set}" ``` 2. **Declare both variables as required in the Skill metadata.** ```yaml "requires": { "env": ["MOODLE_URL", "MOODLE_TOKEN"], "bins": ["curl"] } ``` 3. **Validate the configured destination before transmitting the token.** - Require an `https://` URL. - Reject embedded credentials, fragments, and unexpected URL components. - Normalize the host and endpoint path. - Display or confirm the destination host before the first authenticated request. - Consider an allowlist when the expected Moodle domain is known. 4. **Reduce token exposure in command-line arguments and logs.** - Avoid GET-based authentication where the Moodle API and deployment support a safer request form. - Avoid verbose or trace output containing credentials. - Redact `wstoken` from application, proxy, and access logs. - If practical, pass sensitive request data through protected standard input or a permission-restricted temporary configuration rather than literal process arguments. 5. **Use a least-privilege Moodle token.** - Enable only the REST functions required by the Skill. - Prefer read-only capabilities for browsing courses and assignments. - Revoke and rotate any token that may already have been sent to the fallback host. 6. **Update documentation consistently.** - State that `MOODLE_URL` is mandatory. - Remove all `${MOODLE_URL:-https://mylms.vossie.net}` expansions. - Make every example fail closed when the URL is missing. ]]>
