Back to skill

Security audit

AP Classroom Agent

Security checks for vulnerabilities and agentic risk

Overview

This skill openly automates AP Classroom work, but it can answer and submit live assignments from a logged-in browser without adequate final confirmation, target validation, or disclosure.

Review before installing or using. Only run this in an isolated browser profile if you fully understand that it can act as the logged-in College Board user, capture assignment screenshots, select answers, advance questions, and submit real coursework. Do not use the submission scripts unless you add explicit review and confirmation checks and verify the target page, course, and assignment.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
submit-quiz.js:30
Finding
Irreversible Quiz Submission Without Explicit User Confirmation<![CDATA[ ## Vulnerability Details **File Location**: `submit-quiz.js:30-44`; equivalent behavior also occurs in `complete-quiz.js:150-159` **Vulnerability Type**: Missing authorization checkpoint for a consequential action **Risk Level**: High ### Vulnerable Code ```javascript // 查找 Submit 按钮 const submitBtn = await page.$('button:has-text("Submit")'); if (submitBtn) { console.log('\n🖱️ 点击 Submit...'); await submitBtn.click({ force: true }); await page.waitForTimeout(3000); // 查找确认按钮 const confirmBtn = await page.$('button:has-text("Yes"), button:has-text("Confirm")'); if (confirmBtn) { console.log('🖱️ 确认提交...'); await confirmBtn.click({ force: true }); await page.waitForTimeout(5000); console.log('✅ 测验已提交!'); ``` The fully automated workflow contains the same issue: ```javascript const submitBtn = await page.$('button:has-text("Submit")'); if (submitBtn) { await submitBtn.click({ force: true }); await page.waitForTimeout(3000); // 确认提交 const confirmBtn = await page.$('button:has-text("Yes"), button:has-text("Confirm")'); if (confirmBtn) { console.log('🖱️ 确认提交'); await confirmBtn.click({ force: true }); await page.waitForTimeout(5000); } ``` ### Technical Analysis Both submission workflows click the initial `Submit` control and then automatically click a `Yes` or `Confirm` control. The scripts print warnings, but no interactive authorization is requested after the user can review the exact course, assignment, and selected answers. A console message is not a security boundary. Once either script starts, it can complete the irreversible submission without another affirmative user action. This also conflicts with documentation that represents submission as requiring confirmation. The use of `{ force: true }` further bypasses Playwright actionability safeguards that would ordinarily reject interactions with obscured, disabled, or otherwise unsuitable elements. ### Attack Path 1. The user has an a ...[truncated 1008 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require an explicit interactive confirmation immediately before the final confirmation click, such as typing the exact assignment name. 2. Display the trusted origin, course, assignment, number of answered questions, and unanswered-question count before requesting approval. 3. Abort by default if interactive input is unavailable or if any expected value cannot be verified. 4. Validate that the current URL uses the exact `https://apclassroom.collegeboard.org/` origin and an expected quiz route. 5. Use assignment-specific selectors rather than generic text selectors. 6. Remove `{ force: true }` from submission and confirmation actions. 7. Separate preparation from submission: the default command should stop at a review screen, while final submission should require a distinct, explicitly authorized operation. 8. Add a dry-run mode and make it the default. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
complete-quiz.js:16
Finding
Default Automated Workflow Submits Option A for Every Question<![CDATA[ ## Vulnerability Details **File Location**: `complete-quiz.js:16-57`, with automatic submission at `complete-quiz.js:121-159` **Vulnerability Type**: Unsafe placeholder logic in a production-capable submission workflow **Risk Level**: High ### Vulnerable Code ```javascript async function answerQuestion(page, questionNumber) { console.log(`\n📝 正在回答第 ${questionNumber} 题...`); // 获取题目文本 const questionText = await page.evaluate(() => { const questionEl = document.querySelector('[class*="question"], [class*="stem"]'); return questionEl ? questionEl.textContent.trim() : ''; }); console.log(`题目: ${questionText.substring(0, 200)}...`); // 获取选项 const options = await page.evaluate(() => { const labels = Array.from(document.querySelectorAll('label')); return labels .filter(l => l.textContent.trim().length > 0) .map(l => l.textContent.trim()) .filter(t => t.length < 200); }); console.log('选项:'); options.forEach((opt, i) => { console.log(` ${String.fromCharCode(65 + i)}. ${opt}`); }); // ⚠️ 在这里添加你的答案逻辑 // 示例:选择第一个选项 const answerIndex = 0; // 使用 JavaScript 点击(避免触发划掉选项) await page.evaluate((index) => { const labels = document.querySelectorAll('label'); if (labels[index]) { labels[index].click(); } }, answerIndex); await page.waitForTimeout(2000); console.log(`✅ 已选择选项 ${String.fromCharCode(65 + answerIndex)}`); } ``` The result is then submitted by the same workflow: ```javascript while (hasNext) { // 答题 await answerQuestion(page, questionNumber); // 检查是否有 Next 按钮 const nextBtn = await page.$('button:has-text("Next")'); if (nextBtn) { console.log('🖱️ 点击 Next...'); await nextBtn.click({ force: true }); await page.waitForTimeout(5000); questionNumber++; } else { // 检查是否有 Submit 按钮 const submitBtn = await page.$('button:has-text("Submit")'); if (submitBtn) { console.log('\n✅ 所有题目已完成,准备提交'); hasNext = false; ...[truncated 2323 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the active placeholder answer and fail closed unless a validated answer source is explicitly configured. 2. Never permit final submission when the configured answer provider is a stub, example, default, or constant value. 3. Scope answer selectors to the active question container and identify options through stable, application-specific attributes. 4. Verify that the selected option corresponds to the requested answer and that exactly one intended control changed state. 5. Add a mandatory review stage listing every question and selected answer. 6. Require explicit user approval after review and immediately before final submission. 7. Add dry-run and answer-preview modes; make dry-run the default. 8. Remove the hard-coded course and assignment values and require the user to verify both before execution. 9. Add automated tests that prove the workflow aborts when answer logic is missing or unchanged from the example. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
submit-quiz.js:16
Finding
Authenticated Browser Actions Use the First Open Tab and Generic Forced Selectors<![CDATA[ ## Vulnerability Details **File Location**: `submit-quiz.js:16-43`; the same first-tab pattern is also present in `answer-question.js:27-40` and `complete-quiz.js:63-67,150-159` **Vulnerability Type**: Insufficient target validation for authenticated browser automation **Risk Level**: High ### Vulnerable Code ```javascript browser = await chromium.connectOverCDP('http://localhost:9223'); const context = browser.contexts()[0]; const page = context.pages()[0]; console.log(`📍 当前页面: ${page.url()}\n`); console.log('⚠️ 准备提交测验...'); console.log('💡 请确认所有题目都已回答\n'); // 截图当前状态 await page.screenshot({ path: 'before-submit.png', fullPage: true }); console.log('📸 已保存提交前截图: before-submit.png'); // 查找 Submit 按钮 const submitBtn = await page.$('button:has-text("Submit")'); if (submitBtn) { console.log('\n🖱️ 点击 Submit...'); await submitBtn.click({ force: true }); await page.waitForTimeout(3000); // 查找确认按钮 const confirmBtn = await page.$('button:has-text("Yes"), button:has-text("Confirm")'); if (confirmBtn) { console.log('🖱️ 确认提交...'); await confirmBtn.click({ force: true }); ``` The answer-selection script uses the same unvalidated page selection: ```javascript browser = await chromium.connectOverCDP('http://localhost:9223'); const context = browser.contexts()[0]; const page = context.pages()[0]; console.log(`📍 当前页面: ${page.url()}\n`); // 计算选项索引 const answerIndex = answer.charCodeAt(0) - 65; // A=0, B=1, C=2, D=3, E=4 console.log(`🎯 选择答案: ${answer}\n`); // 使用 JavaScript 点击(避免触发划掉选项) const selected = await page.evaluate((index) => { const labels = document.querySelectorAll('label'); const validLabels = Array.from(labels).filter(l => { const text = l.textContent.trim(); return text.length > 0 && text.length < 200 && !text.includes('Cookie') && !text.includes('checkbox'); }); if (validLabels[index]) { validLabels[index].click(); return true; } return false; }, answerIn ...[truncated 2000 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enumerate pages and select only a page whose parsed URL has the exact trusted origin `https://apclassroom.collegeboard.org`. 2. Reject lookalike hosts, HTTP origins, unexpected ports, and routes outside the expected assignment or quiz path. 3. Verify the course ID and assignment identity before every state-changing action. 4. Revalidate the origin after navigation and immediately before answer selection or submission. 5. Restrict selectors to a known quiz container and stable application-specific attributes. 6. Do not use generic selectors such as `button:has-text("Submit")` across the entire document. 7. Remove `{ force: true }` for consequential actions and rely on normal visibility, enabled-state, and actionability checks. 8. Abort if zero or multiple candidate controls match. 9. Require the user to approve the resolved page URL, course, and assignment before interaction. 10. Consider using a dedicated, isolated browser profile containing only the target AP Classroom tab. ]]>

T08 · Insecure Dependencies

Warning
Location
answer-question.js:1
Finding
Playwright Is Loaded From a Hard-Coded External Workspace Path<![CDATA[ ## Vulnerability Details **File Location**: `answer-question.js:1`; the same import appears in all executable JavaScript files **Vulnerability Type**: Unsafe external dependency resolution **Risk Level**: Medium ### Vulnerable Code ```javascript const { chromium } = require('C:/Users/ASUS/.openclaw/workspace/node_modules/playwright'); ``` The same hard-coded dependency import is present in: - `check-browser-status.js:1` - `check-homework.js:1` - `complete-quiz.js:2` - `get-questions.js:1` - `list-courses.js:1` - `next-question.js:1` - `open-assignment.js:1` - `select-course.js:1` - `submit-quiz.js:1` This bypasses the package-local dependency declared in `package.json`: ```json "dependencies": { "playwright": "^1.40.0" } ``` ### Technical Analysis Node.js executes a required module during import. By resolving Playwright from an absolute path outside the audited project, the scripts trust code that is not part of the supplied artifact and is not necessarily the dependency installed for this package. The external workspace copy may differ from the declared package version. If it is stale, replaced, or writable by another local component, arbitrary initialization code in that module will execute before the Skill connects to the browser. This is an unsafe dependency source and also makes the project non-portable. The declared dependency does not protect execution because normal package resolution is bypassed. ### Attack Path 1. An attacker or compromised local process gains write access to `C:/Users/ASUS/.openclaw/workspace/node_modules/playwright` or its resolved entry point. 2. The external module is modified to execute attacker-controlled JavaScript when imported. 3. The user invokes any executable script in this Skill. 4. Node.js loads the hard-coded external module before running the rest of the script. 5. The replacement code executes with the invoking user's operating-system privileges. 6. It can potentially access process resources an ...[truncated 650 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every absolute import with package-local resolution: ```javascript const { chromium } = require('playwright'); ``` 2. Install dependencies within the project rather than relying on another workspace. 3. Commit a lockfile and use reproducible installation such as `npm ci`. 4. Pin an audited Playwright version rather than using an unrestricted compatible range where reproducibility is required. 5. Verify lockfile integrity and dependency provenance in CI. 6. Prevent untrusted users or processes from modifying the project and its installed dependencies. 7. Fail with a clear error when the package-local dependency is unavailable; do not fall back to global or external workspace paths. 8. Audit the external workspace installation before any continued use of the current version. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (60)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The tool is described as completing homework across subjects, but the actual behavior appears limited to submitting an already-open page and taking screenshots before and after. In a live classroom account, undisclosed submission and screenshot actions can affect grades and capture sensitive educational information, making the mismatch security-significant.

Ae1

High
Category
analysis-evasion
Content
| `select-course.js` | 切换 AP 课程 | `node select-course.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| `check-homework.js` | 检查待完成作业 | `node check-homework.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| `get-questions.js` | 获取当前题目和选项 | `node get-questions.js` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| `complete-quiz.js` | 完整自动化流程 | 需要编辑答题逻辑 |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

High
Confidence
98% confidence
Finding
The script automatically clicks Submit and then confirms submission without any user confirmation, dry-run mode, or last-minute review. In this skill's context—an AP Classroom automation that uses the currently logged-in browser to complete and submit graded work—this can irreversibly submit incorrect or unauthorized answers, causing academic harm and misuse of the user's authenticated session.

Natural-Language Policy Violations

High
Confidence
95% confidence
Finding
The output explicitly offers to help choose answers for an assignment, which supports academic cheating rather than legitimate accessibility or study assistance. In the context of a skill marketed to complete AP Classroom work automatically using the user’s logged-in browser, this materially increases policy, integrity, and account-enforcement risk.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The comment claims the code will only disconnect and keep the browser open, but it actually calls browser.close(). When connected over CDP to the user’s active browser session, closing the browser can terminate unrelated tabs, disrupt workflows, and cause loss of unsaved data or session state.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The documentation instructs users to launch Chrome with a remote debugging port while logged into College Board, but does not explain that this exposes powerful browser control over an authenticated session. If the port is reachable by other local users or software, an attacker or unintended tool could inspect pages, extract data, or perform actions as the user.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The examples explicitly walk the user through opening AP Classroom quizzes, selecting answers, and submitting them, but they do not prominently warn that this automation can act on graded coursework and cause irreversible submissions. In this skill's context, the functionality is specifically aimed at completing school assessments on a logged-in student session, which makes accidental or unauthorized grade-impacting actions materially dangerous.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This markdown file uses Chinese throughout for headings, instructions, and usage steps, but it does not indicate that Chinese is optional or that the skill is intended only for a Chinese-speaking audience. That creates a natural-language policy concern because the skill effectively forces a specific language without user opt-in.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README explicitly documents a workflow to open assignments, retrieve questions, select answers, and submit quizzes, but does not warn about academic-integrity violations, account sanctions, or platform terms-of-service risks. In this skill’s context, the advertised purpose is to complete AP Classroom assignments automatically using the user’s logged-in browser session, which increases the likelihood of misuse and makes the omission materially dangerous.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The release notes explicitly document capabilities to answer questions and submit AP Classroom coursework, but they do not include any warning, consent boundary, or restriction around academic-integrity and account-impacting actions. In the context of a browser-automation skill operating on a logged-in student account, this increases the risk of unauthorized submission, policy violations, and accidental changes with real academic consequences.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill promotes automatic completion and submission of academic assignments without warning about academic-integrity violations, account sanctions, or the risks of acting on a logged-in student session. In this context, omission of such warnings increases the likelihood of misuse and unintended harm to the user's educational standing.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The instructions describe submission automation but do not clearly state that the actions affect live assignments and may be irreversible. For educational platforms, hidden or understated real-world effects are dangerous because they can lead to accidental submission, grade impact, and disciplinary consequences.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The comment claims the script will only disconnect and not affect the browser, but the code later calls browser.close(). In a CDP-attached automation context, misleading lifecycle claims can cause unintended disruption of the user's active browser session and undermine trust in what the script actually does.

Static analysis

No suspicious patterns detected.