Back to skill

Security audit

码虫日报watcher

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real daily-report monitor, but it automatically sends operational details to a hard-coded Feishu recipient and uses weak shared temporary state.

Review before installing. Only use this skill if the hard-coded workspace path, cron job ID, Feishu sender account, and Feishu recipient belong to your environment. Prefer changing the recipient and state location to explicit per-install configuration before running it on a shared or production machine.

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
watcher.py:56
Finding

Hard-Coded Feishu Recipient Can Cause Unauthorized Operational Data Disclosure

Content
View full analysis

Vulnerability Details

File Location: watcher.py:56, watcher.py:132, and watcher.py:235-241
Vulnerability Type: Hard-coded external recipient and unintended information disclosure
Risk Level: Medium

Vulnerable Code

python
RECIPIENT = "ou_991021547578f722d08533accc83651d"
python
result = send_post(title, lines, RECIPIENT)
python
detail_lines = [
    f"📅 检查时间:{now_iso}",
    f"📂 目标日报:{target_date}",
    f"🔴 异常原因:{reason}",
    f"📊 Cron 状态:status={last_run_status}, consecutive={consecutive_errors}",
    f"🔍 诊断信息:{last_diagnostic[:200] if last_diagnostic else '(无)'}",
    f"📁 文件路径:{report_path}",

Technical Analysis

The alert destination is an opaque Feishu user identifier embedded directly in the source code. It cannot be selected or verified by the operator through installation-specific configuration. Consequently, every deployment uses the same recipient regardless of who installs or operates the Skill.

Alert messages include cron status, diagnostic output, report dates, failure information, and an absolute local filesystem path. The project documentation identifies the sending account but does not clearly disclose that the destination itself is fixed. The implementation of the imported feishu_post module is outside the audited project, so its transport and recipient validation behavior could not be independently verified.

Attack Path

  1. An operator installs or invokes the Skill in a different OpenClaw environment without reviewing the embedded recipient identifier.
  2. The monitored cron task fails, reports unsuccessful delivery, or lacks the expected report file.
  3. The watcher constructs an alert containing operational diagnostics and local path information.
  4. send_post transmits the alert to the hard-coded Feishu recipient.
  5. If that identifier does not belong to the current operator, an unintended third party receives the informatio ...[truncated 700 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the recipient identifier from source code.
  2. Require the recipient through an explicit installation-specific configuration value or environment variable.
  3. Fail closed with a clear configuration error when no recipient is configured.
  4. Validate the configured identifier against the expected Feishu identifier format.
  5. Require an explicit confirmation or test message during installation so the operator can verify ownership of the destination.
  6. Minimize alert contents by removing absolute filesystem paths and sanitizing diagnostic text before transmission.
  7. Document what data is transmitted, which account sends it, and how the recipient is selected.
  8. Add automated tests confirming that no default third-party recipient is used.

T09 · Insecure Skill Coding Practices

Warning
Location
watcher.py:55
Finding

Predictable Shared Temporary State File Permits Symlink Attacks and Alert Suppression

Content
View full analysis

Vulnerability Details

File Location: watcher.py:55 and watcher.py:60-67
Vulnerability Type: Unsafe temporary file handling
Risk Level: Medium

Vulnerable Code

python
STATE_FILE = "/tmp/coding-advisor-daily-report-watcher-state.json"
python
def load_state():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE) as f:
            return json.load(f)
    return {"last_alert_at_ms": 0, "last_alert_reason": None}

def save_state(state):
    with open(STATE_FILE, "w") as f:
        json.dump(state, f)

Technical Analysis

The watcher stores security-relevant cooldown state at a fixed, predictable path in the globally shared /tmp directory. The file is opened through ordinary path-based operations without:

  • Symlink protection
  • File ownership or type validation
  • Restrictive creation permissions
  • Atomic replacement
  • Inter-process locking
  • Safe recovery from malformed JSON

Both read and write operations follow symbolic links. On a multi-user system, a local attacker can pre-create the path before the first watcher execution. A crafted JSON object containing a future last_alert_at_ms value can suppress alerts because the cooldown calculation treats the attacker-controlled timestamp as authoritative.

Alternatively, a symbolic link can direct save_state() to another file writable by the watcher account. Opening the link target with mode "w" truncates and replaces its contents with JSON. Malformed JSON can also cause load_state() to raise an exception, terminating the watcher through its top-level exception handler.

Attack Path

Alert suppression path:

  1. A local attacker gains write access to the shared /tmp directory, as is normal for local users.
  2. Before the watcher creates its state file, the attacker creates /tmp/coding-advisor-daily-report-watcher-state.json.
  3. The attacker writes valid JSON with last_alert_at_ms set ...[truncated 1549 chars]
Remediation
View remediation

Remediation Suggestions

  1. Store state in a private per-user state directory, such as a directory under $XDG_STATE_HOME, rather than directly under /tmp.
  2. Create the parent directory with mode 0700 and the state file with mode 0600.
  3. Open files using secure flags such as O_NOFOLLOW, O_CREAT, and O_CLOEXEC.
  4. Verify with lstat or fstat that the state object is a regular file owned by the expected user.
  5. Write to a securely created temporary file in the same private directory, flush and synchronize it, and atomically replace the state file.
  6. Add file locking to prevent concurrent watcher processes from corrupting state or bypassing cooldown updates.
  7. Validate loaded JSON fields and reject future, negative, non-numeric, or otherwise unreasonable timestamps.
  8. Handle malformed state safely by quarantining the invalid file and restoring a conservative default rather than terminating the watcher.
  9. Ensure state-file errors cannot silently disable monitoring; emit a local error through an independent, trusted logging channel.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documentation indicates capabilities to invoke shell commands (openclaw, python3), send network alerts to Feishu, and potentially write files or state, but it declares no explicit tool scope such as permissions or allowed-tools. This creates an over-privileged or ambiguously privileged skill boundary, making it easier for the skill to access broader execution, filesystem, or network capabilities than reviewers and the platform may expect.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The docstring frames alerting as based on '连续 error + 过去 24h 内' and later the implementation comments describe the first check as cron status, but the actual alert condition also includes a missing markdown file independently of cron error status. If the cron metadata appears non-error while the expected report file is absent, the code still sends a Feishu alert, which is broader than the stated alerting criterion.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · watcher.py (reported line 78)May include surrounding context.

python
def check_cron_status():
    """调用 openclaw cron get 检查 19:30 日报任务状态"""
    try:
        result = subprocess.run(
            ["openclaw", "cron", "get", DAILY_REPORT_JOB_ID],
            capture_output=True, text=True, timeout=15
        )

Static analysis

No suspicious patterns detected.