Back to skill

Security audit

Household Book Ocr

Security checks for vulnerabilities and agentic risk

Overview

This is a cloud OCR skill for household-register documents, but it deserves Review because it can upload sensitive identity documents and an API token to a configurable external endpoint without a clear per-upload consent boundary.

Install only if you are comfortable uploading household-register images or PDFs to Scnet's cloud OCR service. Keep SCNET_API_BASE fixed to the documented Scnet HTTPS endpoint, do not paste the API key into chat, use a dedicated environment with pinned dependencies if possible, and confirm with the agent before each document upload.

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

Error
Location
scripts/main.py:78
Finding

Unrestricted OCR API Endpoint Can Exfiltrate Identity Documents and API Credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:78-112
Vulnerability Type: Arbitrary sensitive-data transmission endpoint
Risk Level: High

Vulnerable Code

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)

Technical Analysis

The SCNET_API_BASE configuration value is used directly to construct the upload destination. The code does not validate:

  • The URL scheme, allowing plaintext HTTP.
  • The destination hostname.
  • The destination port.
  • Embedded URL credentials.
  • Whether the final request destination remains the documented Scnet service.

The resulting request contains both an Authorization: Bearer API credential and the complete user-selected document. Household-register documents may contain names, addresses, dates of birth, identification numbers, family relationships, and other sensitive identity information.

Uploading a document to t ...[truncated 2076 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove SCNET_API_BASE configurability if alternate service endpoints are not operationally required.
  2. If configurability is required, parse the URL with urllib.parse.urlparse and enforce all of the following:
    • Scheme must be https.
    • Hostname must be an explicit allowlisted hostname such as api.scnet.cn.
    • Port must be absent or equal to 443.
    • Username and password URL components must be absent.
    • The base path must match the expected API prefix.
  3. Construct the endpoint from a fixed origin and fixed path rather than concatenating an unrestricted string.
  4. Set allow_redirects=False, or manually process redirects and revalidate every destination before transmitting a document or credential.
  5. Fail closed when URL validation is unsuccessful.
  6. Clearly notify users that the selected document will be uploaded to the named third-party service and obtain confirmation before transmitting identity documents.
  7. Consider displaying the validated destination hostname before the upload without logging the bearer token or document contents.
  8. Add tests covering HTTP URLs, unexpected hosts, embedded credentials, alternate ports, malformed URLs, and redirects.

T08 · Insecure Dependencies

Note
Location
SKILL.md:60
Finding

Unpinned Python Dependency Installation Creates Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:60-65
Vulnerability Type: Unpinned third-party dependency
Risk Level: Low

Vulnerable Code

markdown
### 依赖安装

本技能需要 Python 3.6+ 和 requests 库。请运行以下命令:

```bash
   pip install requests
text

### Technical Analysis

The installation instructions request the latest package version resolved under the name `requests`, without a version constraint, lock file, or package hash. Although `requests` is a well-known package and the audit found no evidence of typosquatting or an intentionally malicious dependency, this installation process is not reproducible.

A future compromised, malicious, or incompatible release of the package or one of its transitive dependencies could be selected automatically. Depending on package format and installer behavior, package installation may process build metadata or execute build-related code. Unpinned versions also allow behavior to change after the Skill itself has been reviewed.

### Attack Path

1. A package or transitive dependency available from the configured Python package index is compromised, or a future release introduces malicious installation or runtime behavior.
2. A user follows the documented `pip install requests` command.
3. Pip resolves the then-current package and dependency versions because no reviewed versions or hashes are specified.
4. The unreviewed component is installed into the user's Python environment.
5. Malicious behavior may occur during supported build/install processing or when the Skill imports and uses the affected package.

Exploitation depends on compromise of the configured package source or a selected dependency release; no such compromise was identified in the audited repository.

### Impact Assessment

Potential impact is limited by the privileges of the user or environment running pip. In a compromised-package scenario, consequences could include:

- Code execution in the ins
...[truncated 406 chars]
Remediation
View remediation

Remediation Suggestions

  1. Add a reviewed requirements file with exact dependency and transitive-dependency versions.
  2. Record cryptographic hashes and install with:
    bash
    pip install --require-hashes -r requirements.txt
    
  3. Generate the locked dependency set from a trusted package index and retain the source/index configuration.
  4. Periodically update pinned versions after vulnerability scanning and compatibility review.
  5. Prefer installation inside a dedicated virtual environment rather than a privileged or system-wide Python environment.
  6. Document supported Python versions and test the locked dependency set against each supported version.
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 (20)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation does not clearly warn that local image files will be transmitted to an external OCR provider. Given that household registers contain highly sensitive personal information, failing to disclose this outbound data flow can lead to users unknowingly sending regulated or private identity data to a third party.

Content

No source excerpt is available for this finding.

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 57)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 119)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 appears to require file access, network access, and shell execution, but the manifest does not declare any tool scope or permission boundaries. This makes the skill harder to govern safely and increases the risk of unintended data access or outbound transmission, especially since it processes local files and sends data to an external OCR API.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest description says the skill can OCR general image text and household register information, but the body documents only household register recognition. This mismatch can cause the agent to invoke the skill for broader image OCR tasks than intended, increasing the chance that unrelated or sensitive documents are sent to the external provider.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The skill is configured to send data to an external API endpoint, which creates an external transmission path for local document contents. In this context the transmitted files are household register images, making the privacy risk significant even if the endpoint is legitimate and expected.

Content

Scanner excerpt · SKILL.md (reported line 49)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
89% confidence
Finding

The activation guidance is broad enough that an agent could auto-trigger the skill whenever a user mentions OCR or an image path, without a clear boundary on document type or privacy sensitivity. Because the skill reads local files and sends content to a third-party service, overbroad triggering materially increases the risk of unintended exfiltration of personal documents.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The configuration section reiterates use of the external OCR API, confirming that the skill depends on sending potentially sensitive document data off-host. The danger is heightened by the nature of the data processed, not by the mere presence of a URL alone.

Content

Scanner excerpt · SKILL.md (reported line 101)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
87% confidence
Finding

The file documents an external endpoint for OCR processing, which means uploaded images are transmitted outside the local trust boundary to api.scnet.cn. In the context of a household-register OCR skill, that external transmission is particularly sensitive because the payload can contain government identity documents and extensive personal data.

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 clients to upload household register images and OCR them via a third-party remote service, but provides no warning that this transmits highly sensitive personal data off-platform. Because the sample response includes identity and demographic fields such as full name, ID number, birth date, address-related data, religion, and marital status, users or integrators may unknowingly expose regulated personal information to an external processor.

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

The code is explicitly configured to communicate with an external endpoint at api.scnet.cn and uploads user files there for processing. External transmission is expected for a cloud OCR skill, but in this context it is security-relevant because the files may be household registration documents containing sensitive PII.

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

The script sends a user-supplied image file to a third-party OCR service, but there is no explicit user-facing consent or warning at the point of transmission. Because this skill is specifically designed to process household registration documents, the uploaded content may contain highly sensitive personal data, making undisclosed off-device transfer a real privacy and security risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file uses Chinese for its headings and substantive release notes, which may force a specific language on users without opt-in. The stated policy requires flagging language or locale constraints unless the file offers a choice or clearly justifies the locale restriction.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The parameter table states ocrType must be HOUSEHOLD_REGISTER and the skill is for household register recognition, but the command-line example passes '/path/to/invoice.jpg'. This actively conflicts with the documented intent and can mislead users about the skill's actual purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

Natural-language strings throughout the file, including the module description, errors, warnings, and CLI usage, are presented only in Chinese. Under the locale-policy rule, forcing a specific language without user opt-in can be a policy violation unless the locale constraint is explicitly documented and justified as region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.