Back to skill

Security audit

ESG报告技能

Security checks for vulnerabilities and agentic risk

Overview

This is mostly a local ESG report tool, but its HTML export can embed untrusted input without escaping, creating a report-viewing security risk.

Review before installing or using on untrusted ESG data. Prefer PDF output or sanitize and escape all text before HTML export, avoid hosting generated HTML on trusted domains, and treat the validation output as a basic completeness check rather than formal GRI/TCFD compliance assurance.

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/esg_exporter.py:229
Finding

Stored HTML Injection and Cross-Site Scripting in Generated Reports

Content
View full analysis

Vulnerability Details

File Location: scripts/esg_exporter.py, lines 229–260 and 304–352
Vulnerability Type: Stored HTML injection / cross-site scripting (XSS)
Risk Level: Medium

Vulnerable Code

python
html_content = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{config.get('title', 'ESG report')}</title>
    ...
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>{config.get('company_name', '')}</h1>
            <h2>{config.get('title', 'ESG sustainability report')}</h2>
            <p style="margin-top: 20px; color: #666;">Reporting period: {data.get('dimensions', {}).get('environmental', {}).get('E1', {}).get('period', '')}</p>

The same unsafe interpolation pattern is used for all three ESG dimensions:

python
for metric_id, info in data.get('dimensions', {}).get('environmental', {}).items():
    if info.get('value') is not None:
        html_content += f"""
            <tr>
                <td>{info.get('name', metric_id)}</td>
                <td>{info.get('value')}</td>
                <td>{info.get('unit', '')}</td>
                <td>{info.get('period', '')}</td>
            </tr>
"""

Equivalent code appears for social fields at lines 325–331 and governance fields at lines 346–352.

Technical Analysis

export_html_report() constructs an HTML document through direct f-string interpolation. It does not apply context-appropriate HTML escaping to the company name, report title, reporting period, metric name, metric value, or unit.

The company name and title can originate from command-line arguments. Metric fields and periods originate from the input JSON; the reporting period may also be propagated from imported CSV or Excel data by the collector. Consequently, an attacker who can influence report input can inject HTML elements, event handlers, or script markup int ...[truncated 2147 chars]

Remediation
View remediation

Remediation Suggestions

  1. Apply context-appropriate HTML escaping to every dynamic value before interpolation. At minimum, use html.escape(value, quote=True) after converting values to strings:

    python
    from html import escape
    
    def html_text(value):
        return escape(str(value if value is not None else ""), quote=True)
    
  2. Use the helper for the company name, title, reporting period, metric name, value, and unit:

    python
    company_name = html_text(config.get("company_name", ""))
    title = html_text(config.get("title", "ESG sustainability report"))
    period = html_text(
        data.get("dimensions", {})
            .get("environmental", {})
            .get("E1", {})
            .get("period", "")
    )
    
  3. Prefer an auto-escaping template engine, such as Jinja2 with autoescape explicitly enabled for HTML templates. Avoid assembling HTML through repeated f-string concatenation.

  4. Validate imported JSON against a strict schema. Enforce expected scalar types and reasonable maximum lengths for textual fields. Reject nested objects or unexpected data types where strings or numeric values are required.

  5. Treat CSV and Excel input as untrusted, because fields such as period are propagated into the generated report.

  6. If reports are served from a website, deploy a restrictive Content Security Policy that disallows inline scripts and event handlers. This should be defense in depth rather than a replacement for output encoding.

  7. Add regression tests for all dynamic HTML fields using payloads containing <, >, &, quotes, <script> elements, and event-handler attributes. Verify that generated reports contain encoded text rather than executable markup.

Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (16)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

According to the finding, the actual functionality is substantially narrower than the documented claims, with the main capability limited to static chart generation rather than full ESG workflow support. In an enterprise reporting setting, this discrepancy can cause operational misuse, silent omissions, and false confidence in generated disclosures, especially where stakeholders assume data validation or standards conformance occurred.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

According to the finding, the actual functionality is substantially narrower than the documented claims, with the main capability limited to static chart generation rather than full ESG workflow support. In an enterprise reporting setting, this discrepancy can cause operational misuse, silent omissions, and false confidence in generated disclosures, especially where stakeholders assume data validation or standards conformance occurred.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

According to the finding, the actual functionality is substantially narrower than the documented claims, with the main capability limited to static chart generation rather than full ESG workflow support. In an enterprise reporting setting, this discrepancy can cause operational misuse, silent omissions, and false confidence in generated disclosures, especially where stakeholders assume data validation or standards conformance occurred.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

According to the finding, the actual functionality is substantially narrower than the documented claims, with the main capability limited to static chart generation rather than full ESG workflow support. In an enterprise reporting setting, this discrepancy can cause operational misuse, silent omissions, and false confidence in generated disclosures, especially where stakeholders assume data validation or standards conformance occurred.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill describes reading input data files and exporting reports, which implies file read/write behavior, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates a governance gap: an agent may be granted broader filesystem access than users expect, increasing the chance of unintended file access or modification during report generation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Natural-language strings in the file, including the module description and later CLI help text, impose a single language/locale on users. Under the stated policy, forcing a specific language without user opt-in is a policy violation unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This hard-codes a specific language/locale in generated natural-language output, which can violate language/locale policy when no opt-in or selection mechanism is provided. The rest of the script also produces Chinese-language report text by default, but this line explicitly enforces the locale in the output document.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This file contains user-facing descriptions entirely in Chinese and later continues that pattern in CLI help and chart labels, indicating the skill forces a specific locale by default. Under the policy, language-specific behavior should offer user choice or clearly justify the constraint, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Argument descriptions and command help are exposed directly to users but are only provided in Chinese. Because the script does not provide a language selection mechanism or document a justified region-specific restriction, this is a natural-language locale policy issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation instructs users to export reports to PDF/HTML files but does not warn that output paths may overwrite existing files or create artifacts on disk. While not directly enabling code execution, this can lead to accidental data loss, misplaced sensitive reports, or unintended writes in shared working directories.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The title and entire skill reference content are written in Chinese, and the file does not indicate that language selection is optional or that the skill is specifically limited to a Chinese-speaking or region-specific context. Under the policy rule for language/locale, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire markdown document is written in Chinese and does not offer any language or locale choice, translation note, or justification for being region-specific. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code performs a file write to the path supplied by the user, but the function contains no confirmation prompt or explicit user-facing disclosure at the point of the write. For this rule, file writes in code should have some visible warning, logging, or documented notice unless clearly disclosed elsewhere in the skill materials.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code file contains natural-language descriptions and help text entirely in Chinese, starting with the module docstring and continuing in user-facing messages. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in, and this file provides no alternative language option or justification for being Chinese-only.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The argument parser declares supported chart types as 'bar', 'pie', 'radar', 'trend', 'comparison', and 'all', which communicates that selecting 'pie' or 'comparison' will generate those outputs. However, the dispatch logic only implements 'bar', 'radar', and 'trend'; when 'pie' or 'comparison' is chosen, no chart function is called and the code still returns a success result. This is a documentation/intent mismatch within the code interface itself.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.