Back to skill

Security audit

personal_card_ocr

Security checks for vulnerabilities and agentic risk

Overview

This OCR skill is mostly transparent about uploading sensitive documents to Scnet, but it should be reviewed because the executable can use an arbitrary configured API endpoint and does not enforce explicit consent before upload.

Install only if you are comfortable sending the selected documents to Scnet and you can control the local configuration. Before use, verify config/.env points to https://api.scnet.cn/api/llm/v1, do not process other people's documents without permission, and treat SCNET_API_KEY as sensitive. Prefer a version that hard-validates the API host and requires an explicit consent flag before upload.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.py:51
Finding

Unrestricted OCR API Endpoint Can Exfiltrate Sensitive Documents and API Credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py, lines 51-59 and 78-112
Vulnerability Type: Unvalidated configurable network destination
Risk Level: High

Vulnerable Code

python
with open(ENV_FILE, 'r', encoding='utf-8') as f:
    for line in f:
        line = line.strip()
        if not line or line.startswith('#'):
            continue
        if '=' in line:
            key, value = line.split('=', 1)
            key = key.strip()
            value = value.strip().strip('"').strip("'")
            config[key] = value
python
config.setdefault('SCNET_API_BASE', 'https://api.scnet.cn/api/llm/v1')
return config
python
api_base = config['SCNET_API_BASE']
api_key = config['SCNET_API_KEY']
url = f"{api_base}/ocr/recognize"

# Check whether the file exists
if not os.path.isfile(file_path):
    sys.exit(f"错误: 文件不存在 - {file_path}")

# Detect the MIME type
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
        )

Technical Analysis

The SCNET_API_BASE value is loaded verbatim from config/.env and used to construct the upload destination. The implementation does not parse or validate the URL, require HTTPS, or verify that its hostname is exactly api.scnet.cn.

This behavior conflicts with the declared network permission in skill.yaml, which restricts network requests to api.scnet.cn. At runtime, however, ...[truncated 2129 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove SCNET_API_BASE configurability if alternate service endpoints are not operationally necessary.
  2. If configurability is required, parse the endpoint with a standard URL parser and enforce all of the following:
    • The scheme must be exactly https.
    • The hostname must be exactly api.scnet.cn.
    • User-information components must be absent.
    • Unexpected ports must be rejected.
    • IP literals, redirects to other hosts, and suffix-confusion domains must be rejected.
  3. Construct the endpoint from a trusted constant rather than concatenating an arbitrary base URL.
  4. Disable or explicitly validate redirects so a trusted initial endpoint cannot redirect a credential-bearing upload to another host.
  5. Keep the runtime network policy aligned with the api.scnet.cn host restriction declared in skill.yaml.
  6. Add automated tests covering malicious values such as HTTP URLs, attacker domains, embedded credentials, unexpected ports, IP addresses, and deceptive subdomains.
  7. Document credential rotation procedures because any API key used while a malicious endpoint was configured must be treated as compromised.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:192
Finding

Sensitive Document Upload Proceeds Without Enforcing Explicit User Consent

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py, lines 192-200
Vulnerability Type: Missing affirmative consent enforcement for third-party data disclosure
Risk Level: Medium

Vulnerable Code

python
# --- User-visible warning ---
sys.stderr.write(
    "\n⚠️  隐私警告:本操作将读取您指定的本地图片,并通过 HTTPS 上传到 Scnet 第三方 OCR 服务(https://api.scnet.cn)。\n"
    "    图片中可能包含身份证、银行卡、护照、户口本等敏感信息,上传后将在 Scnet 服务器进行处理。\n"
    "    请确认您已了解上述风险并同意继续。建议仅上传当前任务所需的最小数据。\n\n"
)
# -------------------

config = load_config()
# Call the OCR function with retry support
recognize_with_retry(ocr_type, file_path, config)

Technical Analysis

The Skill documentation states that execution should occur only after the user explicitly agrees to upload the image to Scnet. The executable does not enforce that requirement. It prints a warning to standard error and then immediately loads the configuration and uploads the file.

There is no confirmation prompt, consent flag, signed invocation state, or other fail-closed control. Consequently, direct script invocation or an Agent integration that overlooks the natural-language instruction can upload a sensitive document without affirmative, contemporaneous authorization.

The warning is useful disclosure, but passive notification is not equivalent to explicit consent, particularly because the operation concerns government identity documents, banking records, passports, and similar sensitive material.

Attack Path

  1. An automation workflow, Agent, or user invokes main.py with an OCR type and local document path.
  2. The script writes a privacy warning to standard error.
  3. Execution does not pause or require any acknowledgement.
  4. The script reads the supplied file and uploads it to the configured OCR service.
  5. The document leaves the local system even if no explicit consent was collected by the caller.

Impact Assessment

The issue can result in unauthorized di ...[truncated 590 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require an explicit invocation flag such as --consent-to-scnet-upload.
  2. Fail closed before opening the file or loading credentials when the consent flag is absent.
  3. Require the calling Agent to explain the third-party destination and sensitive-data implications before supplying the flag.
  4. Where interactive use is supported, require a clear affirmative response rather than treating continued execution as consent.
  5. Avoid relying solely on an interactive prompt for automated environments; use an explicit machine-verifiable consent parameter.
  6. Record only minimal, non-sensitive consent metadata if auditing is required. Do not log document contents, credentials, or extracted personal information.
  7. Add tests confirming that no file is opened and no network request occurs when consent has not been explicitly supplied.
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

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 72)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 136)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"

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.yaml (reported line 45)May include surrounding context.

yaml
# --------------------

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
91% confidence
Finding

The skill performs sensitive actions—reading local files, invoking shell/Python, and sending data over the network—but does not declare any explicit tool scope or permission boundaries. In a skill that handles identity documents and other highly sensitive personal data, missing scope declarations weakens least-privilege controls and increases the chance of unintended file access or opaque data exfiltration.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The skill explicitly configures a remote API endpoint and is designed to upload locally supplied images for OCR processing by a third party. Because the supported images include IDs, passports, bank cards, household records, and other regulated personal documents, this is a real external transmission risk with potentially severe privacy and compliance consequences if users do not fully understand or control the transfer.

Content

Scanner excerpt · SKILL.md (reported line 64)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(仅所有者可读写)

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This finding again documents the use of the third-party Scnet API endpoint, confirming recurring network transmission of sensitive document images and extracted data. In this skill's context, the danger is elevated because the transmitted content can contain government IDs, financial information, and other high-value PII, making privacy exposure materially significant even if the behavior is intended and disclosed.

Content

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

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

### 输出

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This document enumerates a large set of highly sensitive personal and financial OCR output fields, including national ID numbers, bank card numbers, passport data, household registration details, and birth certificate information, without any adjacent guidance on consent, minimization, masking, retention, or safe handling. In the context of a skill that sends user-provided images to a third-party OCR service, the absence of privacy and data-handling warnings increases the risk of over-collection, accidental disclosure, unsafe logging, or downstream misuse of extracted PII.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The file documents transmission of user-provided images to an external OCR endpoint, which is a real data egress path. In this skill, the danger is elevated because the transmitted content can include government IDs, passports, bank cards, and similar highly sensitive documents, so any misuse, compromise, or inadequate disclosure can lead to serious privacy and compliance harm.

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
93% confidence
Finding

The documentation describes uploading identity documents and other highly sensitive personal records to a third-party OCR service but does not include any warning about the privacy, consent, and data-transfer implications. In this skill context, that omission is more dangerous because the supported inputs include IDs, passports, bank cards, household records, and other regulated personal data, so users may disclose sensitive material without informed consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring and all user-facing usage/output text are written exclusively in Chinese, and the script does not indicate that users may choose another language or that the tool is intentionally limited to a Chinese-only audience for compliance or regional reasons. Under the language/locale policy, forcing a specific language without opt-in is a natural-language policy concern.

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
96% confidence
Finding

This skill uploads user-specified local image files to an external OCR provider over the network, and those files may contain highly sensitive identity and financial documents. Even though the code warns the user and uses HTTPS, external transmission of PII to a third party materially increases confidentiality and privacy risk if consent is not properly enforced by the caller or if the endpoint is changed via configuration.

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):

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest description is written as an instruction and capability statement entirely in Chinese, with 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 violation unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The file is entirely written in Chinese, including the main heading and all release notes, with no indication that the skill is region-specific or that users can choose another language. Under the policy for natural-language violations, this can be a locale/language constraint imposed 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
92% confidence
Finding

This markdown file contains user-facing instructions, warnings, parameter descriptions, and invocation examples entirely in Chinese. Under the policy rule for natural-language violations, forcing a specific language without user opt-in can be a locale-policy issue when no justification or alternative language option is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The natural-language instructions and field descriptions are written entirely in Chinese, and the file does not indicate that this language restriction is optional or specific to a justified regional context. Per the policy rule, forcing a single language without opt-in can be a locale-policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The file presents all operational instructions and API details exclusively in Chinese, which can constitute a language-policy issue when no user opt-in or locale justification is provided. There is no indication that the skill is intentionally limited to a Chinese-speaking or region-specific audience.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.