Back to skill

Security audit

AudTools Shopify Batch Collector

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it can automatically submit many CSV links through a logged-in AudTools browser with loose page matching and dependency sources that deserve review.

Review the CSV before running because its URLs will be submitted to AudTools in bulk. Prefer a version with a dry-run and explicit confirmation, exact form selectors, origin checks before each submission, and dependencies regenerated from a trusted registry. Use an account where unintended AudTools submissions would be recoverable.

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)

T08 · Insecure Dependencies

Warning
Location
package-lock.json:21
Finding
Dependencies Are Locked to a Non-Official Package Registry## Vulnerability Details **File Location**: `package-lock.json:21-65` **Additional Trigger Locations**: `SKILL.md:68-76`, `setup.json:15-18` **Vulnerability Type**: Supply-chain exposure through a third-party package registry **Risk Level**: Medium ### Vulnerable Code ```json "node_modules/csv-parser": { "version": "3.2.0", "resolved": "https://registry.npmmirror.com/csv-parser/-/csv-parser-3.2.0.tgz", "integrity": "sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA==", "license": "MIT", "bin": { "csv-parser": "bin/csv-parser" }, "engines": { "node": ">= 10" } }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ] } ``` ```json "node_modules/playwright": { "version": "1.58.2", "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.58.2.tgz", "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==" }, "node_modules/playwright-core": { "version": "1.58.2", "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.58.2.tgz", "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==" } ``` The project documentation directs users to run `npm install`, causing npm to retrieve the locked artifacts from `registry.npmmirror.com` rather than the official npm registry. ### Technical Analysis A lockfile normally improves reproducibility, but it also determines the source from which package archives are retrieved. This lockfile places the availability and delivery of every runtime d ...[truncated 1963 chars]
Remediation
## Remediation Suggestions 1. Configure npm to use the official registry: ```bash npm config set registry https://registry.npmjs.org/ ``` 2. Delete and regenerate `package-lock.json` from the official registry after independently verifying dependency versions. 3. Use `npm ci` in controlled environments so the reviewed lockfile is installed without dependency-resolution drift. 4. Pin exact dependency versions in `package.json` rather than broad caret ranges where operationally practical. 5. Review all packages declaring installation scripts and disable scripts during initial verification: ```bash npm ci --ignore-scripts ``` 6. Run required browser or native-component installation steps separately after reviewing their provenance. 7. Add automated dependency scanning and lockfile source validation to CI. 8. Protect the regenerated lockfile with code review and repository integrity controls.

T09 · Insecure Skill Coding Practices

Warning
Location
batch-collect.js:182
Finding
Generic DOM Fallbacks Can Submit Data to Unintended Authenticated Controls## Vulnerability Details **File Location**: `batch-collect.js:182-250` **Vulnerability Type**: Unsafe browser automation selectors and missing target validation **Risk Level**: Medium ### Vulnerable Code ```js async function findInputSelector(page) { // 尝试多种选择器找链接输入框 const selectors = [ 'input[name="collection_url"]', 'input[name="url"]', 'input[placeholder*="url"]', 'input[placeholder*="link"]', 'input[placeholder*="collection"]', 'textarea[name*="collection"]', 'textarea', '.form-control', 'input[type="text"]' ]; for (const selector of selectors) { const element = await page.$(selector); if (element) { return selector; } } // 如果都没找到,返回第一个 text input return 'input[type="text"]'; } ``` ```js async function findSubmitButton(page) { // 尝试多种选择器找提交按钮 const selectors = [ 'button[type="submit"]', 'input[type="submit"]', 'button:has-text("提交")', 'button:has-text("Submit")', 'button:has-text("采集")', 'button:has-text("Start")', 'button:has-text("开始")', '.btn-primary', '.btn-success', 'button' ]; for (const selector of selectors) { const element = await page.$(selector); if (element) { return element; } } return null; } ``` The resulting controls are used without validating their containing form or semantic purpose: ```js await page.fill(inputSelector, ''); await page.fill(inputSelector, link); const submitButton = await findSubmitButton(page); if (submitButton) { await submitButton.click(); } ``` ### Technical Analysis The script initially attempts purpose-specific selectors but falls back to broad selectors such as `textarea`, `.form-control`, `input[type="text"]`, `.btn-primary`, and ultimately any `button`. `page.$` returns the first matching element, which is not necessarily the ...[truncated 1689 chars]
Remediation
## Remediation Suggestions 1. Remove generic fallbacks such as `textarea`, `.form-control`, `input[type="text"]`, `.btn-primary`, and `button`. 2. Use stable selectors unique to the collection form, preferably dedicated element IDs or application-provided test attributes. 3. Scope all control lookups to one validated form: ```js const form = page.locator('form[data-purpose="collection-import"]'); await form.locator('input[name="collection_url"]').fill(link); await form.locator('button[type="submit"]').click(); ``` 4. Verify `new URL(page.url()).origin === 'https://www.audtools.com'` before filling or clicking. 5. Assert that exactly one intended form, input, quantity field, and submission button are visible and enabled. 6. Abort safely instead of continuing when the page structure differs from the expected structure. 7. Confirm a specific success response or UI state after each submission before processing the next CSV row. 8. Add rate limits, duplicate prevention, and an optional confirmation step before executing a large batch.

T09 · Insecure Skill Coding Practices

Warning
Location
batch-collect-fixed.js:245
Finding
Duplicate Collector Uses Generic DOM Fallbacks for Authenticated Submissions## Vulnerability Details **File Location**: `batch-collect-fixed.js:245-313` **Vulnerability Type**: Unsafe browser automation selectors and missing target validation **Risk Level**: Medium ### Vulnerable Code ```js async function findInputSelector(page) { // 尝试多种选择器找链接输入框 const selectors = [ 'input[name="collection_url"]', 'input[name="url"]', 'input[placeholder*="url"]', 'input[placeholder*="link"]', 'input[placeholder*="collection"]', 'textarea[name*="collection"]', 'textarea', '.form-control', 'input[type="text"]' ]; for (const selector of selectors) { const element = await page.$(selector); if (element) { return selector; } } // 如果都没找到,返回第一个 text input return 'input[type="text"]'; } ``` ```js async function findSubmitButton(page) { // 尝试多种选择器找提交按钮 const selectors = [ 'button[type="submit"]', 'input[type="submit"]', 'button:has-text("提交")', 'button:has-text("Submit")', 'button:has-text("采集")', 'button:has-text("Start")', 'button:has-text("开始")', '.btn-primary', '.btn-success', 'button' ]; for (const selector of selectors) { const element = await page.$(selector); if (element) { return element; } } return null; } ``` These selections are consumed by the batch loop without checking the selected elements' purpose: ```js await page.fill(inputSelector, ''); await page.fill(inputSelector, link); const submitButton = await findSubmitButton(page); if (submitButton) { await submitButton.click(); } ``` ### Technical Analysis This alternate executable reproduces the same unsafe selector strategy as the primary collector. It searches for progressively less specific elements and eventually accepts the first text input and first button on the page. Presence alone is treated as proof ...[truncated 1322 chars]
Remediation
## Remediation Suggestions 1. Apply the same hardened selector implementation to both executables or consolidate them into one maintained implementation. 2. Eliminate all selectors that can match arbitrary text fields, textareas, styled controls, or buttons. 3. Resolve controls only inside a uniquely identified collection-import form. 4. Verify the HTTPS origin and expected route before every state-changing interaction. 5. Require exactly one visible match for each expected control and terminate on ambiguity. 6. Validate the button label, form action, and association with the URL and quantity fields. 7. Wait for and verify a collection-specific success response after each click. 8. Add automated tests covering login pages, error pages, modals, and changed DOM layouts to ensure the script fails closed.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (10)

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill clearly automates submission of CSV-derived URLs to an external third-party site, but the description does not warn users that local data will be transmitted off-system in bulk. This creates a meaningful risk of unintended data disclosure, especially because the process is fully automated and designed for high-volume submission with minimal user review.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script extracts URLs from a user-provided CSV, previews them in logs, and then submits them to audtools.com without an explicit warning or consent flow that this data will be transmitted to a third-party service. In this context, the links may reveal merchant targets, internal research, or sensitive sourcing data, so silent transmission increases data-leakage and privacy risk.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script performs automated form submission against an external service for every CSV entry without any explicit confirmation, dry-run step, or per-item approval before triggering the site's submit action. In this skill's context, that creates a real risk of unintended bulk actions, account misuse, or accidental submission of large volumes of third-party URLs under the user's authenticated session.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script performs live batch submissions by clicking whichever element first matches a broad set of submit/button selectors, without a final user confirmation, dry-run mode, domain/action verification, or per-item validation. In this context, that can trigger unintended writes on the authenticated AudTools account, especially if the page structure changes or a wrong button is matched, causing bulk collection jobs or other actions to be submitted at scale.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The natural-language instructions and usage guidance are presented exclusively in Chinese, which can amount to a language policy violation when no user opt-in or locale limitation is documented. There is no indication that the skill is intended only for a Chinese-language environment or that users may choose another language.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The file-level documentation and all user-facing console messages are written in Chinese, including required login and execution instructions. This imposes a specific language on users without any opt-in or alternative locale handling, which matches the language/locale policy violation criteria.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The comments and user-facing console instructions are entirely in Chinese, including usage guidance and runtime prompts. Under the stated policy, forcing a single language without opt-in or justification is a locale-policy issue.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The package description is entirely in Chinese, which constitutes a language-specific constraint in the skill's natural-language metadata. There is no indication that the skill is region-specific or that users may choose another language, so this appears to violate the language/locale policy criteria.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"audtools-batch-collect": "./batch-collect.js"
  },
  "dependencies": {
    "playwright": "^1.40.0",
    "csv-parser": "^3.0.0"
  },
  "keywords": [
Confidence
91% confidence
Finding
Using a caret range for Playwright allows newer minor or patch releases to be installed implicitly, which can introduce supply-chain risk, unexpected behavior changes, or newly introduced malicious code if the dependency ecosystem is compromised. In a browser automation tool that submits bulk data to an external website, dependency drift is more sensitive because the package has high execution capability and network interaction.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "playwright": "^1.40.0",
    "csv-parser": "^3.0.0"
  },
  "keywords": [
    "audtools",
Confidence
90% confidence
Finding
Using a caret range for csv-parser permits automatic upgrades that may pull in changed or compromised code without explicit review. Although csv-parser is less privileged than a browser automation framework, it still executes in the local Node.js environment and contributes to software supply-chain exposure.

Static analysis

No suspicious patterns detected.