Back to skill

Security audit

GIS 校招监控

Security checks for vulnerabilities and agentic risk

Overview

This skill is domain-aligned but materially overstates live monitoring capabilities and includes under-scoped scheduled messaging and file-write behavior.

Review this skill before installing if you expect reliable live job monitoring. It appears to provide mostly static examples, and scheduled DingTalk delivery or file output should only be enabled after confirming the exact recipient, schedule, output path, and how to stop or clean up the job.

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

Warning
Location
scripts/search-jobs.py:149
Finding

Arbitrary File Overwrite Through User-Controlled Output Path

Content
View full analysis

Vulnerability Details

File Location: scripts/search-jobs.py, lines 149-150 and 160-188
Vulnerability Type: Arbitrary file overwrite
Risk Level: Medium

Technical Analysis

The --output command-line argument accepts an unrestricted filesystem path. That path is passed directly to open() in write mode without validating that it is inside an approved output directory, checking whether it is a symbolic link, or preventing replacement of an existing file.

Relevant code:

python
def save_to_file(content, filepath):
    """保存结果到文件"""
    with open(filepath, 'w', encoding='utf-8') as f:
        f.write(content)
python
parser.add_argument('--output', type=str, default=None, help='输出文件路径')
python
if args.output:
    save_to_file(output, args.output)
    print(f"结果已保存到:{args.output}")
else:
    print(output)

Python's open(filepath, 'w') truncates an existing regular file. It also follows symbolic links. Consequently, anyone able to influence the script arguments can overwrite any file writable by the account running the skill.

This issue is particularly significant if an automation service invokes the script with elevated privileges or constructs --output from untrusted user input.

Attack Path

  1. An attacker gains control over, or injects content into, the value supplied to --output.
  2. The attacker selects an existing file writable by the skill process, such as a workspace configuration file:
    bash
    python scripts/search-jobs.py --output /path/to/writable/configuration
    
  3. save_to_file() opens that path using w mode.
  4. The original file is truncated and replaced with the generated report.
  5. Alternatively, where the attacker can create a symbolic link in an output location, the link can point to another process-writable target and open() will follow it.

Exploitation does not permit writing arbitrary attacker-selected conte ...[truncated 897 chars]

Remediation
View remediation

Remediation Suggestions

  • Restrict generated files to a dedicated project-controlled output directory.
  • Resolve the requested path with pathlib.Path.resolve() and verify that it remains beneath the approved directory.
  • Reject absolute paths and traversal components such as .. if arbitrary relative names are supported.
  • Refuse to overwrite existing files unless the caller supplies an explicit, trusted overwrite option.
  • Defend against symbolic-link attacks by using operating-system flags such as O_NOFOLLOW, where available.
  • Create files atomically with restrictive permissions, then rename them into place.
  • Run the skill under a dedicated unprivileged account with access only to its own data directory.

Example validation pattern:

python
from pathlib import Path

OUTPUT_DIR = (Path(__file__).resolve().parents[1] / "output").resolve()

def save_to_file(content, filename):
    OUTPUT_DIR.mkdir(mode=0o700, parents=True, exist_ok=True)
    target = (OUTPUT_DIR / filename).resolve()

    if OUTPUT_DIR not in target.parents:
        raise ValueError("Output path is outside the approved directory")
    if target.exists() or target.is_symlink():
        raise FileExistsError("Refusing to overwrite an existing output")

    target.write_text(content, encoding="utf-8")

T09 · Insecure Skill Coding Practices

Note
Location
scripts/generate_report.py:225
Finding

Predictable Hard-Coded Write Into the Root OpenClaw Workspace

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_report.py, lines 225-227
Vulnerability Type: Unsafe privileged and non-project-local file write
Risk Level: Low

Technical Analysis

The report generator uses a fixed absolute path beneath /root/.openclaw/workspace and creates its parent directories before saving the document:

python
output_path = '/root/.openclaw/workspace/references/gis-jobs-daily-20260324.docx'
os.makedirs(os.path.dirname(output_path), exist_ok=True)
doc.save(output_path)

This behavior assumes the process runs as root, reaches outside the skill's project directory, and replaces the same predictable target on every execution. It does not check whether the target already exists or is a symbolic link.

Writing into a privileged agent workspace violates least-scope storage expectations for a report-generation task. The predictable destination can also create a link-following overwrite condition if another actor can modify the destination directory. The latter depends on filesystem permissions and is not independently proven by the project.

Attack Path

A direct attack requires the attacker to have write access to the destination directory or target:

  1. The attacker creates or replaces /root/.openclaw/workspace/references/gis-jobs-daily-20260324.docx with a symbolic link to another file writable by the report process.
  2. A privileged automation process runs generate_report.py.
  3. doc.save(output_path) follows the filesystem path and writes the generated document to the linked target.
  4. The target is corrupted or replaced with DOCX content.

Even without an attacker-controlled symbolic link, repeated executions overwrite a predictable file in a global OpenClaw workspace and can modify state outside the installed skill directory.

Impact Assessment

The effective privileges are those of the process executing the generator. Because the destinatio ...[truncated 680 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the hard-coded /root/.openclaw/workspace destination.
  • Default to a project-local output directory or an explicitly configured per-user data directory.
  • Do not require or recommend execution as root.
  • Generate unique filenames or require explicit confirmation before replacing an existing report.
  • Resolve and validate the destination before writing.
  • Reject symbolic-link targets and use atomic file creation with restrictive permissions.
  • Pass the output directory through a trusted configuration boundary rather than embedding an account-specific absolute path.

A safer default would derive the destination from the project location:

python
from pathlib import Path

output_dir = Path(__file__).resolve().parents[1] / "output"
output_dir.mkdir(mode=0o700, parents=True, exist_ok=True)

output_path = output_dir / "gis-jobs-daily-20260324.docx"
if output_path.exists() or output_path.is_symlink():
    raise FileExistsError(f"Refusing to overwrite: {output_path}")

doc.save(str(output_path))
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents this as a monitoring/search skill that can track and regularly push the latest surveying/GIS campus recruitment postings, including filtering by employer type priority. However, the supplied code only generates a prewritten .docx daily report from static, hardcoded content. It does not query websites or APIs, monitor changes, ingest new job postings, apply runtime filters, or send scheduled pushes. While the report content is aligned with the recruiting domain and includes employer-priority sections, the primary behavior is document generation rather than job monitoring or notification. Therefore, the description materially overstates the implemented functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述的是一个信息监控/搜索/推送类技能,核心能力应包括获取最新招聘信息、按条件筛选、持续监控以及可能的定时推送。但实际代码只是使用 python-docx 创建一份固定内容的 Word 文档,生成日期、岗位内容、来源说明、建议和输出路径均为硬编码。本地文件写入本身可视为报告生成的实现细节,但代码缺少与声明主功能相匹配的任何外部查询、网络访问、监控逻辑、调度机制或推送行为。因此其实际主要用途更像是“生成静态校招日报模板/文档”,与声明的“搜索、监控、定期推送最新校招岗位”存在实质性不符。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill describes writing scraped job results to references/latest-jobs.md and invoking external tooling, but it does not declare any explicit tool scope or permissions. In an agent environment, missing least-privilege boundaries can allow broader-than-expected file write or tool use if the runtime infers capabilities, increasing the blast radius of prompt injection or misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill instructs creation of a recurring DingTalk cron job that delivers automated messages to a user channel, but it does not include an explicit user-facing consent/notice model for ongoing scheduled delivery and data transmission. This can lead to unexpected persistent messaging, accidental spam, or sending data to the wrong recipient/channel if configured incorrectly.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The docstring says this is a '日报生成脚本' for campus job information, which implies assembling a current daily report. However, the body uses hard-coded report dates, generation time, and job entries, with no dynamic inputs or data retrieval, so the documentation overstates what the script actually does. This is an intent-level contradiction, not just missing detail.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill manifest says the skill is for searching, monitoring, filtering, and scheduled pushing of latest GIS-related recruitment information. In this file, the code does not perform any collection, monitoring, filtering, or update logic; it simply builds a prewritten .docx document with fixed content and dates. That is a semantic mismatch between the claimed monitoring capability and the actual implemented behavior in this script.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest says the skill is for searching, monitoring, and periodically pushing the latest GIS-related campus recruitment information with prioritization filters. In this file, the code only constructs a static .docx document with prewritten content and fixed dates, without any logic to search sources, monitor updates, or obtain fresh job data.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The function docstring says it creates a campus-job daily report, which implies producing a current report based on daily information. However, the body writes a static report for a fixed date with hard-coded employers, notes, and platform summaries, so the documentation overstates what the function actually does.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill states that scraped job results are saved to a local file, but it does not warn users that data will be stored locally or define retention/cleanup behavior. Even if the content is low sensitivity, undisclosed local persistence can expose stale or unintended data to later sessions, users, or tools on the same environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The entire markdown file is written in Chinese and does not indicate that language selection is optional or that the content is intentionally limited to a Chinese-speaking audience. Under the policy rule for natural-language violations, forcing a specific language without user opt-in can be a locale-policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This markdown file contains only Chinese-language content and does not provide any user opt-in, alternative language option, or justification for enforcing a single language. Under the stated policy, forcing a specific language without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file presents all user-facing content in Chinese and does not indicate that the skill is region-specific or that users can opt into another language. Under the stated policy, forcing a specific language without user choice can be a natural-language policy violation.

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’s user-facing natural language is entirely Chinese, including the module description and command-line help text, and there is no indication that users can opt into another language. Under the stated policy, forcing a specific language without user choice can be a locale-policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.