Back to skill

Security audit

PV Inspection

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent solar inspection report skill, but it needs review because user-provided station names can affect local output paths and create or overwrite files outside the intended report folder.

Install only if you are comfortable with a review-required local report tool. Run it in a restricted workspace, use trusted station names, sanitize path characters before generating reports, pin python-docx in an isolated environment, and require explicit confirmation before sending inspection reports through Feishu or email.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_word_report.py:189
Finding

Unsanitized Station Name Permits Report Path Traversal

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_word_report.py:189-194; related unsafe filename construction also occurs in scripts/generate_report.py:87-88, scripts/generate_report.py:128-129, and scripts/generate_report.py:176-177
Vulnerability Type: Path traversal and arbitrary file creation
Risk Level: High

Vulnerable Code

python
# Generate a filename from the user-controlled station name
filename = f"{station_name}_{date_str}_巡检日报.docx"
output_file = OUTPUT_DIR / filename

# Save the document
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
doc.save(str(output_file))

Related Markdown report generation:

python
output_file = OUTPUT_DIR / f"daily_{station_name}_{date_str}.md"
output_file.write_text(content, encoding='utf-8')
python
output_file = OUTPUT_DIR / f"weekly_{station_name}_{week_str}.md"
output_file.write_text(content, encoding='utf-8')
python
output_file = OUTPUT_DIR / f"monthly_{station_name}_{month_str}.md"
output_file.write_text(content, encoding='utf-8')

Technical Analysis

The station_name value originates from the required --station command-line argument and is incorporated directly into an output path. The application does not reject absolute paths, path separators, parent-directory components, control characters, or platform-specific path syntax.

In generate_word_report.py, the station name appears at the beginning of the filename. A value containing components such as ../../ is therefore resolved relative to OUTPUT_DIR and can escape the intended Word-report directory.

The Markdown generators prepend strings such as daily_ to the station name, making exploitation dependent on the constructed intermediate path layout, but they still fail to enforce that the resolved destination remains below OUTPUT_DIR.

The fixed output extensions constrain the names that can be targeted, but they do not prevent una ...[truncated 1267 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat station names as display data, not filesystem paths.

  2. Convert the station name to a strict filename-safe identifier using an allowlist such as letters, digits, spaces, hyphens, and underscores.

  3. Explicitly reject /, \, .., absolute paths, drive prefixes, null bytes, and control characters.

  4. Resolve the final path and verify that it remains under the resolved output directory before writing:

    python
    import re
    from pathlib import Path
    
    def safe_filename_component(value: str) -> str:
        value = value.strip()
        if not re.fullmatch(r"[\w -]{1,100}", value, flags=re.UNICODE):
            raise ValueError("Station name contains invalid filename characters")
        return value.replace(" ", "_")
    
    output_root = OUTPUT_DIR.resolve()
    safe_station = safe_filename_component(station_name)
    output_file = (
        output_root / f"{safe_station}_{date_str}_inspection-report.docx"
    ).resolve()
    
    if output_root not in output_file.parents:
        raise ValueError("Output path escapes the report directory")
    
  5. Apply the same validation and containment check to daily, weekly, and monthly Markdown output.

  6. If replacement is not required, use exclusive file creation or generate a unique identifier to prevent accidental overwrites.

  7. Add tests covering absolute paths, nested paths, repeated parent components, backslash traversal, Unicode separator-like characters, and excessively long names.

T08 · Insecure Dependencies

Warning
Location
scripts/generate_word_report.py:17
Finding

Unpinned Runtime Dependency Installation Guidance

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_word_report.py:17-23
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

Vulnerable Code

python
try:
    from docx import Document
    from docx.shared import Inches, Pt, RGBColor, Cm
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    from docx.enum.style import WD_STYLE_TYPE
except ImportError:
    print("Error: install the python-docx package")
    print("Run: pip install python-docx")
    sys.exit(1)

The English rendering above preserves the installation command and control flow of the source code.

Technical Analysis

When the dependency is unavailable, the script instructs the operator to install python-docx without an exact version, integrity hash, trusted package index, or isolated environment. The command therefore installs whichever release the active Python package index currently resolves.

This does not prove that the named package is malicious. However, it creates an avoidable supply-chain exposure because the installed code can vary after the Skill has been reviewed. Risk can arise from a compromised package release, compromised maintainer account, unsafe package mirror, altered package-index configuration, or a future vulnerable release.

Attack Path

  1. The Word generator runs in an environment where python-docx is not installed.
  2. The import fails and the script displays the unpinned installation command.
  3. An operator or automated workflow executes that command.
  4. pip resolves the package using the environment's current index and selects the latest matching release.
  5. If the selected distribution or configured index is compromised, package installation or subsequent import executes attacker-controlled code with the operator's privileges.

Exploitation requires compromise or manipulation of the dependency supply chain or package-resolution environment; the re ...[truncated 533 chars]

Remediation
View remediation

Remediation Suggestions

  1. Declare dependencies in a version-controlled dependency file instead of relying on runtime installation instructions.

  2. Pin python-docx to a reviewed exact version.

  3. Use a lockfile or hash-verified requirements file, for example:

    text
    python-docx==REVIEWED_VERSION \
        --hash=sha256:REVIEWED_DISTRIBUTION_HASH
    
  4. Install dependencies from a documented trusted index and avoid inheriting untrusted global pip configuration.

  5. Use an isolated virtual environment with least-privilege permissions.

  6. Run dependency vulnerability and provenance checks during release preparation.

  7. Fail with a neutral dependency-missing message rather than encouraging an ad hoc installation into the active environment.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This mismatch includes an undeclared local file write behavior to a fixed directory, which is security-relevant because it may create files in locations the user did not expect. In an agent setting, silent writes combined with overstated features can cause data leakage, overwrite risks, or persistence of sensitive inspection records without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This mismatch includes an undeclared local file write behavior to a fixed directory, which is security-relevant because it may create files in locations the user did not expect. In an agent setting, silent writes combined with overstated features can cause data leakage, overwrite risks, or persistence of sensitive inspection records without clear consent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This mismatch includes an undeclared local file write behavior to a fixed directory, which is security-relevant because it may create files in locations the user did not expect. In an agent setting, silent writes combined with overstated features can cause data leakage, overwrite risks, or persistence of sensitive inspection records without clear consent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill references scripts and report generation workflows that imply local file reads/writes, but it does not declare any tool scope such as permissions or allowed-tools. Undeclared file access increases the chance of over-broad execution in an agent environment and reduces the user's ability to understand or constrain what data may be read from or written to disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill describes sending generated inspection reports via Feishu or email but does not warn users that operational data, defect records, photos, and possibly personnel information may be transmitted to external systems. In an industrial inspection context, these reports can contain sensitive infrastructure and safety details, so unannounced external transmission increases confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The description is written entirely in Chinese and presents the skill as a Chinese-language reporting capability, with no indication that users may choose another language or that the skill is restricted to a Chinese-speaking deployment context. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest frames the skill as supporting defect recording and generation-data statistics for inspection reports. Here, the daily report uses simulated hardcoded data, while weekly and monthly reports contain placeholders like 'XXXX' and 'X 个', so the implemented behavior is template generation rather than actual defect/data recording or statistical summarization.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill description says it supports exporting formatted report documents in Word/PDF formats. In this file, all report generators write only Markdown files with a .md extension, and there is no code for Word or PDF conversion/export.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code file contains natural-language content that fixes the skill's interface and generated report content to Chinese, including the docstring and report format. The policy allows locale constraints only when the skill offers opt-in choice or clearly documents a justified region-specific limitation, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file consists solely of Chinese-language headings, instructions, and report templates, and does not indicate that users may select another language. Under the policy for natural-language violations, forcing a specific language without user opt-in can be a locale-policy issue unless the regional constraint is documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file presents all instructions, labels, and checklist content exclusively in Chinese, and there is no indication that users may choose another language or locale. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code presents its description, CLI help text, and runtime status messages exclusively in Chinese, which is a natural-language locale constraint. Under the policy, forcing a specific language without user opt-in is a violation unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.