Back to skill

Security audit

百度网盘文档扫描官方Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Baidu image-processing integration, but it needs Review because its documented local-file execution path can run shell commands from crafted file paths and it handles sensitive images/API keys with weak hardening.

Review before installing. Use only if you trust the Baidu scan endpoint and are comfortable uploading the images you process. Do not process attacker-supplied local file paths until the sh -c command pattern in SKILL.md is replaced with direct stdin/file handling. Restrict and rotate BDPAN_API_KEY as needed, and manually remove /tmp/scan_*.png outputs after use, especially for IDs, invoices, bank cards, contracts, or other sensitive images.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:78
Finding

Command Injection Through Shell-Based Image Path Handling

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:78-93
Vulnerability Type: Command injection caused by interpolating a user-controlled file path into sh -c
Risk Level: High

Vulnerable Code

python
subprocess.run([
    "sh", "-c",
    "cat 'IMAGE_FILE_PATH' | python3 scripts/scan_filter.py --method METHOD_VALUE"
])

The alternative Base64 workflow also unnecessarily invokes a shell:

python
img_bytes = base64.b64decode("IMAGE_BASE64_DATA")
with tempfile.NamedTemporaryFile(delete=False, suffix=".bin") as f:
    f.write(img_bytes)
    tmp_path = f.name
subprocess.run([
    "sh", "-c",
    f"cat '{tmp_path}' | python3 scripts/scan_filter.py --method METHOD_VALUE"
])
os.unlink(tmp_path)

Technical Analysis

The Skill instructs the Agent to replace IMAGE_FILE_PATH with the user-supplied local image path and execute the resulting text through sh -c. Although subprocess.run receives a list, this does not prevent command injection because the list explicitly launches a command interpreter. The shell parses the entire third argument as shell syntax.

Wrapping the path in single quotes is insufficient. A file path containing a single quote can terminate the quoted string and introduce shell operators or additional commands. Consequently, the documentation's claim that list-style subprocess invocation avoids shell injection is incorrect for this execution pattern.

The Base64 workflow uses a Python-generated temporary path and therefore has a substantially lower direct injection risk, but the shell and cat process remain unnecessary. The local-file workflow is directly exploitable when an attacker can influence the image path supplied to the Agent.

Attack Path

  1. An attacker submits a request that identifies an image through a crafted local path containing a single quote and shell syntax.
  2. The Agent follows the mandatory instructions in SKILL.md and substitutes that value for IMAGE_FILE_PATH.
  3. The Agen ...[truncated 1183 chars]
Remediation
View remediation

Remediation Suggestions

Remove sh -c and cat entirely. Open the selected image directly and connect it to the child process through standard input:

python
from pathlib import Path
import subprocess

script_path = Path(__file__).resolve().parent / "scripts" / "scan_filter.py"

with open(image_path, "rb") as image:
    subprocess.run(
        [
            "python3",
            str(script_path),
            "--method",
            str(method),
        ],
        stdin=image,
        check=False,
    )

Additional hardening should include:

  1. Treat the path exclusively as data and never interpolate it into shell command text.
  2. Resolve the script using a trusted absolute path rather than relying on the current working directory.
  3. Continue restricting method to the documented integer allowlist.
  4. If path access should be constrained, resolve the requested path and enforce an allowlisted input directory.
  5. For Base64 input, pass decoded bytes directly through the input argument or a temporary file object without invoking a shell.
  6. Update the security documentation to avoid claiming that list arguments are safe when the invoked executable is a command interpreter.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/do_scan.py:24
Finding

API Key Exposed in Request URL Query String

Content
View full analysis

Vulnerability Details

File Location: scripts/do_scan.py:24-30
Vulnerability Type: Sensitive credential transmitted in a URL query parameter
Risk Level: Medium

Vulnerable Code

python
resp = requests.post(
    url=f"{Config.API_BASE}?api_key={Config.BDPAN_SPACE_TOKEN}",
    json=req_data,
    headers={
        "Content-Type": "application/json",
    },
    timeout=60
)

Technical Analysis

The request uses HTTPS and sends data to a fixed Baidu endpoint, so the credential and image are encrypted during normal network transit. However, the API key is appended to the URL as an api_key query parameter.

URLs are frequently captured by components outside the application's direct control, including:

  • Web-server access logs.
  • Reverse proxies and API gateways.
  • Network monitoring and application-performance systems.
  • Request tracing and error telemetry.
  • Debug logs and exception reports.

As a result, placing the credential in the URL unnecessarily expands the set of systems and personnel that may gain access to it. This violates secure secret-handling practices even though no explicit credential logging is implemented in the audited source.

Attack Path

  1. The Skill reads BDPAN_API_KEY from the environment.
  2. do_scan.py concatenates the key into the outbound request URL.
  3. A server, reverse proxy, gateway, or monitoring service records the complete URL.
  4. A person or compromised service with access to those records extracts the query parameter.
  5. The exposed key is reused to issue unauthorized requests to the API within the permissions and lifetime of that credential.

This path depends on URL logging by request infrastructure; the audited project itself does not explicitly write the URL to a local log.

Impact Assessment

Credential disclosure could allow unauthorized use of the associated Baidu scanning API. The precise impact depends on the API key's server-side permissions and scope, which are n ...[truncated 369 chars]

Remediation
View remediation

Remediation Suggestions

Use a provider-supported authentication header rather than a query parameter. For example, if supported by the API:

python
resp = requests.post(
    url=Config.API_BASE,
    json=req_data,
    headers={
        "Content-Type": "application/json",
        "Authorization": f"Bearer {Config.BDPAN_SPACE_TOKEN}",
    },
    timeout=Config.DEFAULT_TIMEOUT,
)

If the service uses a custom header, follow its documented header name instead of inventing one. Additional controls should include:

  1. Confirm the supported authentication mechanism with the API provider.
  2. Configure clients, proxies, gateways, and telemetry systems to redact authorization headers and query parameters.
  3. Avoid including complete request URLs or headers in errors returned to users.
  4. Scope the key to only the required scanning operation.
  5. Apply usage limits and expiration where supported.
  6. Rotate the existing key if it may already have appeared in infrastructure logs.
  7. If the provider mandates query-string authentication, suppress query-string logging at every intermediary and use a short-lived, narrowly scoped credential.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/file_saver.py:6
Finding

Sensitive Processed Images Stored Insecurely in Shared Temporary Storage

Content
View full analysis

Vulnerability Details

File Location: scripts/file_saver.py:6-13
Vulnerability Type: Unsafe temporary-file creation and indefinite retention of sensitive output
Risk Level: Medium

Vulnerable Code

python
def save_base64_image(base64_str: str) -> str:
    try:
        data = base64.b64decode(base64_str)
        tmp_dir = "/tmp"
        os.makedirs(tmp_dir, exist_ok=True)
        filename = f"scan_{uuid.uuid4().hex[:8]}.png"
        path = os.path.join(tmp_dir, filename)
        with open(path, "wb") as f:
            f.write(data)
        return path
    except:
        return ""

Technical Analysis

The Skill can process identity documents, bank cards, invoices, contracts, and other sensitive images. Successful API responses are decoded and written directly into the shared /tmp directory.

The implementation has several weaknesses:

  • It does not explicitly apply owner-only permissions such as mode 0600.
  • Effective permissions depend on the process umask.
  • It uses ordinary open(path, "wb") rather than atomic exclusive creation.
  • It retains only eight hexadecimal characters from the UUID, reducing the file-name namespace.
  • It does not place files inside an owner-only temporary directory.
  • It does not automatically delete output after consumption.
  • It decodes the server-provided Base64 response without enforcing a maximum decoded output size.

The documentation informs users that files remain until manually removed, but disclosure alone does not protect their confidentiality or availability.

Attack Path

A confidentiality attack can proceed as follows:

  1. A user submits a sensitive document for processing.
  2. The remote service returns a processed image.
  3. file_saver.py writes that image to /tmp/scan_XXXXXXXX.png.
  4. The file remains after processing completes.
  5. On a multi-user or otherwise shared runtime, another local principal discovers the file and reads it if effective permissions permit acc ...[truncated 1421 chars]
Remediation
View remediation

Remediation Suggestions

Create output using secure temporary-file primitives with explicit owner-only access:

python
import base64
import os
import tempfile

def save_base64_image(base64_str: str) -> str:
    data = base64.b64decode(base64_str, validate=True)

    if len(data) > 10 * 1024 * 1024:
        raise ValueError("Processed image exceeds the allowed size")

    fd, path = tempfile.mkstemp(prefix="scan_", suffix=".png")
    try:
        os.fchmod(fd, 0o600)
        with os.fdopen(fd, "wb") as output:
            output.write(data)
        return path
    except Exception:
        os.close(fd)
        try:
            os.unlink(path)
        except OSError:
            pass
        raise

Further hardening should include:

  1. Prefer an application-specific temporary directory created with mode 0700.
  2. Use exclusive, atomic file creation.
  3. Enforce a maximum Base64 and decoded response size before writing.
  4. Validate that the decoded output is a supported image format.
  5. Establish a short retention period and delete files automatically after use.
  6. Provide an explicit cleanup operation for callers that need temporary path access.
  7. Avoid broad exception suppression so storage failures can be diagnosed without exposing sensitive image data.
  8. Retain full-strength random identifiers if application-generated names are used.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 206)May include surrounding context.

md
- `SKILL.md` — 本文档(意图分析 + 通用规范)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly requires environment access, network communication, and shell execution via metadata and documented subprocess usage, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization boundary gap: a host may grant broader capabilities than users expect, increasing the risk of unintended command execution, secret access, and external data exfiltration when processing untrusted inputs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The instruction to return results exactly as-is, without translation, combined with the rest of the skill being entirely Chinese, effectively enforces a single language/locale for user-visible output. The file does not offer any opt-in or alternative language behavior, which may violate language-choice policy.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/do_scan.py (reported line 24)May include surrounding context.

python
"image_base64": image_b64,
    }
    try:
        resp = requests.post(
            url=f"{Config.API_BASE}?api_key={Config.BDPAN_SPACE_TOKEN}",
            json=req_data,
            headers={

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script transmits full base64-encoded image content to an external API without any in-script disclosure, consent prompt, or privacy notice. Because this tool processes documents and images that may contain sensitive personal or business data, silent exfiltration to a third party can create privacy, compliance, and data-handling risk even if the remote API is legitimate.

Content

No source excerpt is available for this finding.

Tainted flow: 'req_data' from sys.stdin.read (line 17, user input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/do_scan.py (reported line 24)May include surrounding context.

python
"image_base64": image_b64,
    }
    try:
        resp = requests.post(
            url=f"{Config.API_BASE}?api_key={Config.BDPAN_SPACE_TOKEN}",
            json=req_data,
            headers={

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/scan_filter.py (reported line 110)May include surrounding context.

python
]

    # 执行(无shell注入风险,base64 via stdin 绕过参数长度限制)
    result = subprocess.run(
        cmd_args,
        input=image_b64,
        capture_output=True,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The file includes natural-language text in Chinese only, which imposes a specific language without any opt-in or explanation of a locale-specific requirement. Under the policy, language constraints should be optional or clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The request URL includes Config.BDPAN_SPACE_TOKEN, indicating use of a credential during outbound network access. The script provides no visible notice, prompt, or documentation comment warning that configured credentials will be used for the operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The function decodes caller-provided base64 content and writes it to /tmp as a PNG file, but there is no confirmation prompt, log/print statement, or explanatory comment/docstring disclosing that a file will be created on disk. For a code file, this is a safety-relevant file write lacking visible user disclosure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language docstring forces a specific language for documentation in this file and does not provide any opt-in or alternative language. Under the stated policy, language-specific instructions or documentation without user choice can be a locale policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.