T09 · Insecure Skill Coding Practices
- Location
SKILL.md:105- Finding
Shell Command Injection Through Unencoded Course Search Input
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly coherent for Coursera progress tracking, but it handles Coursera credentials and private grades/certificates through broad shell-based API instructions without enough scoping or safety guidance.
Review before installing. Use only for explicit Coursera requests, provide least-privilege and short-lived Coursera credentials where possible, avoid pasting secrets into chat, and prefer implementations that URL-encode search terms and keep tokens out of command-line arguments and logs.
SKILL.md:105Shell Command Injection Through Unencoded Course Search Input
SKILL.md:42Coursera Credentials Exposed Through Child-Process Arguments
The skill explicitly requires a client secret and optionally an access token, which means it is designed to operate on bearer credentials capable of accessing private account data. In a skill ecosystem, requesting and handling such credentials materially increases the blast radius of any misuse, logging error, or prompt-injection-assisted invocation.
- name: COURSERA_CLIENT_SECRET
description: "Coursera API client secret"
- name: COURSERA_ACCESS_TOKEN
description: "OAuth2 access token (generated from client credentials)"
optional: true
---
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
export COURSERA_CLIENT_ID="your_client_id"
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# Get your own user ID first
curl -s "https://api.coursera.com/api/users/v1/me" \
-H "$AUTH_HEADER"
# Then fetch enrollments
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# Public course info (no auth)
curl -s "https://api.coursera.com/api/courses.v1?q=search&query=python&includes=instructors&fields=name,partnerIds,instructorIds,primaryLanguages,workload" \
| python3 -m json.tool
The activation guidance says to use the skill whenever the user wants to check learning progress and includes phrases like "check my Coursera" and especially "online course progress," which is broader than Coursera-specific intent. This ambiguity could cause unintended invocation for generic learning-progress or online-course queries that are not clearly about this skill.
The skill accesses personal learning data and uses authentication credentials, but it does not prominently warn users that their account data, grades, certificates, and deadlines will be fetched from a third-party service. This increases the risk of users invoking the skill without informed consent and exposing sensitive educational metadata unintentionally.
This command transmits the Coursera client ID and client secret to an external endpoint to obtain an access token. Although this is the expected OAuth flow, it still involves handling and transmitting secrets, and the skill provides no safeguards around secret storage, redaction, or confirmation, making accidental exposure more dangerous in an agent setting.
export COURSERA_CLIENT_ID="your_client_id"
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
export COURSERA_CLIENT_SECRET="your_client_secret"
COURSERA_ACCESS_TOKEN=$(curl -s -X POST \
"https://api.coursera.com/oauth2/client_credentials/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=$COURSERA_CLIENT_ID&client_secret=$COURSERA_CLIENT_SECRET" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
This API call sends an authenticated request for the user's account identity data to Coursera. In context, that is core functionality, but it still transmits personal account information externally and lacks explicit consent, data minimization, or guardrails against over-collection in an agent workflow.
# Get your own user ID first
curl -s "https://api.coursera.com/api/users/v1/me" \
-H "$AUTH_HEADER"
# Then fetch enrollments
This request retrieves private enrollment, grade, completion, and certificate metadata from Coursera using an authenticated token. The data is sensitive educational information, and the skill does not define consent, minimization, or safe handling requirements, which makes accidental disclosure plausible.
-H "$AUTH_HEADER"
curl -s "https://api.coursera.com/api/enrollments.v1?userId=USER_ID&fields=courseId,enrolledAt,grade,completedAt,certificateCode"
-H "$AUTH_HEADER"
This call retrieves user-specific progress and grade information, which is sensitive personal educational data. The operation is expected for the skill's purpose, but without consent checks and privacy guidance it creates a real risk of exposing progress details to the agent or logs unintentionally.
curl -s "https://api.coursera.com/api/onDemandCourseCompletions.v1?userId=USER_ID&courseId=COURSE_ID&fields=progressPercent,completedAt,grade" \
-H "$AUTH_HEADER"
This request fetches deadline schedule data tied to a course, which may reveal aspects of a learner's participation and schedule. The sensitivity is lower than credentials or grades, but it still concerns personal account activity and should be protected accordingly.
curl -s "https://api.coursera.com/api/onDemandDeadlineSchedules.v1?courseId=COURSE_ID&fields=deadlineSchedule,moduleIds" \
-H "$AUTH_HEADER"
Certificate and grade information can reveal completion status and academic performance, and the verify URL may be shareable proof of achievement. Pulling this data through an agent without clear consent and output controls creates a privacy exposure risk.
curl -s "https://api.coursera.com/api/certificates.v1?userId=USER_ID&fields=courseId,issuedAt,verifyUrl,grade" \
-H "$AUTH_HEADER"
The Python helper reads an access token from the environment and sends it in an Authorization header to an external service. In an agent environment, this pattern is risky because tokens may be mishandled, captured in subprocess diagnostics, or reused without explicit user approval, leading to unauthorized access to private Coursera data.
token = os.environ["COURSERA_ACCESS_TOKEN"]
r = subprocess.run(
["curl", "-s",
f"https://api.coursera.com/api/enrollments.v1?userId={user_id}"
f"&fields=courseId,enrolledAt,grade,completedAt,certificateCode",
"-H", f"Authorization: Bearer {token}"],
capture_output=True, text=True)
No suspicious patterns detected.