Back to skill

Security audit

Info Vivid

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but its HTML chart generator can turn chart data into executable browser content, so it needs review before use.

Use this only with trusted chart/report data unless the SVG/HTML escaping and color validation are fixed. Avoid opening or publishing generated HTML from untrusted JSON, pin Pillow in an isolated environment for PNG rendering, and be aware that outputs include WorkBuddy branding and can be copied to an archive path when requested.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Note
Location
scripts/svg_bar_chart.py:238
Finding
Unconditional Third-Party Branding in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:163-165`, `scripts/svg_bar_chart.py:238-247`, and `scripts/png_longform.py:379-388` **Vulnerability Type**: Output manipulation through mandatory branding **Risk Level**: Low ### Vulnerable Code ```markdown - **Top**: 3px teal divider + dark Header - **Bottom**: report time + WorkBuddy watermark ``` ```python <!-- Footer --> <rect y="{chart_bottom+24}" width="{W}" height="{FOOTER_H}" fill="{theme['bg_alt']}"/> <text x="{W//2}" y="{chart_bottom+24+28}" font-size="11" fill="{theme['text_muted']}" font-family="Microsoft YaHei,sans-serif" text-anchor="middle">{footer}</text> <text x="{W//2}" y="{chart_bottom+24+46}" font-size="10" fill="#2A3A50" font-family="Microsoft YaHei,sans-serif" text-anchor="middle">Powered by WorkBuddy</text> ``` ```python main_text = f"Report time: {now} | {text}" tw = draw_obj.textbbox((0, 0), main_text, font=F_SMALL)[2] draw_obj.text(((self.W - tw) // 2, y0 + 12), main_text, font=F_SMALL, fill=GRAY) if next_update: nt_w = draw_obj.textbbox((0, 0), next_update, font=F_SMALL)[2] draw_obj.text(((self.W - nt_w) // 2, y0 + 34), next_update, font=F_SMALL, fill=DIVIDER) # WorkBuddy watermark wm = "Powered by WorkBuddy" wm_w = draw_obj.textbbox((0, 0), wm, font=F_SMALL)[2] draw_obj.text((self.W - wm_w - PAD, y0 + 22), wm, font=F_SMALL, fill=(38, 58, 82)) ``` ### Technical Analysis Both output generators insert the phrase `Powered by WorkBuddy` without consulting user configuration. The SVG renderer places it directly in every generated document, while the PNG renderer draws it into the final image. The Skill documentation also defines the watermark as part of the expected design. Because the attribution cannot be disabled, generated artifacts are systematically modified with third-party promotional content unrelated to the supplied visualization data. This may misrepresent the author, producer, or sponsor of a report. It is classified as instruction hij ...[truncated 798 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove unconditional references to WorkBuddy from both renderers. 2. If attribution is legitimately required, expose an explicit configuration field such as `watermark_text`. 3. Disable watermarking by default and require affirmative user consent before adding third-party branding. 4. Document attribution behavior clearly and allow an empty value to suppress it. 5. Add tests confirming that default output contains only user-requested content. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/svg_bar_chart.py:129
Finding
Stored Script Injection in Generated SVG and HTML<![CDATA[ ## Vulnerability Details **File Location**: `scripts/svg_bar_chart.py:106-116`, `scripts/svg_bar_chart.py:129-170`, and `scripts/svg_bar_chart.py:193-253` **Vulnerability Type**: Unescaped HTML and SVG injection **Risk Level**: High ### Vulnerable Code ```python title = config.get("title", "Chart") subtitle = config.get("subtitle", "") footer = config.get("footer", "Powered by WorkBuddy") suffix = config.get("value_suffix", "") kpis = config.get("kpis") or [] ref_val = config.get("show_reference_line") ref_lbl = config.get("reference_label", "Reference line") ``` ```python for i, item in enumerate(items): y = HEADER_H + i * ROW_H val = item["value"] label = item.get("label", "") extra = item.get("extra", "") tag = item.get("tag", "") color = item.get("color") or value_to_color(val, bar_colors, tc) bar_w = max(2, (val / max_v) * (BAR_RIGHT - BAR_LEFT)) bg = theme["bg_row1"] if i % 2 == 0 else theme["bg_row2"] display_val = f"{val:+.2f}{suffix}" if val >= 0 else f"{val:.2f}{suffix}" tooltip = label if extra: tooltip += f" | {extra}" if tag: tooltip += f" | {tag}" tooltip += f" | {display_val}" rows_svg.append(f""" <rect x="0" y="{y}" width="{W}" height="{ROW_H}" fill="{bg}"/> <text x="{PAD}" y="{y+20}" font-size="12" fill="{theme['text_primary']}" font-family="Microsoft YaHei,sans-serif">{i+1:02d}. {label}</text> <rect x="{BAR_LEFT}" y="{y+6}" width="{bar_w:.1f}" height="18" rx="3" fill="{color}" opacity="0.9"> <title>{tooltip}</title> </rect> <text x="{LABEL_X}" y="{y+20}" font-size="12" fill="{color}" font-weight="bold" font-family="Microsoft YaHei,sans-serif">{display_val}</text> <text x="{W-PAD}" y="{y+20}" font-size="10" fill="{theme['text_muted']}" font-family="Microsoft YaHei,sans-serif" text-anchor="end">{tag}</text>""") ``` ```python subtitle_svg = ( f'<text x="{W//2}" y="65" font-size="13" fill="{theme["text_label" ...[truncated 3230 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every untrusted value inserted into an HTML or SVG text node using XML-compatible escaping for `&`, `<`, and `>`. 2. Escape attribute values separately, including quotation marks. 3. Prefer constructing SVG with an XML library such as `xml.etree.ElementTree` rather than concatenating markup with f-strings. 4. Apply strict validation to configurable colors: - Accept only known color names or patterns such as `^#[0-9A-Fa-f]{6}$`. - Reject CSS functions, quotes, semicolons, and arbitrary attribute fragments. 5. Validate numeric layout settings: - Require finite integers or floats. - Enforce safe minimum and maximum dimensions. - Reject `NaN`, infinity, negative widths, and invalid reference values. 6. Escape the HTML document title independently from SVG content. 7. Consider applying a restrictive Content Security Policy to generated HTML, such as disallowing scripts and external resources. This should be defense in depth, not a substitute for encoding. 8. Add regression tests using payloads in every input-controlled field, including labels, titles, KPI values, tags, tooltips, footer text, reference labels, colors, and theme values. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:25
Finding
Unpinned Third-Party Dependency Installation Guidance<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:25-30` and `scripts/png_longform.py:5-7,64-70` **Vulnerability Type**: Unpinned and mutable dependency resolution **Risk Level**: Medium ### Vulnerable Code ```markdown | Script | Output format | Applicable scenarios | Dependencies | |--------|---------------|----------------------|--------------| | `svg_bar_chart.py` | SVG + HTML | Rankings, comparisons, arbitrary bar charts | None | | `png_longform.py` | PNG long image | Daily/weekly reports, monitoring reports, comprehensive infographics | `pip install Pillow` | ``` ```python """ png_longform.py — General-purpose dark-theme PNG long-image renderer Dependency: pip install Pillow """ ``` ```python try: from PIL import Image, ImageDraw, ImageFont except ImportError: print("ERROR: Install Pillow first: pip install Pillow") raise ``` ### Technical Analysis The project instructs users to install `Pillow` without specifying a reviewed version, lock file, package hash, or trusted package index. Consequently, installation resolves mutable content from whatever Python package index is configured in the user's environment. The package name itself is legitimate and no malicious dependency was found in the repository. The risk arises from non-reproducible dependency resolution: future versions, a compromised package index, or a maliciously configured mirror could provide code different from what was reviewed during this audit. Python package installation can execute build-system logic, and imported packages execute module initialization code. A compromised dependency can therefore run code with the privileges of the user or automation account performing installation or report generation. ### Attack Path 1. A user follows the documented `pip install Pillow` instruction. 2. `pip` queries the configured index or mirror without a repository-provided version and hash constraint. 3. The index returns a compromised, substituted, or otherwise ...[truncated 899 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Pillow to a reviewed, supported version in a dependency file, for example `Pillow==<reviewed-version>`. 2. Generate a lock file containing cryptographic hashes for all resolved distributions. 3. Install dependencies with hash enforcement, such as `pip install --require-hashes -r requirements.txt`. 4. Document the expected trusted package index and avoid untrusted or implicit mirrors. 5. Install dependencies in an isolated virtual environment with minimal permissions. 6. Use automated dependency scanning and update pinned versions through a controlled review process. 7. Prefer prebuilt, verified wheels where appropriate, and verify provenance or signatures when the package ecosystem supports them. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The documentation presents the skill as a visualization utility, but the described behavior includes file archival/copy operations and does not cleanly align with the claimed output modes. Description-behavior mismatches are dangerous because users and orchestration layers may trust a narrower capability set than the skill actually uses, enabling unexpected persistence of generated content or invocation under false assumptions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documents behavior that reads input files and writes output artifacts, but it declares no explicit tool scope or permissions boundary. In an agent environment, this weakens policy enforcement and can allow the skill to be invoked with broader file access than users expect, especially when combined with automatic output and archival behavior.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are broad enough to match many ordinary user requests, increasing the chance the skill activates in contexts where the user did not intend file generation or report rendering. Overbroad activation is risky because it can cause unexpected handling of user data and unintended file writes, especially in multi-skill agent systems.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The markdown describes writing output files and optionally copying them to an archive path, but it does not clearly warn users that local files will be created or duplicated. In an agent setting, silent or poorly signposted file writes can surprise users, leak sensitive rendered data into persistent storage, or violate least-surprise expectations.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The generated HTML sets `lang="zh-CN"`, and the script’s user-facing strings and font choices are consistently Chinese-specific throughout the file. The policy allows locale constraints only when the user can opt in or when the constraint is clearly documented and justified, neither of which is present here.

Context-Inappropriate Capability

Low
Confidence
84% confidence
Finding
The skill is described primarily as rendering structured data into SVG/HTML charts and PNG reports. SKILL.md additionally documents copying outputs into an archive directory such as `C:/Users/user/.ai-memory/news` / `C:\Users\ToddC\.ai-memory\news\`, which is not necessary to generate visualizations and adds a separate persistence/archival behavior.

Description-Behavior Mismatch

Low
Confidence
89% confidence
Finding
The manifest describes this skill as rendering charts and long-form reports, but the CLI also supports copying the generated output into an arbitrary archive directory. That file-management behavior is not part of the stated visualization/rendering scope and goes beyond producing the requested chart/report artifact.

Static analysis

No suspicious patterns detected.