Back to skill

Security audit

slop-check

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly purpose-aligned, but it needs Review because it can broadly activate, write and serve repo reports without a consent gate, and its generated HTML report has a script-injection risk from untrusted repo data.

Install only if you are comfortable with repo-wide local code analysis, generated files under .slop-check plus slop-report.html, and a temporary localhost report server. Avoid running it on untrusted repositories until the report data embedding is fixed, or run it in a disposable checkout and open the report cautiously. Stop the local server when finished and review generated artifacts before sharing them.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Note
Location
scripts/build-report.mjs:65
Finding
Stored Script Injection Through Unsafe Report Payload Embedding<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build-report.mjs:65-70` and `assets/report-template.html:254-258` **Vulnerability Type**: Stored script injection in a generated HTML report **Risk Level**: Moderate ### Vulnerable Code From `scripts/build-report.mjs:65-70`: ```js const ANCHOR = /(const DATA = )\/\*SLOP_DATA\*\/[\s\S]*?\/\*END_SLOP_DATA\*\//; if (!ANCHOR.test(template)) { console.error('build-report: could not find the `const DATA = /*SLOP_DATA*/ ... /*END_SLOP_DATA*/` block in the template'); process.exit(1); } const out = template.replace(ANCHOR, '$1/*SLOP_DATA*/' + JSON.stringify(payload, null, 2) + '/*END_SLOP_DATA*/'); ``` The payload is inserted into the executable script context established in `assets/report-template.html:254-258`: ```html <script> // Default is a PLACEHOLDER sentinel, never a plausible-looking example. If injection // fails for any reason, the page must shout "not built" instead of rendering a fake // report — that exact silent-default failure shipped a blank report once. const DATA = /*SLOP_DATA*/{ "__notBuilt__": true }/*END_SLOP_DATA*/; ``` ### Technical Analysis The report builder uses `JSON.stringify()` and inserts the resulting text directly into an inline `<script>` element. JSON serialization protects JavaScript string syntax, but it does not protect the surrounding HTML parser context. In particular, it does not neutralize the case-insensitive `</script>` sequence. The HTML parser recognizes `</script>` even when it appears inside a JavaScript string literal. Therefore, a payload field containing content such as: ```html </script><script>/* attacker-controlled JavaScript */</script> ``` can terminate the legitimate report script and create a new executable script element. This condition is reachable because the report schema includes repository-derived values such as project names, file paths, finding descriptions, and fix-it prompts. A malicious repository can influence these valu ...[truncated 2292 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Encode serialized JSON for HTML script context.** At minimum, replace HTML-significant characters after serialization: ```js const serializedPayload = JSON.stringify(payload, null, 2) .replace(/&/g, '\\u0026') .replace(/</g, '\\u003c') .replace(/>/g, '\\u003e') .replace(/\u2028/g, '\\u2028') .replace(/\u2029/g, '\\u2029'); const out = template.replace( ANCHOR, '$1/*SLOP_DATA*/' + serializedPayload + '/*END_SLOP_DATA*/' ); ``` Escaping `<` prevents an attacker from creating the `</script>` delimiter. 2. **Prefer a non-executable JSON container.** Place the serialized payload in an element such as: ```html <script id="slop-data" type="application/json">...</script> ``` Then parse it using: ```js const DATA = JSON.parse(document.getElementById('slop-data').textContent); ``` The payload must still have `<` escaped because the HTML parser recognizes `</script>` regardless of the script element's type. 3. **Add regression tests.** Build reports containing adversarial values such as: ```text </script><script>globalThis.reportInjectionExecuted = true</script> ``` Verify that: - The generated file contains no literal attacker-controlled `</script>` sequence inside the data block. - The payload remains valid after browser-side parsing. - No injected script executes when the report is opened. 4. **Apply a restrictive Content Security Policy.** Remove inline event handlers and inline executable scripts where practical, then use a policy that disallows unauthorized script execution. A CSP provides defense in depth but should not replace correct serialization. 5. **Treat all repository-derived report fields as untrusted.** Validate types and reasonable size limits for project names, paths, descriptions, category fields, and prompts. Continue using text-safe DOM APIs such as `textContent` wherever HTML markup is unnecessary. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Vague Triggers

High
Confidence
96% confidence
Finding
The trigger text is extremely broad and includes generic phrases like code quality score, audit, report card, and code smells, which can cause the skill to activate for many ordinary software-review requests beyond a user's likely intent. That creates overreach risk: the agent may run repo-scanning, file-writing, and local-serving workflows when the user only wanted lightweight advice, expanding access and actions unnecessarily.

Hidden Instructions

High
Category
Prompt Injection
Content
<!DOCTYPE html>
<!--
  slop-check report template — "Report Card + Receipt" theme.
  Do not hand-edit. The report is built by scripts/build-report.mjs, which injects the
  payload into the marked block on the "const DATA =" line below (schema:
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill directs the agent to write report files into the target repository and start a local HTTP server, but it does not require an explicit user-facing warning or confirmation before taking those side-effecting actions. In practice, this can surprise users, alter working trees, and expose potentially sensitive code-review output over a local port without informed consent.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The manifest describes this skill as grading a codebase and producing a report card with findings, which justifies scanning and report generation. However, this block creates a separate per-file 'Slop Map' explicitly for 'downstream fixing agents' and advises using it before refactoring, adding agent-enablement metadata beyond what is needed to score or roast a repo.

Missing User Warnings

Low
Confidence
90% confidence
Finding
The file explicitly instructs the agent to write `.slop-check/report-data.json` into the target repository and then run `scripts/build-report.mjs`, which are state-changing actions. There is no warning, confirmation gate, or requirement to obtain user approval before modifying files or executing a local script, so the skill can cause unintended repository changes or run unreviewed code as part of normal operation.

Intent-Code Divergence

Low
Confidence
82% confidence
Finding
The inline documentation says downstream fixing agents should consult this artifact instead of re-exploring the repo because 'the tokens were already spent,' implying prior LLM-style tokenized review. In reality, this script just reads local files, computes metrics, and writes JSON; it does not spend tokens or perform the agent behavior the comment suggests.

Static analysis

No suspicious patterns detected.