Back to skill

Security audit

Display Quantitative Information

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent data-visualization helper that reads user-provided chart data/specs and can write chart outputs, with no evidence of hidden persistence, credential access, network payloads, or deceptive behavior.

This skill is reasonable to install for chart critique, display selection, and simple SVG chart generation. Use it with data you intend the agent to read, choose output paths deliberately because chart files may be overwritten, and avoid feeding very large or untrusted CSVs until input and output limits are added. Review generated charts for source, units, uncertainty, and accessibility before relying on them in reports or slides.

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

Warning
Location
scripts/render_chart_svg.py:35
Finding

Unbounded CSV Rendering Can Cause Local Resource Exhaustion

Content
View full analysis
List[Dict[str, str]]: try: with path.open("r", encoding="utf-8-sig", newline="") as handle: rows = list(csv.DictReader(handle)) ``` The resulting unbounded collection is subsequently aggregated: ```python def aggregate(rows: List[Dict[str, str]], x: str, y: str, group: Optional[str]) -> List[Dict[str, Any]]: acc: Dict[Tuple[str, str], List[float]] = defaultdict(list) for r in rows: yv = to_float(r.get(y)) if yv is None: continue xv = str(r.get(x, "")) gv = str(r.get(group, "")) if group else "" acc[(xv, gv)].append(yv) data = [] for (xv, gv), vals in acc.items(): data.append({"x": xv, "group": gv, "y": sum(vals) / len(vals), "n": len(vals)}) return data ``` ### Technical Analysis The renderer materializes the entire CSV through `list(csv.DictReader(handle))`. It does not enforce limits on input file size, row count, field length, unique categories, group cardinality, or generated SVG size. Memory consumption is amplified during processing because the original rows remain resident while values are copied into aggregation lists. The renderer then builds the complete SVG as an in-memory list of strings before joining and writing it. A CSV with many rows or high-cardinality category and group values can therefore consume substantial memory and CPU and produce an excessively large output file. Unlike `scripts/suggest_display.py`, which provides a bounded `--max-rows` sampling option, the SVG renderer has no equivalent safeguard. ### Attack Path 1. An attacker or untrusted user supplies a very large CSV, or a CSV containing extremely many unique category/group combinations. 2 ...[truncated 1142 chars]
Remediation
View remediation
= max_rows: raise SystemExit(f"Error: CSV exceeds the {max_rows} row limit.") # Update running sum and count for each key. ``` 4. **Cap cardinality and field length** - Limit the number of unique categories and groups. - Reject or truncate abnormally long headers, category labels, titles, and group names. - Fail clearly when a chart would contain more marks than the renderer can safely support. 5. **Bound output generation** - Estimate the number of SVG elements before rendering. - Enforce a maximum output byte size. - Write incrementally where practical instead of retaining the entire SVG document in memory. 6. **Constrain output dimensions** - Keep the existing minimum dimensions and add maximum width and height values. - Reject dimensions that would result in impractically large documents. 7. **Add adversarial tests** - Test oversized row counts, high-cardinality groups, extremely long fields, and large requested dimensions. - Verify that each case terminates with a controlled error rather than exhausting resources. ]]>
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises bundled scripts that read input files and write outputs such as SVG and markdown, but it does not declare any explicit tool scope or allowed-tools restrictions. That mismatch can let an agent invoke file read/write capabilities more broadly than intended, increasing the risk of unintended access to local files or overwriting files during normal use.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The spec explicitly states a persuasive goal to make sales appear to have 'jumped dramatically,' which signals intent to shape perception rather than accurately inform. In the context of a quantitative-display skill, this is more dangerous because the surrounding settings also omit labels, units, zero baseline, context, and use decorative 3D effects, all of which can amplify a misleading executive-facing chart.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JSON file is a manifest-like trigger corpus, so SQP-1 applies. Several positive trigger queries such as "Make a better visual argument from these numbers for my report" and "Generate a quick SVG chart from this CSV" are phrased broadly and there is no accompanying specification of explicit boundaries or exclusion conditions beyond a few negative examples, making activation scope somewhat ambiguous.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This JSON manifest describes the skill content but provides no activation conditions, trigger phrases, or exclusion conditions. For manifest files, the absence of any trigger specificity can make skill invocation behavior ambiguous if this file is used as part of routing or selection metadata.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This is a JSON manifest-style file, so vague-trigger review applies. The phrase "Review five chart critiques" is broad natural language and does not specify activation boundaries, exclusions, or a constrained invocation context, which could overlap with ordinary review requests rather than a narrowly scoped skill trigger.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.