Back to skill

Security audit

Xhs Rental Ocr

Security checks for vulnerabilities and agentic risk

Overview

This OCR skill is mostly coherent, but its Excel export can place attacker-controlled image filenames into spreadsheets without formula sanitization.

Review this before installing if you process images or filenames from other people. Use a virtual environment, consider pinning dependencies, and rename input files so they do not start with =, +, -, @, tabs, or similar formula-triggering characters before opening exported spreadsheets.

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
scripts/extract_data.py:92
Finding

Spreadsheet Formula Injection Through Attacker-Controlled Image Filenames

Content
View full analysis

Vulnerability Details

File Location: scripts/extract_data.py:92 and scripts/extract_data.py:187-190
Vulnerability Type: Spreadsheet formula injection
Risk Level: Medium

Vulnerable Code

python
# scripts/extract_data.py:187-190
records = extract_rental_data(texts)
for r in records:
    r['图片'] = f"{os.path.basename(img_path)}-{i+1}"
all_records.extend(records)
python
# scripts/extract_data.py:90-93
for row, record in enumerate(records, 2):
    ws.cell(row=row, column=1, value=row-1)
    ws.cell(row=row, column=2, value=record.get('图片', ''))
    ws.cell(row=row, column=3, value=record.get('区域', ''))

Technical Analysis

The image filename originates from a user-supplied command-line path. Its basename is placed into each generated record without validation and is subsequently written directly to an XLSX cell.

Spreadsheet values beginning with = can be stored as formulas by openpyxl. Spreadsheet applications may also treat values beginning with other formula-triggering characters, such as +, -, or @, as active expressions in some contexts. Appending -{i+1} does not reliably neutralize formulas because an attacker can construct a filename for which the resulting cell value remains a valid expression.

The vulnerability requires OCR to produce at least one rental record because filename cells are only generated for extracted records.

Attack Path

  1. An attacker creates or distributes an image whose filename begins with a spreadsheet formula, such as a formula that performs a network request.
  2. The victim processes the file using:
    bash
    python3 scripts/extract_data.py --images 'ATTACKER_CONTROLLED_FILENAME' --output data.xlsx
    
  3. OCR finds text matching the rental-data patterns, causing at least one record to be generated.
  4. The attacker-controlled basename is copied into the 图片 field and written directly to the workbook.
  5. The ...[truncated 912 chars]
Remediation
View remediation

Remediation Suggestions

Sanitize every user-controlled or OCR-controlled value before writing it to a spreadsheet cell.

  1. Prefix values beginning with formula-triggering characters with an apostrophe.
  2. Explicitly store such cells as strings.
  3. Apply the protection through a centralized helper so that future exported fields receive the same treatment.
  4. Add tests covering =, +, -, @, tabs, carriage returns, and leading whitespace before formula characters.

Example hardening:

python
def safe_spreadsheet_value(value):
    if not isinstance(value, str):
        return value

    dangerous_prefixes = ("=", "+", "-", "@", "\t", "\r")
    if value.startswith(dangerous_prefixes):
        return "'" + value

    return value

image_cell = ws.cell(
    row=row,
    column=2,
    value=safe_spreadsheet_value(record.get("图片", ""))
)
image_cell.data_type = "s"

The same helper should be applied to all text fields written to XLSX or CSV output, including any fields populated from OCR results in future versions.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unbounded and Unhashed Third-Party Dependencies

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-11 and README.md:17
Vulnerability Type: Non-reproducible dependency resolution and supply-chain exposure
Risk Level: Low

Vulnerable Code

text
# Python dependencies for xhs-rental-ocr

# Image processing
Pillow>=10.0.0

# Excel export
openpyxl>=3.1.0

# macOS OCR (system framework, but needs Python bindings)
pyobjc-framework-Vision>=10.0
pyobjc-framework-Cocoa>=10.0

The documented installation command resolves these mutable version ranges:

bash
pip3 install -r requirements.txt

Technical Analysis

Every dependency specifies only a minimum version. There are no exact pins, upper bounds, lock file entries, or package hashes. Consequently, separate installations can resolve materially different dependency versions.

This configuration does not itself demonstrate that any currently listed package is malicious. However, it creates a supply-chain weakness because future releases are trusted automatically without being represented in the audited project state. Python package installation can execute package build logic, while imported dependencies execute with the privileges of the OCR process.

Attack Path

  1. A listed dependency account, release process, or distribution artifact is compromised, or a future release contains a security vulnerability.
  2. A user runs the documented installation command after the affected release becomes available.
  3. The open-ended version constraint permits pip to select the affected release automatically.
  4. Malicious build behavior may execute during installation, or vulnerable code may execute when the application imports or uses the dependency.
  5. The resulting impact occurs with the privileges of the user or automation account performing installation or running the skill.

Impact Assessment

A compromised package could potentially access any files, creden ...[truncated 440 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin each dependency to an explicitly reviewed version.
  2. Generate and commit a lock file containing transitive dependencies.
  3. Record cryptographic hashes and install with hash verification.
  4. Update dependencies through a controlled review process with automated vulnerability scanning.
  5. Install packages inside a dedicated virtual environment without administrative privileges.
  6. Separate platform-specific dependencies where appropriate.

A hash-locked installation should use a command such as:

bash
python3 -m pip install --require-hashes -r requirements.lock

The lock file should use exact versions and SHA-256 hashes, for example:

text
Pillow==REVIEWED_VERSION \
    --hash=sha256:VERIFIED_DISTRIBUTION_HASH

Hashes must be generated from trusted, reviewed artifacts rather than copied from an unverified source.

Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (11)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The 'Use when' activation text is broad enough to match generic image/table/data-extraction requests, not just Xiaohongshu rental OCR tasks. In an agent ecosystem, this can cause over-invocation of the skill on unrelated user prompts, leading to unintended processing of local images or URLs and increasing the attack surface for any downstream code the skill runs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help text and --url argument present URL-based extraction as a supported usage mode, including a concrete example for extracting from a Xiaohongshu URL. However, the runtime branch for args.url only prints a TODO/warning and performs no download or OCR, which directly contradicts the documented behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

Natural-language strings describe the module specifically as a Chinese OCR component, and the default recognition languages are preset to 'zh-Hans,en-US'. Under the locale policy, forcing a language or locale without explicit user choice can be a violation unless the regional constraint is clearly justified and documented.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The natural-language description emphasizes Chinese optimization and a Chinese-centric use case, and the documented default OCR language later includes Chinese by default. While multilingual use is technically possible via a parameter, the README framing does not clearly present language choice up front or as an opt-in, which can conflict with locale-neutral policy expectations.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is only lower-bounded (Pillow>=10.0.0), which makes builds non-reproducible and can unintentionally pull in a vulnerable or breaking future release. In a skill that processes untrusted social-media images, image-parsing libraries are part of the attack surface, so version drift modestly increases supply-chain and parser-risk exposure.

Content

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

text
# Python dependencies for xhs-rental-ocr

# Image processing
Pillow>=10.0.0

# Excel export
openpyxl>=3.1.0

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

Pillow has a history of security advisories, and because the requirement is not pinned, it is impossible to verify from this manifest alone whether deployed environments are using a safe release. This matters more in this skill because it processes attacker-controlled images from social platforms, where image decoder vulnerabilities are a realistic concern.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

openpyxl is unpinned, so installations may resolve to different versions over time, including versions with security regressions or incompatible behavior. Because this skill exports Excel data, the library is directly used in document generation, making dependency control an appropriate hardening measure even though the immediate impact is limited.

Content

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

text
Pillow>=10.0.0

# Excel export
openpyxl>=3.1.0

# macOS OCR (system framework, but needs Python bindings)
pyobjc-framework-Vision>=10.0

Unverifiable Dependency: openpyxl has 2 known advisory(ies) (CVE-2017-5992 (Improper Restriction of XML External Entity Reference in Openpyxl); CVE-2017-5992 (Openpyxl 2.4.1 resolves external entities by default, which allows remote attack)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding

openpyxl has known past advisories, and the unpinned requirement prevents confirming whether an affected version may be installed. In this skill the library is used for Excel export rather than parsing hostile spreadsheets, so the practical risk is lower, but unverifiable dependency state is still a genuine security hygiene issue.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
89% confidence
Finding

pyobjc-framework-Vision is not pinned to a specific release, which weakens reproducibility and allows unreviewed upstream changes into the runtime environment. While this wrapper is less commonly associated with direct remote exploitation, controlling exact versions is still important for supply-chain hygiene in an OCR pipeline handling untrusted content.

Content

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

text
openpyxl>=3.1.0

# macOS OCR (system framework, but needs Python bindings)
pyobjc-framework-Vision>=10.0
pyobjc-framework-Cocoa>=10.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
89% confidence
Finding

pyobjc-framework-Cocoa is also unpinned, creating the same reproducibility and supply-chain uncertainty as the other dependencies. Since it bridges into system frameworks, unexpected version changes can affect stability and security assumptions even if no specific exploit is evident here.

Content

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

text
# macOS OCR (system framework, but needs Python bindings)
pyobjc-framework-Vision>=10.0
pyobjc-framework-Cocoa>=10.0

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

This code creates new files alongside the input image by saving sliced copies, which is a file-write operation covered by the warning requirement for code files. Although the function docstring describes slicing behavior, there is no visible user-facing print/log/confirmation at the point of writing, so the disclosure is minimal and easy to miss in execution.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.