Back to skill

Security audit

Adaptive Learning

Security checks for vulnerabilities and agentic risk

Overview

This study-app skill is not malicious, but untrusted course files and course IDs can be treated as executable browser content or unsafe output paths.

Review before installing or using with untrusted materials. Only import question JSON and use course IDs from trusted sources, avoid opening generated apps with sensitive same-origin browser data, and prefer fixing sanitization, course-id validation, local KaTeX vendoring or SRI, and clearer storage/network consent before broader use.

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
assets/framework/engine.js:97
Finding

Stored DOM-Based Cross-Site Scripting Through Imported Course Content

Content
View full analysis
c.id === courseId)) { COURSE_REGISTRY.push({ id: courseId, name: courseName, desc: '', school: '', term: '' }); } ``` ```javascript let html = `
${q.topic} ${diffLabels[q.difficulty] || '?'} ${fsrsInfo}
${this.formatText(q.question)}
`; if (this.flipped) { html += `
答案
${this.formatText(q.answer)}
`; } else { html += '
点击查看答案 →
'; } document.getElementById('card-inner').innerHTML = html; ``` ```javascript formatText(text) { return (text || '').replace(/\\n/g, '
').replace(/\n/g, '
'); } ``` ```javascript list.innerHTML = this.allTopics.map(t => { const tm = this.topicMastery[t]; let scoreClass = 'score-none', scoreText = '未开始'; if (tm && tm.attempts > 0) { const m = tm.mastery; if (m >= 0.7) { scoreCla ...[truncated 2877 chars]
Remediation
View remediation
` elements rather than using `innerHTML`. 3. If controlled rich-text support is required, sanitize content with a maintained allowlist-based sanitizer. Disallow script elements, event-handler attributes, dangerous URLs, SVG, MathML, iframes, and active embedded content. 4. Validate imported JSON against a strict schema, including expected types and maximum lengths for every field. 5. Apply a restrictive Content Security Policy that disallows inline event handlers and limits script execution to trusted bundled resources. CSP should be defense in depth rather than the primary correction. 6. Add regression tests using payloads such as: ```html link ``` Verify that these strings are displayed literally and never interpreted as markup. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate-course.sh:8
Finding

Unsafe Course Identifier Interpolation in Generated JavaScript and File Paths

Content
View full analysis
}" QUESTIONS="${2:?Provide path to questions.json}" OUTPUT="${3:?Provide output directory}" ``` ```bash # Generate preload script with inline questions QDATA=$(cat "$QUESTIONS") cat > "$OUTPUT/preload-${COURSE_ID}.js" <|\n|" "$OUTPUT/index.html" # Remove any other preload scripts from index.html sed -i "/preload-.*\.js/!b; /preload-${COURSE_ID}\.js/b; d" "$OUTPUT/index.html" ``` ### Technical Analysis `COURSE_ID` is accepted without validation and is embedded into three security-sensitive contexts: 1. A generated JavaScript string literal. 2. A filesystem path used as a redirection target. 3. Dynamically constructed `sed` expressions. Shell quoting around the output filename prevents ordinary whitespace splitting, but it does not make slash components safe. A course identifier containing `../` can alter the resolved output path when the referenced directories exist. Quotes and JavaScript syntax in the identifier can also terminate the generated JavaScript string and introduce attacker-controlled statements. For example, an identifier containing a single quote can break out of: ```javascript var KEY = 'alearn_${COURSE_ID}_questions'; ``` The question file is likewise inserted directly as JavaScript so ...[truncated 1824 chars]
Remediation
View remediation
&2 exit 1 fi ``` 2. Reject dots, slashes, backslashes, quotes, control characters, shell metacharacters, and empty identifiers. 3. Construct the destination path and verify its canonical parent remains beneath the canonical output directory before writing. 4. Validate the question file with a real JSON parser before generation. 5. Generate the preload file through a JSON-aware implementation rather than raw heredoc interpolation. Serialize `COURSE_ID` as a JSON string and parse the question file as data. 6. Avoid injecting untrusted values into `sed` programs. Prefer a fixed placeholder and a tool that performs literal replacement, or escape all regular-expression and replacement metacharacters correctly. 7. Create output files using safe temporary files followed by an atomic move after all validation succeeds. 8. Add negative tests covering identifiers with `'`, `"`, `/`, `../`, `\`, `&`, `|`, newlines, and regular-expression metacharacters. ]]>

T08 · Insecure Dependencies

Warning
Location
assets/framework/index.html:7
Finding

Remote JavaScript Dependencies Loaded Without Subresource Integrity

Content
View full analysis
``` ### Technical Analysis The application loads executable KaTeX resources from a third-party CDN without Subresource Integrity attributes. Although the dependency version is pinned, the browser has no cryptographic declaration of the exact expected content. If the CDN, package publication process, delivery infrastructure, or DNS/TLS trust chain is compromised, modified JavaScript can be delivered and executed with the same browser privileges as the local application code. This behavior also conflicts with the documented claim that the application is self-contained and works offline. On a fresh load without cached CDN resources, KaTeX functionality requires external network access. ### Attack Path 1. An attacker compromises or gains influence over the CDN response, upstream package artifact, or relevant delivery infrastructure. 2. A user opens the generated learning application while network access is available. 3. The browser requests the KaTeX scripts from the CDN. 4. Because no `integrity` attribute is present, the browser accepts any successfully delivered response. 5. The modified script executes in the application context. 6. The script can access browser storage available to the page, alter the interface, and transmit accessible data over the network. ### Impact Assessment A successful supply-chain compromise provides arbitrary JavaScript execution in the application's browser context. This can expose or corrupt course questions, learning progress, scheduler state, and ...[truncated 195 chars]
Remediation
View remediation
``` 3. Obtain integrity values from a trusted build or independently calculate and verify them. Do not use placeholder hashes. 4. Add a restrictive Content Security Policy limiting scripts and styles to the selected trusted sources. Prefer local-only resources where practical. 5. Document the external dependency and network requirement if remote loading remains enabled. 6. Establish a dependency update process that verifies checksums, reviews release changes, and periodically updates KaTeX to a maintained version. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented purpose claims the skill can create adaptive learning apps from URLs, PDFs, or folders, but the described implementation mainly operates on prebuilt question banks and manual generation steps. This mismatch is dangerous because users and orchestrators may grant broader trust, permissions, or autonomy than the skill actually needs, masking data-handling behaviors and causing unsafe invocation in contexts expecting a pure frontend/offline tool.

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

md
| `ts-fsrs.umd.js` | FSRS algorithm library (UMD build of ts-fsrs) |

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill instructs network access ('Fetch the course page') and local file writes ('Download ... PDFs') but does not declare any explicit tool scope or permissions. This creates an authorization and transparency gap: an agent may perform network and filesystem actions users or platforms did not clearly approve, increasing the risk of unintended data access or exfiltration.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill presents itself as a pure frontend offline app, yet its workflow includes fetching remote course pages and downloading PDFs to the local filesystem. This inconsistency is security-relevant because operators may treat the skill as low-risk/offline while it actually performs network and local storage actions, changing the threat model and exposing users to unanticipated data collection or malicious remote content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The workflow directs the agent to download course PDFs and persist generated content locally without discussing privacy, retention, access controls, or handling of copyrighted/sensitive educational materials. In practice this can lead to storing personal, proprietary, or institution-restricted content on disk in predictable locations, where it may be exposed to other local processes or retained longer than intended.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This JavaScript file contains multiple hard-coded user-facing strings in Chinese, such as course-status labels and empty-state text, with no indication that the skill is intentionally region-specific or that users can select another language. That creates a natural-language policy issue because the skill effectively forces a specific locale without opt-in.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
55% 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 · assets/framework/engine.js (reported line 154)May include surrounding context.

js
// Init FSRS scheduler
    this.initFSRS();

    // Load saved state
    this.loadState();

    // Switch screens

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document declares zh-CN as the page language, and the visible UI strings throughout the file are presented in Simplified Chinese without any indication that users can select another language. The policy allows locale constraints only when users can opt in or when the restriction is clearly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The markdown embeds Chinese labels for the difficulty levels (基础, 中等, 高级) as part of the skill instructions, which imposes a specific language choice in the user-facing content. The policy requires offering language or locale choice unless the constraint is documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This bundled FSRS library installs scheduler, diff, format, and dueFormat onto the global Date prototype. While date handling is relevant to spaced-repetition scheduling, mutating a built-in global prototype is a broad capability that affects unrelated code and is not justified by the manifest’s limited purpose of creating adaptive learning apps.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.