Back to skill

Security audit

pdf_to_word

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended for cloud PDF-to-Word conversion, but it uploads local files and the SCNet API token to a configurable remote endpoint without strong destination or file-type safeguards.

Install only if you are comfortable sending selected documents to SCNet. Use it only on non-sensitive PDFs, keep the API base set to the official HTTPS SCNet endpoint, protect the API key, and confirm the exact file path before each run.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.py:131
Finding

Unrestricted API Endpoint Can Exfiltrate the API Token and Uploaded Documents

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:276
Finding

Insufficient Input Validation Allows Arbitrary Readable Files to Be Uploaded

Content
View full analysis
") print("Available ocrType value: PDF_TO_WORD") sys.exit(1) ocr_type = sys.argv[1] file_path = sys.argv[2] if ocr_type not in SUPPORTED_TYPES: sys.exit( f"Unsupported ocrType '{ocr_type}'. " f"Available values: {', '.join(SUPPORTED_TYPES.keys())}" ) if not os.path.isfile(file_path): sys.exit(f"File does not exist: {file_path}") config = load_config() sys.stderr.write( "Data security warning: this operation uploads the specified local " "file to the external SCNet service for processing." ) task_id = submit_task(ocr_type, file_path, config) ``` The original implementation performs only this effective validation: ```python if not os.path.isfile(file_path): sys.exit(f"错误: 文件不存在 - {file_path}") ``` ### Technical Analysis The Skill documentation states that `PDF_TO_WORD` accepts a PDF input, but the implementation only verifies that the supplied path refers to a file. It does not: - Require a `.pdf` extension. - Verify the PDF magic signature. - Confirm that the detected MIME type is `application/pdf`. - Reject symbolic links. - Restrict the file to an approved directory. - Confirm the resolved path immediately before upload. `mimetypes.guess_type()` is later used only to label the multipart upload. It does not enforce the content type and is based primarily on the filename. Because an Agent can receive file paths through natural-language requests, prompt manipulation, ambiguity, or ordinary mistakes may cause a sensitive non-PDF file to be supplied. Any file readable by the Skill's operating-system identity can then be ...[truncated 1234 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:78
Finding

Unpinned Dependency Installation Produces a Non-Reproducible Supply Chain

Content
View full analysis
Remediation
View remediation
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 (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The metadata/description understates critical behavior: the skill claims PDF/image conversion, but the documented invocation only supports PDF_TO_WORD and, more importantly, the top-level description does not clearly disclose that local files are uploaded to a third-party service using an API key from local configuration. This mismatch can cause users or orchestrators to trigger the skill under false assumptions, leading to unintended exfiltration of local document contents and use of stored credentials.

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 75)May include surrounding context.

md
def load_config():
    """从 .env 文件加载配置,若文件不存在则抛出友好错误"""
    config_from_env = {}
    for key in ["SCNET_API_KEY", "SCNET_API_BASE", "SCNET_POLL_INTERVAL", "SCNET_MAX_POLL_TIME"]:
        value = os.environ.get(key)

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 145)May include surrounding context.

md
def load_config():
    """从 .env 文件加载配置,若文件不存在则抛出友好错误"""
    config_from_env = {}
    for key in ["SCNET_API_KEY", "SCNET_API_BASE", "SCNET_POLL_INTERVAL", "SCNET_MAX_POLL_TIME"]:
        value = os.environ.get(key)

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 37)May include surrounding context.

python
def load_config():
    """从 .env 文件加载配置,若文件不存在则抛出友好错误"""
    config_from_env = {}
    for key in ["SCNET_API_KEY", "SCNET_API_BASE", "SCNET_POLL_INTERVAL", "SCNET_MAX_POLL_TIME"]:
        value = os.environ.get(key)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file appears to be a generic GitLab README template rather than a skill description, and it never defines when or how the skill should be invoked. For a skill-facing README, the absence of explicit trigger phrases, scope constraints, or exclusion conditions leaves activation behavior ambiguous.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

As a markdown file describing a skill, this README provides no actual description of what the 'pdf_to_word' skill does, including whether it uploads files, writes output files, or handles sensitive document contents. Because document-conversion workflows can affect user data and privacy, the lack of any warning or disclosure is a notable omission.

Content

No source excerpt is available for this finding.

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 declares capabilities that involve reading local files, accessing environment-based credentials, invoking shell/Python, and sending data over the network, but it does not define any explicit tool scope or permission boundaries. In an agent environment, this weakens reviewability and can allow the skill to be invoked with broader powers than users or operators expect, especially since it uploads local documents to an external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This skill is designed to transmit user-specified local files to https://api.scnet.cn/api/llm/v1 for processing. External transmission is expected for the feature, but it remains a real security risk because uploaded documents may contain sensitive data and leave the local trust boundary.

Content

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

md
SCNET_API_KEY=your_scnet_api_key_here

# API 基础地址(一般无需修改)
SCNET_API_BASE=https://api.scnet.cn/api/llm/v1

# 轮询配置(可选)
SCNET_POLL_INTERVAL=5

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill says the AI may auto-trigger based on broad description keywords for requests like '帮我把这份 PDF 转成 Word', without defining strict activation boundaries or mandatory structured consent checks. In a tool-using agent, broad matching increases the chance of accidental invocation on user messages that mention files or conversion, causing unintended local file upload to an external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · config/.env.example (reported line 6)May include surrounding context.

text
SCNET_API_KEY=your_scnet_api_key_here

# API 基础地址(一般无需修改)
SCNET_API_BASE=https://api.scnet.cn/api/llm/v1

# 轮询配置(可选)
SCNET_POLL_INTERVAL=5

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation instructs users to submit local files or file URLs to a third-party remote conversion service, but it does not disclose that document contents will leave the local environment and be processed externally. This creates a real privacy and data-handling risk, especially for sensitive PDFs, because users may unknowingly transmit confidential material to an external provider.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file_url parameter accepts publicly accessible document links, but the documentation does not warn that using public URLs can expose documents to unintended parties and to the service operator. Users may assume URL submission is safer than upload when in fact it can widen access and leak sensitive files if links are guessable, long-lived, or broadly shared.

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 59)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 122)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
60% 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 · SKILL.md (reported line 124)May include surrounding context.

md
)
        sys.exit(error_msg)

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

    try:
        config.setdefault('SCNET_POLL_INTERVAL', str(DEFAULT_POLL_INTERVAL))

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/api-docs.md (reported line 76)May include surrounding context.

md
)
        sys.exit(error_msg)

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

    try:
        config.setdefault('SCNET_POLL_INTERVAL', str(DEFAULT_POLL_INTERVAL))

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/api-docs.md (reported line 85)May include surrounding context.

md
)
        sys.exit(error_msg)

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

    try:
        config.setdefault('SCNET_POLL_INTERVAL', str(DEFAULT_POLL_INTERVAL))

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/main.py (reported line 95)May include surrounding context.

python
)
        sys.exit(error_msg)

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

    try:
        config.setdefault('SCNET_POLL_INTERVAL', str(DEFAULT_POLL_INTERVAL))

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill behavior does not match a typical local 'PDF 转 Word' expectation: it uploads the user-supplied file to a third-party SCNet API and returns remote task metadata/results instead of producing a local converted document. This is dangerous because users may disclose sensitive local documents under the assumption of local-only processing, creating a transparency and data-exfiltration risk even though the script does print a warning before upload.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This code sends task identifiers to an external SCNet service over the network. In context, the broader skill already uploads local files to the same service, so the external transmission is intentional but still security-relevant because document content and associated metadata leave the local trust boundary.

Content

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

python
payload = {"task_ids": task_ids}

    try:
        response = requests.post(url, headers=headers, json=payload, timeout=60)
    except Exception as e:
        sys.exit(f"网络请求失败: {str(e)}")

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest description is written entirely in Chinese and presents the skill behavior only in that locale, with no indication that users can choose another language or that the skill is intended solely for a Chinese-language audience. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The entire skill documentation is presented only in Chinese, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking or region-specific audience. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.