Back to skill

Security audit

online_car_hailing_itinerary_ocr

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a legitimate remote OCR integration, but it can upload any readable local file to a configurable external endpoint without strong scoping or confirmation.

Review before installing. Use this only for documents you are comfortable sending to Scnet's OCR service, keep a dedicated SCNET_API_KEY in config/.env, do not pass paths supplied by untrusted prompts, and avoid changing SCNET_API_BASE unless the destination is explicitly trusted.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/main.py:91
Finding

Unrestricted Local File Upload to an External OCR Service

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py, lines 91-112
Vulnerability Type: Arbitrary local file disclosure through insufficient input validation
Risk Level: High

Technical Analysis

The filePath argument is accepted as long as it points to a regular file. The implementation does not verify that the supplied file is a supported image or PDF, inspect its content signature, reject symbolic links, enforce a maximum size, or restrict access to a user-approved directory.

The MIME type is inferred only from the filename. If it cannot be inferred, the file is uploaded as application/octet-stream. Consequently, any regular file readable by the Skill process can be transmitted to the configured OCR server.

python
# 检查文件是否存在
if not os.path.isfile(file_path):
    sys.exit(f"错误: 文件不存在 - {file_path}")

# 自动检测 MIME 类型
mime_type, _ = mimetypes.guess_type(file_path)
if mime_type is None:
    mime_type = 'application/octet-stream'

headers = {
    'Authorization': f'Bearer {api_key}'
}

try:
    with open(file_path, 'rb') as f:
        files = {
            'file': (os.path.basename(file_path), f, mime_type)
        }
        data = {
            'ocrType': ocr_type,
            'channelTag': "scnetSkills"
        }
        response = requests.post(url, headers=headers, data=data, files=files, timeout=60)

Uploading a user-selected document is necessary for the declared hosted OCR functionality. However, permitting arbitrary Agent-readable files exceeds the minimum file-access scope needed to process ride-hailing itinerary images and PDFs.

Attack Path

  1. An attacker or untrusted prompt persuades the Agent to invoke the Skill with a sensitive local path instead of a legitimate itinerary.
  2. The Skill checks only whether the path references a regular file.
  3. The Skill opens the file using the permissions of its host process.
  4. The complete file is placed in a m ...[truncated 689 chars]
Remediation
View remediation

Remediation Suggestions

  1. Allowlist only the file formats required by the OCR service, such as PDF, JPEG, and PNG.
  2. Validate the file's content signature rather than trusting its extension or inferred MIME type.
  3. Resolve the path with Path.resolve() and restrict it to an explicitly approved upload or workspace directory.
  4. Reject symbolic links and non-regular files, and verify the resolved file immediately before opening it.
  5. Enforce a conservative maximum file size before reading or uploading the file.
  6. Require explicit user confirmation that the selected file will be sent to a third-party OCR service.
  7. Clearly disclose the types of personal information potentially contained in itinerary documents and refer users to the service provider's retention and privacy terms.
  8. If arbitrary paths must be supported, use a trusted host-provided file-selection or attachment mechanism rather than accepting unverified prompt-derived paths.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:78
Finding

Unvalidated API Base URL Can Redirect Credentials and Documents

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py, lines 78-112
Vulnerability Type: Untrusted destination configuration for sensitive network transmission
Risk Level: Medium

Technical Analysis

The API base URL can be supplied through SCNET_API_BASE in the configuration file. The implementation uses that value directly to construct the request URL without validating the scheme, hostname, port, or path.

The request contains both the bearer API key and the complete document. A malicious or accidentally insecure configuration can therefore redirect both values to an attacker-controlled endpoint. In particular, an http:// base URL would transmit the credential and document without transport encryption.

python
config.setdefault('SCNET_API_BASE', 'https://api.scnet.cn/api/llm/v1')
return config

def recognize_with_retry(ocr_type, file_path, config, retry_count=0):
    """
    带重试机制的 OCR 识别函数。
    当遇到 429 (Too Many Requests) 时,自动等待后重试。
    调用 Scnet OCR API 进行识别"""
    api_base = config['SCNET_API_BASE']
    api_key = config['SCNET_API_KEY']
    url = f"{api_base}/ocr/recognize"

    # 检查文件是否存在
    if not os.path.isfile(file_path):
        sys.exit(f"错误: 文件不存在 - {file_path}")

    # 自动检测 MIME 类型
    mime_type, _ = mimetypes.guess_type(file_path)
    if mime_type is None:
        mime_type = 'application/octet-stream'

    headers = {
        'Authorization': f'Bearer {api_key}'
    }

    try:
        with open(file_path, 'rb') as f:
            files = {
                'file': (os.path.basename(file_path), f, mime_type)
            }
            data = {
                'ocrType': ocr_type,
                'channelTag': "scnetSkills"
            }
            response = requests.post(url, headers=headers, data=data, files=files, timeout=60)

A configurable endpoint may be useful for legitimate deployments, but unrestricted destination control is not nece ...[truncated 1304 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the endpoint to https://api.scnet.cn/api/llm/v1 when custom deployments are not required.
  2. If endpoint customization is necessary, parse the URL and require the https scheme.
  3. Maintain an explicit allowlist of trusted hostnames and approved ports.
  4. Reject URLs containing embedded credentials, fragments, unexpected paths, or nonstandard ports.
  5. Disable redirects for requests carrying credentials and files, or validate every redirect destination before following it.
  6. Separate credentials by destination so an SCNet token is never sent to a custom host.
  7. Protect config/.env with owner-only permissions and verify its ownership where supported.
  8. Display the resolved upload hostname and obtain confirmation before sending sensitive documents to a nondefault approved endpoint.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/main.py (reported line 20)May include surrounding context.

python
# 获取技能根目录(脚本所在目录的上一级)
SKILL_ROOT = Path(__file__).parent.parent.absolute()
ENV_FILE = SKILL_ROOT / "config" / ".env"

# --- 新增:重试配置 ---
MAX_RETRIES = 3            # 最大重试次数

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
# --------------------

def load_config():
    """从 .env 文件加载配置,若文件不存在则抛出友好错误"""
    if not ENV_FILE.exists():
        error_msg = (
            "\n===============================================\n"

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
# --------------------

def load_config():
    """从 .env 文件加载配置,若文件不存在则抛出友好错误"""
    if not ENV_FILE.exists():
        error_msg = (
            "\n===============================================\n"

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/main.py (reported line 29)May include surrounding context.

python
# --------------------

def load_config():
    """从 .env 文件加载配置,若文件不存在则抛出友好错误"""
    if not ENV_FILE.exists():
        error_msg = (
            "\n===============================================\n"

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · README.md (reported line 38)May include surrounding context.

md
* [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
* [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
* [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
* [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
* [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation indicates capabilities that can read local files, invoke shell commands, and send data over the network, but it does not declare any explicit tool scope or permission boundaries. In an agent environment, this increases the chance of over-broad execution, unintended file access, or silent transmission of local content to a remote service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill handles local document images and transmits them to a third-party OCR API, but the description does not clearly warn users that document contents leave the local environment. This is dangerous because receipts and itinerary images may contain personal, financial, or location data, and users may not realize they are authorizing external processing.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
78% confidence
Finding

This finding reflects explicit configuration of a remote API endpoint used to process OCR requests. External transmission is expected for the feature, but it is still a real security concern because local document images and extracted data may be sent off-host to a third party.

Content

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

SCNET_API_KEY=your_scnet_api_key_here

API 基础地址(一般无需修改)

SCNET_API_BASE=https://api.scnet.cn/api/llm/v1

text
2. 添加:`SCNET_API_KEY=你的密钥`
3. 设置文件权限为 600(仅所有者可读写)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation guidance is broad enough that a general request to 'recognize this image' may auto-trigger the skill without strong confirmation that the user intends remote OCR processing. Because the skill sends local image content to an external API, vague triggers can cause accidental disclosure of sensitive receipts or personal travel data.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
78% confidence
Finding

The documented default base URL confirms that the skill depends on external transmission to a third-party service. While this is likely intended functionality, it remains security-relevant because the skill processes local user-provided images that may contain sensitive travel or billing information.

Content

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

md
| 变量名 | 默认值 | 说明 |
|--------|--------|------|
| SCNET_API_KEY | 必需 | Scnet API 密钥 |
| SCNET_API_BASE | https://api.scnet.cn/api/llm/v1 | API 基础地址(一般无需修改) |

### 输出

External Transmission

Medium
Category
Data Exfiltration
Confidence
81% confidence
Finding

The file documents a direct POST to an external OCR service, which means uploaded images, PDFs, or archives containing itinerary records will be transmitted off-system to a third party. In this skill's context, those documents commonly contain personal and travel data, making the external transfer security-relevant even though the mere presence of a URL is not malicious by itself.

Content

Scanner excerpt · references/api-docs.md (reported line 4)May include surrounding context.

md
# Sugon-Scnet OCR API 文档摘要

## 接口地址
`POST https://api.scnet.cn/api/llm/v1/ocr/recognize`

## 请求头
- `Content-Type: multipart/form-data`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation instructs users to upload OCR source files to a remote third-party endpoint and the sample response includes extracted personal data such as a passenger phone number and trip details, but it does not warn users that sensitive documents and derived PII leave the local environment. In a receipt/OCR skill for ride-hailing itineraries, this omission can cause users or integrators to unknowingly transmit regulated or sensitive data to an external processor without informed consent, review, or data-handling safeguards.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/main.py (reported line 45)May include surrounding context.

python
"   b) 配置文件:\n"
            f"      mkdir -p {SKILL_ROOT}/config\n"
            f"      echo 'SCNET_API_KEY=你的密钥' > {ENV_FILE}\n"
            f"      chmod 600 {ENV_FILE}\n"
            "\n配置完成后重新运行。"
        )
        sys.exit(error_msg)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/main.py (reported line 152)May include surrounding context.

python
"   b) 配置文件:\n"
            f"      mkdir -p {SKILL_ROOT}/config\n"
            f"      echo 'SCNET_API_KEY=你的密钥' > {ENV_FILE}\n"
            f"      chmod 600 {ENV_FILE}\n"
            "\n配置完成后重新运行。"
        )
        sys.exit(error_msg)

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The skill is hardwired by default to send content to an external endpoint at api.scnet.cn, which means user documents leave the local environment. While external OCR is expected for this type of skill, it still constitutes a genuine security/privacy concern because itinerary images can contain personally identifiable information and trip details.

Content

Scanner excerpt · scripts/main.py (reported line 78)May include surrounding context.

python
)
        sys.exit(error_msg)

    config.setdefault('SCNET_API_BASE', 'https://api.scnet.cn/api/llm/v1')
    return config

def recognize_with_retry(ocr_type, file_path, config, retry_count=0):

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script uploads the user-supplied file to a third-party OCR service, but it does not present any explicit runtime notice, consent prompt, or privacy warning before transmitting potentially sensitive itinerary data. In the context of ride-hailing receipts, files may contain personal and financial information, so silent exfiltration to a remote API creates a real data exposure risk even if it is part of the intended functionality.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The changelog content is entirely in Chinese, including the title and feature description, with no indication that the skill is region-specific or that users can choose another language. This can violate language/locale policy when a skill presents user-facing content in a fixed language without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file’s user-facing documentation is entirely in Chinese and does not indicate that language selection is optional or 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.

Static analysis

No suspicious patterns detected.