Back to skill

Security audit

Extract Design

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent webpage design-extraction helper, but it should be used with normal caution around browser access, file output paths, and third-party dependencies.

Install and run this in a normal isolated project or virtual environment, prefer public/trusted target URLs, avoid pointing it at localhost, private network, cloud metadata, or sensitive internal pages, and keep any --out path under the skill's assets/theme directory unless you intentionally want an intermediate file elsewhere. Pin Playwright in controlled environments and be aware that some sample HTML specimens may load external fonts when opened.

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/extract-styles.py:159
Finding
Unrestricted URL Navigation Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/extract-styles.py:159-166` - `scripts/extract-keyframes.py:5-11` **Vulnerability Type**: Server-Side Request Forgery through unrestricted browser navigation **Risk Level**: High ### Vulnerable Code `scripts/extract-styles.py:159-166`: ```python def extract(url: str, switch_dark: bool = False, out_path: str = None): with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={"width": 1280, "height": 800}) print(f"[extract-styles] Navigating to {url}", file=sys.stderr) page.goto(url, wait_until="networkidle", timeout=30000) ``` `scripts/extract-keyframes.py:5-11`: ```python def extract_keyframes(url, output_file): with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.goto(url, wait_until="networkidle", timeout=30000) ``` ### Technical Analysis Both scripts pass a caller-controlled URL directly to Playwright's `page.goto()` without validating the URL scheme, destination hostname, resolved IP address, or redirect chain. There are no controls preventing navigation to: - Loopback destinations such as `127.0.0.1` or `localhost` - Private network ranges - Link-local or cloud metadata addresses - Internal DNS names - Non-HTTP schemes such as `file:` or `data:` - Public URLs that redirect to otherwise prohibited destinations The browser subsequently evaluates JavaScript against the loaded document and extracts its title, final URL, CSS variables, computed colors, typography, background resources, and other document metadata. This turns the scripts into a limited request-and-observation proxy operating from the agent's network environment. ### Attack Path 1. An attacker or untrusted user supplies an internal destination as the extraction URL. 2. The skill forwards the value unchanged to `page.goto()`. 3. Chromium requests the destination using the netwo ...[truncated 1146 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Accept only explicitly supported schemes, preferably `https` and optionally `http`. 2. Reject URLs containing embedded credentials or unsupported schemes such as `file:`, `data:`, `javascript:`, and `ftp:`. 3. Resolve the destination hostname before navigation and reject addresses in loopback, private, link-local, multicast, unspecified, and reserved ranges for both IPv4 and IPv6. 4. Intercept browser requests through Playwright routing and repeat destination validation for every subrequest. 5. Validate every redirect target rather than only the original URL. 6. Consider requiring an explicit hostname allowlist when the skill is used in sensitive environments. 7. Run Chromium in an isolated container with restricted egress and no access to internal networks or cloud metadata endpoints. 8. Add automated tests covering encoded IP addresses, IPv6, DNS rebinding, alternate numeric address formats, and public-to-private redirects. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:606
Finding
Unpinned Playwright and Chromium Installation Creates Supply-Chain Risk<![CDATA[ ## Vulnerability Details **File Location**: - `SKILL.md:606-612` - `README.md:110-113` **Vulnerability Type**: Mutable, unverified third-party dependency installation **Risk Level**: Medium ### Vulnerable Code `SKILL.md:606-612`: ```markdown This skill ships a self-contained Python/Playwright script. Before running it, resolve `SKILL_DIR` using the Glob pattern `**/skills/extract-design/SKILL.md` (as described in **Output Location** above), then substitute it into the path below. **Setup (one-time):** ```bash pip install playwright playwright install chromium ``` ``` `README.md:110-113`: ```markdown - [Claude Code](https://claude.ai/claude-code) CLI - Python 3.8+ - Playwright: `pip install playwright && playwright install chromium` - Web access (for fetching target pages) ``` ### Technical Analysis The installation instructions retrieve the latest available Playwright package and its corresponding Chromium binary at installation time. The project does not provide: - An exact Playwright version - A dependency lock file - Package hashes - A pinned Chromium revision documented by the project - Artifact checksum or signature verification - An explicit trusted package index As a result, the effective dependency set can change after the skill has been audited. A compromised upstream release, package-index configuration, mirror, or downloaded browser artifact could introduce code that was not present during review. The audited project itself does not contain evidence that the current Playwright package is malicious. The vulnerability is the non-reproducible and insufficiently verified installation process. ### Attack Path 1. A user follows the documented setup commands. 2. `pip` resolves whichever Playwright release is current or available through the configured package index. 3. Playwright downloads a matching browser artifact during `playwright install chromium`. 4. If either source has been compromised or redirected through an unsafe mirror, ...[truncated 841 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Playwright to a reviewed exact version, for example through a version-controlled `requirements.txt` or lock file. 2. Generate and verify cryptographic hashes using a hash-locked installation process such as `pip install --require-hashes`. 3. Document the expected Chromium revision and verify downloaded artifacts against trusted checksums or signatures where supported. 4. Require the official Python package index rather than inheriting an arbitrary environment-specific mirror. 5. Install dependencies in an isolated virtual environment or disposable container. 6. Add automated dependency scanning and a controlled process for reviewing version updates. 7. Keep package and browser updates synchronized and test the pinned combination before publishing it. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
assets/theme/planetono-style-specimen.html:8
Finding
Supposedly Self-Contained HTML Specimens Load Undeclared External Fonts<![CDATA[ ## Vulnerability Details **File Location**: - `assets/theme/planetono-style-specimen.html:8` - `assets/theme/tiwis-style-specimen.html:8` **Vulnerability Type**: Undisclosed external resource loading and privacy leakage **Risk Level**: Low ### Vulnerable Code `assets/theme/planetono-style-specimen.html:8`: ```css @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap'); ``` `assets/theme/tiwis-style-specimen.html:8`: ```css @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500&display=swap'); ``` ### Technical Analysis The specimens load CSS and font resources from Google Fonts whenever they are opened in a browser with network access. This conflicts with the project's description of the generated specimen as a self-contained HTML file. External CSS is mutable and is retrieved at viewing time rather than being part of the audited artifact. Loading it also discloses browser and network metadata to an external service. Depending on browser policy, the request can expose the viewer's IP address, user agent, access time, and referrer-related information. No malicious JavaScript was found in the referenced specimens. The confirmed issue is the undeclared network dependency and resulting privacy and integrity exposure. ### Attack Path 1. A user opens either specimen HTML file in a browser. 2. The browser processes the CSS `@import` directive. 3. A request is sent to `fonts.googleapis.com`. 4. The returned stylesheet directs the browser to additional font resources. 5. Google or any compromised delivery path receives request metadata and controls the remotely delivered font stylesheet or files. ### Impact Assessment The issue can result in: - Disclosure of the viewer's IP address, browser metadata, and access time - Unexpected outbound network traffic from a local artifact - Rendering failures in offline or restricted environments - Dependence on mutable third-party content - A li ...[truncated 221 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove remote `@import` rules and use a system-font fallback stack where exact font reproduction is unnecessary. 2. If the fonts are required, bundle reviewed font files inside the project and reference them through local `@font-face` declarations. 3. Confirm that font licenses permit redistribution before bundling them. 4. Add a restrictive Content Security Policy, such as `default-src 'self'; font-src 'self'; style-src 'self' 'unsafe-inline'`, adjusted to the specimen's actual requirements. 5. Clearly disclose any intentionally retained external resources and require explicit user consent before loading them. 6. Add a validation step that rejects generated specimens containing remote URLs when the output is described as self-contained. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (37)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is the same underlying issue expressed with more detail: the skill claims narrowly scoped, full design-system extraction with local asset-only writes, while the implementation behavior described by analysis allows arbitrary path output and only partial JSON extraction. Such description-behavior drift can bypass reviewer expectations and lead to unsafe use of the helper scripts in more privileged contexts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This is the same underlying issue expressed with more detail: the skill claims narrowly scoped, full design-system extraction with local asset-only writes, while the implementation behavior described by analysis allows arbitrary path output and only partial JSON extraction. Such description-behavior drift can bypass reviewer expectations and lead to unsafe use of the helper scripts in more privileged contexts.

Ae1

High
Category
analysis-evasion
Content
The directory containing that `SKILL.md` file is `SKILL_DIR`. All output goes under `SKILL_DIR/assets/theme/`.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Hidden Instructions

High
Category
Prompt Injection
Content
<button class="btn btn-secondary theme-toggle" id="themeToggle">Toggle theme</button>
    </div>

    <!-- SECTION: Visual Character — replace component CSS below with extracted styles from target site -->
    <section class="section hero">
      <h2 style="margin-top:0;">Visual Character</h2>
      <p class="muted">Replace this with a concise summary of the extracted design language, including atmosphere and motifs.</p>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Color Board — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Color Board</h2>
      <div class="grid grid-3">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Typography — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Typography</h2>
      <div class="card">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Background System — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Background System</h2>
      <!-- Add/remove bg-sample cards based on actual background layers found -->
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- SECTION: Background System — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Background System</h2>
      <!-- Add/remove bg-sample cards based on actual background layers found -->
      <div class="background-board">
        <div class="bg-sample bg-page-base">
          <div class="bg-label">Page Base</div>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Motif Library — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Motif Library</h2>
      <!-- Add/remove motif cards based on what motifs were actually found in the target site -->
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- SECTION: Motif Library — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Motif Library</h2>
      <!-- Add/remove motif cards based on what motifs were actually found in the target site -->
      <div class="motif-grid">
        <div class="motif-card motif-stripe">Diagonal Stripe</div>
        <div class="motif-card motif-gridline">Gridline</div>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Cards — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Cards</h2>
      <div class="grid grid-3">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Forms — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Forms</h2>
      <div class="card">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Navigation — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Navigation</h2>
      <div class="card">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Table — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Table</h2>
      <table class="table">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</table>
    </section>

    <!-- SECTION: Prose — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Prose</h2>
      <div class="card prose">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Code Block — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Code Block</h2>
      <div class="code">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Callouts — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Callouts</h2>
      <div class="grid grid-2">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Overlay — replace component CSS below with extracted styles from target site -->
    <section class="section">
      <h2>Overlay</h2>
      <div class="overlay-demo">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</div>
    </section>

    <!-- SECTION: Animation System — add extracted @keyframes demos below -->
    <section class="section">
      <h2>Animation System</h2>
      <p class="muted" style="margin-bottom:16px;">Replace this section with extracted @keyframes from the site's CSS. Add animation demo boxes and the @keyframes definitions in the CSS section above.</p>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The script accepts a caller-supplied output path and writes JSON there without constraining it to the skill’s declared assets/theme directory. In an agent context, this can violate the skill boundary and allow overwriting or planting files elsewhere on the filesystem, which is especially risky because the skill metadata explicitly promises it will never write into the user’s project.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script accepts an arbitrary --out path and writes extracted page data directly to that location without constraining it to the skill’s assets/theme directory. In an agent context, this can violate the skill’s stated boundary and enable overwriting files outside the skill workspace, including user project files or other sensitive local paths if the caller can influence arguments.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill instructs the agent to write files into its own assets/theme directory but does not declare any explicit tool scope such as allowed-tools or permissions. That creates an avoidable overprivilege gap: if the runtime grants broader file-write capability than intended, the skill can write beyond its documented boundary or be combined with prompt-injected path changes in future edits.

Skill Enumeration

Medium
Category
Agent Snooping
Content
**Before writing any output file**, resolve the skill directory by running:

```
Glob pattern: **/skills/extract-design/SKILL.md
```

The directory containing that `SKILL.md` file is `SKILL_DIR`. All output goes under `SKILL_DIR/assets/theme/`.
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Skill Enumeration

Medium
Category
Agent Snooping
Content
**Before writing any output file**, resolve the skill directory by running:

```
Glob pattern: **/skills/extract-design/SKILL.md
```

The directory containing that `SKILL.md` file is `SKILL_DIR`. All output goes under `SKILL_DIR/assets/theme/`.
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The 'When to use' and 'Do not use' trigger guidance is presented in Chinese bullet points, which imposes a specific language on users or maintainers reading the skill. The file does not state that Chinese is optional, provide an alternative language version for these instructions, or offer a user language choice.

Static analysis

No suspicious patterns detected.