Back to skill

Security audit

GTYT Reconcile (共同赢账单 vs 到货单对账)

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to do the advertised reconciliation work, but it handles sensitive business spreadsheets with under-scoped local staging and outbound delivery.

Review before installing. Use it only with reconciliation files you are comfortable staging locally and sending through Feishu, run it as an unprivileged user, and prefer an explicit private output directory instead of the default /tmp path.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run_full.py:24
Finding
Predictable Files in a Shared Temporary Directory Allow Symlink-Based File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_full.py:24-29`, `scripts/parse_tables.py:177-178`, `scripts/build_diff_report.py:170`, and `scripts/mark_bill_diff.py:70` **Vulnerability Type**: Unsafe temporary-file handling and symlink-following file writes **Risk Level**: Medium ### Vulnerable Code `scripts/run_full.py:24-29` selects the shared `/tmp` directory by default and constructs predictable output names: ```python out_dir = os.path.abspath(sys.argv[3]) if len(sys.argv) > 3 else '/tmp' os.makedirs(out_dir, exist_ok=True) here = os.path.dirname(os.path.abspath(__file__)) parsed_json = os.path.join(out_dir, 'gtyt_parsed.json') diff_xls = os.path.join(out_dir, '两表金额差异对比.xls') ``` The generated JSON is opened for writing without exclusive creation or protection against symbolic links in `scripts/parse_tables.py:177-178`: ```python with open(out_path, 'w', encoding='utf-8') as f: json.dump(output, f, ensure_ascii=False, indent=2) ``` The generated report is saved directly to the predictable path in `scripts/build_diff_report.py:170`: ```python wb.save(out_path) ``` The marked bill is likewise saved directly to its predictable path in `scripts/mark_bill_diff.py:70`: ```python wbcopy.save(out_path) ``` ### Technical Analysis The workflow defaults to a globally writable directory and uses deterministic filenames. It does not create a private per-run directory, verify that destination paths are regular files, reject symbolic links, or use exclusive file creation. On systems where `/tmp` is writable by multiple users, another local user can create a symbolic link at one of the expected output paths before the workflow runs. Standard write operations generally follow symbolic links. Consequently, the process may truncate and overwrite the link target using the privileges of the account running the Skill. The vulnerable paths include: - `/tmp/gtyt_parsed.json` - `/tmp/两表金额差异对比.xls` - `/tmp/共同赢<month>账单-上海-已标差异.xls` The month ...[truncated 1889 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Use a private directory for every run.** Create it with `tempfile.mkdtemp()` or `tempfile.TemporaryDirectory()` rather than writing predictable files directly under `/tmp`: ```python import tempfile out_dir = ( os.path.abspath(sys.argv[3]) if len(sys.argv) > 3 else tempfile.mkdtemp(prefix='gtyt-reconcile-') ) os.chmod(out_dir, 0o700) ``` 2. **Avoid predictable temporary filenames.** Use `tempfile.NamedTemporaryFile` or randomized names inside the private directory. 3. **Reject symbolic-link destinations.** Before replacing a caller-selected output, use `os.lstat()` to detect symbolic links. Where supported, open files using `os.open()` with `O_NOFOLLOW`, `O_CREAT`, and `O_EXCL`. 4. **Write and publish atomically.** Generate each file in a private temporary directory, flush and close it, and then use `os.replace()` to publish it to an approved destination. Ensure the destination directory is trusted and not writable by untrusted users. 5. **Validate caller-supplied output directories.** Require the directory to be owned by the executing user and reject globally writable directories unless they have appropriate isolation and a private child directory is created. 6. **Run with least privilege.** The reconciliation process should not execute as `root` or another privileged service account. Restrict its filesystem permissions to the input and designated output directories. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill advertises executable workflow steps that invoke local Python scripts, write files, and use shell-style command entry points, but it does not declare corresponding permissions or capabilities. This creates a transparency and governance gap: an agent may perform file writes and command execution beyond what a reviewer or user expects, increasing the chance of unintended filesystem modification or misuse if the surrounding platform auto-trusts undeclared behavior.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill states that generated Excel reports will be sent via Feishu DM, but it does not prominently warn that potentially sensitive billing and receiving data will be copied out for delivery. In a financial reconciliation context, these files may contain store-level commercial data, so silent outbound transmission materially increases data leakage and privacy risk if triggered without explicit user understanding or confirmation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The workflow explicitly writes reports to /tmp and then copies them into /root/.openclaw/media/outbound/ before sending, but it gives no warning about local persistence of sensitive artifacts. Temporary and outbound staging directories can leave recoverable copies on disk, broadening exposure to other processes, operators, or later tasks even if the user only expected an in-memory transformation.

Missing User Warnings

Low
Confidence
86% confidence
Finding
Defaulting output to /tmp can expose sensitive billing and invoice artifacts in a shared or world-accessible temporary location, especially on multi-user systems or agent hosts processing data for different users. This skill handles financial reconciliation files and emits parsed JSON and marked spreadsheets, so persistence in /tmp increases confidentiality and data-retention risk.

Static analysis

No suspicious patterns detected.