Back to skill

Security audit

EdStem

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly performs the advertised EdStem export task, but it ships and encourages hardcoded bearer tokens for private course data, so it needs Review before installation.

Do not install this as-is in a shared or published environment. Any included EdStem token should be treated as exposed and revoked, and users should only run the skill after replacing hardcoded tokens with a secure runtime secret such as an environment variable. Also consider whether you are authorized to export course discussions, where the saved files will live, and whether LLM or cron workflows could expose student or staff content.

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/fetch-edstem.py:22
Finding

Published Hardcoded EdStem Bearer Credential

Content
View full analysis
"$OUTPUT_DIR/thread-$thread_num-raw.json" ``` ### Technical Analysis The project distributes a reusable bearer credential directly in two executable source files. Bearer tokens grant access based on possession; therefore, any person or automated system that can read the published package can reuse this credential without knowing the account password. The scripts legitimately need to send an authentication token to the official EdStem HTTPS API. However, shipping a token belonging to an existing account is not necessary for the declared functionality and violates least-secret and secure-configuration principles. Documentation in `PUBLISHING.md:136-139` explicitly acknowledges that the published Skill includes a bearer token by default, confirming that this is not merely an omitted local placeholder. Because the token is duplicated in both implementations, replacing it in only one script would leav ...[truncated 1503 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch-edstem.py:154
Finding

Requested Thread Limit Is Bypassed, Causing Excessive Collection and Storage

Content
View full analysis
Remediation
View remediation
maximum_limit: parser.error(f"--limit must not exceed {maximum_limit}") threads = fetch_threads(course_id, limit=args.limit) ``` 3. Persist only records within the requested scope: ```python requested_threads = threads[:args.limit] with open(edstem_dir / "threads.json", "w", encoding="utf-8") as f: json.dump(requested_threads, f, indent=2) ``` 4. If fetching additional records is required for pagination or synchronization, clearly disclose that behavior and avoid persisting surplus records. 5. Consider restrictive output permissions because the generated files contain private course information. 6. Add tests confirming that `--limit 1`, the default value, and larger valid values cause no more than the requested number of records to be fetched and stored. ]]>

T08 · Insecure Dependencies

Note
Location
README.md:146
Finding

Unpinned Third-Party Requests Dependency

Content
View full analysis
Remediation
View remediation
``` 2. For stronger reproducibility, generate a lock file containing hashes for `requests` and all transitive dependencies. 3. Install with integrity enforcement: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 4. Review and update pinned dependencies regularly using an automated vulnerability scanner. 5. Document the supported Python version and use an isolated virtual environment. 6. Avoid adding extra package indexes or untrusted dependency sources. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · PUBLISHING.md (reported line 9)May include surrounding context.

md
- [x] Remove institution-specific code and documentation
- [x] Add flexible command-line parameters
- [x] Update SKILL.md with general documentation
- [x] Create README.md for repository listing
- [x] Add VERSION file (currently: 1.1.0)
- [x] Create CHANGELOG.md with version history

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README instructs users to extract a live bearer token from browser traffic and hardcode it into the script, but gives no warning that this credential grants API access and may expose all accessible course data if leaked. Hardcoding secrets into source files commonly leads to accidental disclosure via version control, logs, screenshots, or shared workspaces, making this a significant credential-handling weakness.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill claims broad, institution-agnostic sync/organization capabilities, but the documentation indicates a simpler course-specific downloader using a hardcoded credential and local file output. This kind of description-behavior gap increases the chance of unsafe deployment and unreviewed access to private educational data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill claims broad, institution-agnostic sync/organization capabilities, but the documentation indicates a simpler course-specific downloader using a hardcoded credential and local file output. This kind of description-behavior gap increases the chance of unsafe deployment and unreviewed access to private educational data.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The authentication section explains how to harvest a bearer token from browser requests but omits a clear warning that the token is a highly sensitive credential. This omission materially raises the chance that users will mishandle the token, store it insecurely, or leak it through source control, screenshots, or shared scripts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

A live bearer token is hardcoded directly into the script, exposing reusable credentials to anyone who can read the file, repository history, logs, or packaged skill contents. In this context, the token can grant access to private course discussions and user data across EdStem, making credential theft and unauthorized data access highly likely and potentially widespread.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script contains a hard-coded EdStem bearer token directly in source, which is a real credential exposure vulnerability. Anyone with access to the file can reuse the token to make authenticated API requests against EdStem, potentially accessing private course discussions and associated metadata beyond the intended user context.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This script silently uses a hard-coded bearer token to perform authenticated network requests and download course thread data without any user consent or disclosure. In the context of an EdStem syncing skill, this is especially dangerous because the retrieved data may include non-public student/staff discussions, and the credential use is hidden inside an automation utility.

Content

No source excerpt is available for this finding.

Context Leakage

High
Category
Data Exfiltration
Confidence
86% confidence
Finding

The script retrieves course threads and writes raw JSON plus per-thread exports to local disk, which can leak private academic discussion content into the operator's environment. Although the line itself is part of normal fetching logic, in this skill context the data includes potentially sensitive student/staff posts, making local persistence and broad collection a genuine context-leakage risk.

Content

Scanner excerpt · scripts/fetch-edstem.sh (reported line 31)May include surrounding context.

sh
"https://us.edstem.org/api/courses/$COURSE_ID/threads?limit=20&sort=new" \
  > "$OUTPUT_DIR/threads.json"

# Extract thread IDs and fetch details
jq -r '.threads[] | "\(.id)|\(.number)|\(.title)"' "$OUTPUT_DIR/threads.json" | while IFS='|' read -r thread_id thread_num title; do
  echo "  Thread #$thread_num: $title"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The migration notes explicitly tell users that the ED_TOKEN remains embedded in a script file at a fixed line location, which normalizes storing a live authentication secret in source code. Even though this markdown file does not itself contain the token, it reinforces an insecure credential-management practice that increases the likelihood of token leakage through version control, local file sharing, backups, or accidental disclosure.

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

md
- [x] Remove institution-specific code and documentation
- [x] Add flexible command-line parameters
- [x] Update SKILL.md with general documentation
- [x] Create README.md for repository listing
- [x] Add VERSION file (currently: 1.1.0)
- [x] Create CHANGELOG.md with version history
- [x] Test scripts with --help flag

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manual installation section normalizes direct credential embedding by telling users to update ED_TOKEN in a Python file without steering them toward safer secret-handling practices. In the context of a publishable reusable skill, that increases the chance that users will commit or redistribute credentials unintentionally.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document explicitly instructs users to update an EdStem bearer token in the script, which encourages storing live credentials directly in source code and packaged skill contents. That creates a realistic risk of accidental disclosure through git history, tarballs, screenshots, backups, or shared skill directories, especially because this file is specifically about publishing and distribution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The security notes acknowledge a bearer token is included by default and tell users to replace it, which confirms the project ships with hardcoded credential material or a placeholder pattern that legitimizes embedding secrets in code. Even if the token is only a template or test token, distributing code that expects embedded bearer tokens is an unsafe practice for an API-access skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README promotes monitoring, reviewing, and archiving EdStem discussions, which can contain student identities, academic records, private questions, and instructor communications, but it provides no privacy, consent, retention, or access-control guidance. In the context of educational platforms, this omission increases the risk of improper collection, storage, and redistribution of sensitive FERPA-like data through routine use of the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly encourages feeding fetched course discussion data into LLM agents without warning that the data may include personally identifiable, educational, or confidential staff/student communications. Sending such content to external AI services can violate institutional policy, privacy obligations, or user expectations, especially if prompts or files are retained by third-party providers.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill advertises operational behavior that includes shell execution, network access, and local file writes, but it declares no explicit tool scope or permissions. This weakens containment and review because a caller cannot easily tell that the skill can perform authenticated data retrieval and persist course content to disk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation wording is broad enough to trigger on routine requests about course discussions, which can cause the skill to run in contexts where the user did not clearly consent to authenticated retrieval and local storage. In a skill that accesses private academic content, over-broad invocation language increases the risk of unnecessary data collection and disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation describes fetched outputs but does not warn that EdStem threads may contain sensitive student, staff, or course information and will be stored locally as JSON and Markdown. Users may therefore export educational records onto shared machines or insecure directories without understanding the privacy implications.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The documentation tells users to copy a bearer token from browser traffic and paste it directly into the script source. This encourages insecure secret handling, makes accidental disclosure via source control or logs much more likely, and grants anyone with the token access under the user's EdStem account.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script makes authenticated HTTP requests to the EdStem API using a bearer token to fetch user, course, and thread data. Although remote access is central to the script's purpose, the file does not disclose that it will use credentials to access potentially private course content, which is relevant safety information for users.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script exports private EdStem discussion data to local JSON and Markdown files, which creates a persistence and secondary-exposure risk beyond transient review. In the context of a course forum skill, threads may contain student questions, names, staff responses, and other educational records, so writing them to disk without clear disclosure or access controls can leak sensitive data to other local users, backups, or downstream tooling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script stores fetched course discussion content locally without warning the operator that potentially sensitive educational data will be persisted. In this skill's context, EdStem posts can include student names, course logistics, and private discussion material, so silent local storage increases the chance of unauthorized access through shared machines, logs, backups, or later ingestion by other tools.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · README.md (reported line 14)May include surrounding context.

md
- Analyze discussion patterns
- Integrate EdStem with LLM agents and automation workflows

**Institution-agnostic:** Works with any school using EdStem (not limited to any specific institution).

## Features

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code requests at least 50 threads from the remote API even when the user asks for fewer, which causes unnecessary overcollection of potentially sensitive course discussion data. Although only a subset is later processed in detail, the extra thread metadata is still retrieved and saved to disk, violating least-privilege and least-data principles.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.