Back to skill

Security audit

Research Company

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says by researching a company and generating a PDF, with ordinary caution needed for package installation and local report files.

Before installing, prefer using a pinned or preinstalled ReportLab dependency, review where the temp JSON and final PDF will be written, clean up sensitive research data after use, and verify important claims or links in generated reports before relying on them.

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 (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:54
Finding
Unpinned Runtime Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 54-56 **Vulnerability Type**: Supply-chain exposure through an unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Code ```bash # Install if needed pip install reportlab ``` ### Technical Analysis The workflow instructs the Agent to install `reportlab` without specifying a reviewed version, integrity hash, trusted package index, or locked dependency set. Consequently, the package artifact installed during one invocation may differ from the artifact used during another invocation. Python package installation can execute package build and installation logic. If the selected package release or one of its transitive dependencies is compromised, malicious code could execute with the same operating-system permissions and network access as the Agent running `pip`. This is a supply-chain weakness rather than evidence that the current ReportLab package is malicious. ### Attack Path 1. The Skill is invoked in an environment where ReportLab is unavailable. 2. Following `SKILL.md`, the Agent runs `pip install reportlab`. 3. The package resolver downloads the current package and dependencies from the configured index. 4. A compromised release, dependency, index, or package artifact supplies malicious build or installation logic. 5. That logic executes during installation with the privileges of the Agent process. 6. The malicious package can then affect PDF generation or access resources available to that process. ### Impact Assessment Successful exploitation could provide arbitrary Python code execution with the permissions of the account performing the installation. Depending on the execution environment, this could expose accessible files, environment variables, generated reports, and network services. It could also modify files in the Python environment or tamper with subsequent report generation. The issue does not independently provide privilege escalation beyond the per ...[truncated 41 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Declare an exact, reviewed ReportLab version in a dependency file, for example: ```text reportlab==<reviewed-version> \ --hash=sha256:<verified-distribution-hash> ``` 2. Install dependencies with hash verification: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Lock and review all transitive dependencies rather than pinning only the top-level package. 4. Use a trusted or internally mirrored package index. 5. Install inside an isolated virtual environment or container with minimal filesystem and network permissions. 6. Avoid performing package installation automatically during normal Skill execution. Prepare and verify the runtime environment before invoking the Skill. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_report.py:137
Finding
Untrusted Research Data Is Interpreted as ReportLab Paragraph Markup<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_report.py`, lines 137-145; additional sinks at lines 209-211, 273-275, 333, 366, 375, 392, 416-438, 463-475, 502, and 510 **Vulnerability Type**: Markup injection and malformed-input denial of service **Risk Level**: Medium ### Vulnerable Code The report header directly interpolates JSON values into ReportLab markup: ```python def create_header_table(data, styles): """Create the dark header section.""" company = data.get('company_name', 'Unknown Company') date = data.get('report_date', datetime.now().strftime('%B %d, %Y')) url = data.get('source_url', '') header_content = [ [Paragraph('<font color="white" size="9">ACCOUNT RESEARCH REPORT</font>', styles['Normal'])], [Paragraph(f'<font color="white" size="20"><b>{company}</b></font>', styles['Normal'])], [Spacer(1, 8)], [Paragraph(f'<font color="#94a3b8" size="9"><b>Date:</b> {date} | <b>Source:</b> {url} | <b>Analyst:</b> Claude AI</font>', styles['Normal'])] ] ``` Titles and descriptions are also passed directly to the markup parser: ```python def create_bordered_item(title, description, accent_color, styles): """Create a left-bordered item block.""" content = [] if title: content.append([Paragraph(f'<b>{title}</b>', styles['ItemTitle'])]) if description: content.append([Paragraph(description, styles['ItemDesc'])]) ``` Additional direct sinks include: ```python story.append(Paragraph(data['executive_summary'], styles['ReportBody'])) ``` ```python story.append(Paragraph(data['target_market']['segments'], styles['ReportBody'])) ``` ```python story.append(Paragraph(data['target_market']['business_model'], styles['ReportBody'])) ``` ### Technical Analysis ReportLab's `Paragraph` accepts XML-like formatting syntax. The generator supplies externally derived JSON strings directly to this parser without XML escaping, tag allowlisting, schema vali ...[truncated 2313 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every untrusted value before passing it to `Paragraph` or interpolating it into trusted markup: ```python from xml.sax.saxutils import escape safe_company = escape(str(company)) safe_date = escape(str(date)) safe_url = escape(str(url)) ``` 2. Keep trusted formatting separate from untrusted text: ```python Paragraph( f'<font color="white" size="20"><b>{safe_company}</b></font>', styles['Normal'] ) ``` 3. Apply escaping consistently to all fields, including descriptions, summaries, competitors, trends, keywords, profile values, and footer data. 4. If limited markup is a required feature, implement an explicit allowlist of permitted tags and attributes rather than accepting arbitrary ReportLab markup. 5. Reject link and resource-loading constructs unless they are explicitly required and validated. 6. Validate the JSON against a machine-enforced schema before rendering: - Require expected object, array, and string types. - Set maximum lengths for strings and arrays. - Reject unexpected nested structures. 7. Catch ReportLab parsing and rendering exceptions and return a controlled error without leaving a misleading or partial output file. 8. Add regression tests using unbalanced tags, entity characters, injected links, deeply nested markup, and oversized strings. ]]>
Vulnerability Patterns
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill instructs the agent to read local files such as `scripts/generate_report.py` and `references/data-schema.md`, but it does not declare any explicit tool scope or permissions. Missing scope declarations can cause overbroad tool access or ambiguous enforcement, increasing the chance that an agent with broader-than-expected filesystem access reads unintended files in the workspace.

Missing User Warnings

Low
Confidence
87% confidence
Finding
The workflow writes JSON to `/tmp` and generates a PDF in the workspace without warning the user that local filesystem changes will occur. While expected for a report-generation skill, silent file creation can still surprise users, leave residual sensitive research artifacts on disk, or overwrite existing files if paths are reused carelessly.

Static analysis

No suspicious patterns detected.