Back to skill

Security audit

Task Watchdog

Security checks for vulnerabilities and agentic risk

Overview

This task-lock helper has a coherent purpose, but its scripts can take over, complete, move, or delete task records without reliable ownership checks.

Review before installing. This skill is best limited to a controlled single-user or trusted-agent environment until it validates task and agent IDs, fails closed on missing identities or session-list errors, uses structured JSON parsing, and adds explicit authorization for completion, takeover, archive, and cleanup operations.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/lock-done.sh:21
Finding
Missing authorization allows arbitrary tasks to be marked complete and archived<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lock-done.sh:21-45` **Vulnerability Type**: Missing authorization check **Risk Level**: High ### Vulnerable Code ```bash # Find lock if [[ -z "$AGENT_ID" ]]; then AGENT_SEARCH=$(find "$LOCKS_ROOT" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) [[ -z "$AGENT_SEARCH" ]] && { echo "Error: lock not found: $TASK_ID"; exit 1; } AGENT_ID=$(echo "$AGENT_SEARCH" | sed "s|$LOCKS_ROOT/||" | cut -d/ -f1) fi LOCK_FILE="$LOCKS_ROOT/$AGENT_ID/locks/active/${TASK_ID}.lock" [[ ! -f "$LOCK_FILE" ]] && LOCK_FILE=$(find "$LOCKS_ROOT/$AGENT_ID/locks" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) [[ ! -f "$LOCK_FILE" ]] && { echo "Error: lock does not exist: $TASK_ID"; exit 1; } # Check status CURRENT_STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$LOCK_FILE" | sed 's/.*: *"\([^"]*\)".*/\1/') [[ "$CURRENT_STATUS" == "done" ]] && { echo "Note: already done: $TASK_ID"; exit 0; } DONE_AT=$(date -u +"%Y-%m-%dT%H:%M:%S+08:00") # Update status sed -i 's/"status": "[^"]*"/"status": "done"/' "$LOCK_FILE" sed -i "s/\"done_at\": \"[^\"]*\"/\"done_at\": \"$DONE_AT\"/" "$LOCK_FILE" # Archive immediately ARCHIVE_DIR="$LOCKS_ROOT/$AGENT_ID/locks/archive/$(date +%Y-%m-%d)" mkdir -p "$ARCHIVE_DIR" mv "$LOCK_FILE" "$ARCHIVE_DIR/" ``` ### Technical Analysis The completion operation locates a lock solely by a caller-supplied task and optional agent identifier. It then modifies and moves the lock without authenticating the caller or comparing the caller's session with the lock's `session_id`. This contradicts the ownership model documented in `references/spec.md:80-101`, which requires owner-session validation or an authorized takeover decision. Filesystem permissions alone do not establish task-level ownership when multiple agents or sessions execute under the same operating-system account. ### Attack Path 1. An attacker with permission to invoke the script identifies or guesses another tas ...[truncated 703 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require a trusted current-session identity for every state-changing operation. - Read the lock owner's `session_id` and compare it using exact string equality. - Fail closed if either the current identity or lock owner is absent or malformed. - Permit takeover only after a reliable, structured session-liveness check. - Do not accept privileged identities such as `main` or `dispatcher` from untrusted command-line arguments or environment variables. - Centralize authorization in a shared helper used by both `lock-update.sh` and `lock-done.sh`. - Revalidate authorization immediately before the final write and move to reduce race conditions. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/lock-update.sh:48
Finding
Lock update authorization is fail-open and trusts spoofable environment variables<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lock-update.sh:48-75` **Vulnerability Type**: Authorization bypass **Risk Level**: High ### Vulnerable Code ```bash # Check write permission CURRENT_SESSION=$(get_field "session_id" "$LOCK_FILE") ALLOWED_SESSION="${ALLOWED_SESSION:-${AGENT_SESSION_ID:-}}" has_permission() { local allowed="$1" local current="$2" # Owner session matches [[ "$allowed" == "$current" ]] && return 0 # Dispatcher or main session [[ "$allowed" == "dispatcher" || "$allowed" == "main" ]] && return 0 return 1 } if [[ -n "$CURRENT_SESSION" && -n "$ALLOWED_SESSION" ]]; then if ! has_permission "$ALLOWED_SESSION" "$CURRENT_SESSION"; then # Is owner still alive? if openclaw sessions list --agent "$AGENT_ID" --format json 2>/dev/null | grep -q "$CURRENT_SESSION"; then echo "Error: no write permission (owner session is still active)" >&2 exit 3 fi # Owner is gone, allow takeover echo "Note: taking over task $TASK_ID (original session disappeared)" fi fi ``` ### Technical Analysis Authorization only executes when both `CURRENT_SESSION` and `ALLOWED_SESSION` are nonempty. If the caller omits `AGENT_SESSION_ID` and `ALLOWED_SESSION`, the conditional body is skipped and the update proceeds. A malformed lock with no `session_id` also bypasses the check. The authorization identity is obtained from caller-controlled environment variables. A caller can set `ALLOWED_SESSION=main` or `ALLOWED_SESSION=dispatcher`, both of which are treated as privileged identities without external verification. ### Attack Path **Missing-identity bypass:** 1. Select another task's lock. 2. Invoke `lock-update.sh` without setting `AGENT_SESSION_ID` or `ALLOWED_SESSION`. 3. `ALLOWED_SESSION` remains empty. 4. The authorization block is skipped. 5. The script updates the victim lock's heartbeat or progress. **Privileged-identity spoofing:** 1. Set `ALLOWED_SESSION=main` or `ALLOWED_SESSION=dispatche ...[truncated 472 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Fail closed whenever the authenticated caller identity or lock owner is unavailable. - Obtain the current session from a trusted OpenClaw runtime interface rather than a freely controlled environment variable. - Replace magic privileged strings with verified role or capability data. - Require explicit agent identity and verify that it is associated with the authenticated session. - Apply exact session matching and structured liveness validation. - Reject malformed locks before any modification. - Use a single authorization implementation for create, update, completion, takeover, and archival operations. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/lock-create.sh:36
Finding
Unvalidated agent and task identifiers permit path traversal outside lock namespaces<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/lock-create.sh:36-39` - `scripts/lock-update.sh:36-47` - `scripts/lock-done.sh:21-31` - `scripts/lock-status.sh:28-42` **Vulnerability Type**: Path traversal **Risk Level**: High ### Vulnerable Code ```bash # scripts/lock-create.sh LOCK_DIR="$LOCKS_ROOT/$AGENT_ID/locks/active" mkdir -p "$LOCK_DIR" LOCK_FILE="$LOCK_DIR/${TASK_ID}.lock" ``` ```bash # scripts/lock-update.sh if [[ -z "$AGENT_ID" ]]; then AGENT_SEARCH=$(find "$LOCKS_ROOT" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) [[ -z "$AGENT_SEARCH" ]] && { echo "Error: lock not found: $TASK_ID"; exit 1; } AGENT_ID=$(echo "$AGENT_SEARCH" | sed "s|$LOCKS_ROOT/||" | cut -d/ -f1) fi LOCK_FILE="$LOCKS_ROOT/$AGENT_ID/locks/active/${TASK_ID}.lock" [[ ! -f "$LOCK_FILE" ]] && LOCK_FILE=$(find "$LOCKS_ROOT/$AGENT_ID/locks" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) ``` ```bash # scripts/lock-done.sh if [[ -z "$AGENT_ID" ]]; then AGENT_SEARCH=$(find "$LOCKS_ROOT" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) [[ -z "$AGENT_SEARCH" ]] && { echo "Error: lock not found: $TASK_ID"; exit 1; } AGENT_ID=$(echo "$AGENT_SEARCH" | sed "s|$LOCKS_ROOT/||" | cut -d/ -f1) fi LOCK_FILE="$LOCKS_ROOT/$AGENT_ID/locks/active/${TASK_ID}.lock" [[ ! -f "$LOCK_FILE" ]] && LOCK_FILE=$(find "$LOCKS_ROOT/$AGENT_ID/locks" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) ``` ```bash # scripts/lock-status.sh if [[ -z "$AGENT_ID" ]]; then AGENT_SEARCH=$(find "$LOCKS_ROOT" -name "${TASK_ID}.lock" -type f 2>/dev/null | head -1) if [[ -z "$AGENT_SEARCH" ]]; then echo "Error: lock file not found: $TASK_ID" >&2 exit 1 fi AGENT_ID=$(echo "$AGENT_SEARCH" | sed "s|$LOCKS_ROOT/||" | cut -d/ -f1) fi LOCK_FILE="$LOCKS_ROOT/$AGENT_ID/locks/active/${TASK_ID}.lock" [[ ! -f "$LOCK_FILE" ]] && LOCK_FILE="$LOCKS_ROOT/$AGENT_ID/locks/archive/*/${TASK_ID}.lock" [[ ! -f "$LOCK_FILE" ]] && LOCK_FILE=$(find "$LOCKS_ROOT/$AGENT_ID/locks ...[truncated 1564 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate both identifiers against a strict allowlist such as `^[A-Za-z0-9._-]+$`. - Explicitly reject path separators, `.` and `..` components, control characters, and empty identifiers. - Resolve the parent directory to a canonical path and verify that it begins with the canonical `LOCKS_ROOT` plus a path separator. - Avoid global `find` searches based on caller-supplied names. - Open files relative to trusted directory descriptors where supported. - Reject symbolic links and verify expected file types before writes or moves. - Apply the same validation helper consistently in every script. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lock-create.sh:58
Finding
Raw input interpolation permits malformed JSON and sed program manipulation<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/lock-create.sh:58-78` - `scripts/lock-update.sh:86-94` **Vulnerability Type**: Unsafe data serialization and sed injection **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/lock-create.sh JSON="{ \"task_id\": \"$TASK_ID\", \"agent_id\": \"$AGENT_ID\", \"session_id\": \"$SESSION_ID\", \"status\": \"in_progress\", \"created_at\": \"$CREATED_AT\", \"last_heartbeat\": \"$CREATED_AT\", \"last_progress\": \"$CREATED_AT\", \"description\": \"$DESCRIPTION\", \"progress\": \"Task created\"" [[ -n "$PARENT_TASK_ID" ]] && JSON="$JSON, \"parent_task_id\": \"$PARENT_TASK_ID\"" JSON="$JSON }" echo "$JSON" > "$LOCK_FILE" ``` ```bash # scripts/lock-update.sh if [[ -n "$PROGRESS" ]]; then sed -i "s/\"progress\": \"[^\"]*\"/\"progress\": \"$PROGRESS\"/" "$LOCK_FILE" sed -i "s/\"last_progress\": \"[^\"]*\"/\"last_progress\": \"$HEARTBEAT\"/" "$LOCK_FILE" echo "Progress updated: $TASK_ID" echo " progress: $PROGRESS" fi sed -i "s/\"last_heartbeat\": \"[^\"]*\"/\"last_heartbeat\": \"$HEARTBEAT\"/" "$LOCK_FILE" ``` ### Technical Analysis `lock-create.sh` constructs JSON through direct string interpolation. Values containing quotes, backslashes, newlines, or control characters are not JSON-escaped. A crafted value can terminate its original string and introduce additional JSON fields or make the document invalid. `lock-update.sh` inserts `PROGRESS` and `HEARTBEAT` into a double-quoted sed expression. Sed replacement metacharacters such as `&`, backslashes, delimiters, and newlines are not escaped. This allows data corruption and manipulation of the generated sed program. On sed implementations or invocation forms that support executable commands, hostile sed syntax may increase the impact, although local lock corruption is the directly demonstrated consequence. ### Attack Path 1. Create a task with a description, session ID, or parent task ID containing JSON syntax, ...[truncated 770 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Generate JSON with a real serializer, for example `jq -n --arg`, rather than shell interpolation. - Update documents with structured operations such as `jq --arg value '.progress = $value'`. - Write updates to a securely created temporary file in the same directory, validate the result, and atomically rename it. - Validate timestamps against a strict ISO 8601 format. - Apply length limits and reject control characters where they are not required. - Stop parsing JSON with `grep` and `sed`; use exact field extraction through `jq`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scan-locks.sh:25
Finding
Regex-based session checks allow false liveness and authorization decisions<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/lock-create.sh:47` - `scripts/lock-update.sh:67` - `scripts/lock-self-check.sh:46-51` - `scripts/lock-report.sh:14-23` - `scripts/scan-locks.sh:25-35` **Vulnerability Type**: Improper session identifier validation **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/lock-create.sh if openclaw sessions list --agent "$AGENT_ID" --format json 2>/dev/null | grep -q "$EXISTING_SESSION"; then ``` ```bash # scripts/lock-update.sh if openclaw sessions list --agent "$AGENT_ID" --format json 2>/dev/null | grep -q "$CURRENT_SESSION"; then ``` ```bash # scripts/lock-self-check.sh session_alive() { local sid="$1" local ag="$2" [[ -z "$sid" ]] && return 1 openclaw sessions list --agent "$ag" --format json 2>/dev/null | grep -q "$sid" } ``` ```bash # scripts/lock-report.sh session_alive() { local session_id="$1" local agent_id="$2" if [[ -z "$session_id" ]]; then return 1 fi openclaw sessions list --agent "$agent_id" --format json 2>/dev/null | grep -q "$session_id" } ``` ```bash # scripts/scan-locks.sh session_alive() { local session_id="$1" local agent_id="$2" if [[ -z "$session_id" ]]; then return 1 fi openclaw sessions list --agent "$agent_id" --format json 2>/dev/null | grep -q "$session_id" } ``` ### Technical Analysis Session IDs are passed to `grep` as basic regular expressions and searched across the entire serialized JSON response. They are not escaped, anchored, or restricted to a specific JSON field. A session ID containing regular-expression metacharacters can match unrelated text. Even an ordinary short session ID can match a substring in another session or another JSON property. Consequently, the scripts may incorrectly treat a dead owner as active or make other incorrect lifecycle decisions. ### Attack Path 1. Introduce a lock whose `session_id` is a regex pattern or a substring likely to occur in `openclaw sessions list` output. 2. Tri ...[truncated 605 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse `openclaw sessions list --format json` with `jq`. - Select only the documented session-ID property and compare it using exact string equality. - Validate session IDs against the runtime's documented identifier grammar. - Treat malformed command output and command failures as an explicit indeterminate state rather than silently equivalent to a dead session. - Use one shared, tested `session_alive` implementation throughout the project. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lock-archive.sh:181
Finding
Unvalidated retention arguments enter Bash arithmetic evaluation<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/lock-archive.sh:97-109` - `scripts/lock-archive.sh:130-143` - `scripts/lock-archive.sh:181-191` **Vulnerability Type**: Unsafe arithmetic input handling **Risk Level**: Medium ### Vulnerable Code ```bash cmd_archive() { local days="${1:-7}" echo "Archiving completed tasks older than ${days} days..." local count=0 while IFS= read -r lock; do [[ -z "$lock" ]] && continue local status=$(get_status "$lock") [[ "$status" == "in_progress" ]] && continue local age=$(file_age_days "$lock") [[ $age -lt $days ]] && continue ``` ```bash cmd_cleanup() { local days="${1:-30}" echo "Cleaning archives older than ${days} days..." local count=0 while IFS= read -r lock; do [[ -z "$lock" ]] && continue local age=$(file_age_days "$lock") [[ $age -lt $days ]] && continue ((count++)) || true local task=$(basename "$lock") rm -f "$lock" ``` ```bash case "${1:-}" in --list) cmd_list ;; --status) cmd_status ;; --archive-days) [[ $# -lt 2 ]] && { echo "Error: --archive-days requires a day count"; exit 2; } cmd_archive "$2" ;; --cleanup-days) [[ $# -lt 2 ]] && { echo "Error: --cleanup-days requires a day count"; exit 2; } cmd_cleanup "$2" ;; *) usage ;; esac ``` ### Technical Analysis The caller-controlled `days` value is used as an arithmetic operand without first verifying that it is a bounded decimal integer. Bash arithmetic contexts interpret identifiers and expressions rather than treating all input as inert numeric data. Malformed input can terminate the script under `set -euo pipefail`, causing a reliable denial of service for scheduled archive or cleanup operations. Complex arithmetic syntax also creates unnecessary evaluation behavior and version-dependent risk. ### Attack Path 1. Invoke `lock-archive.sh --archive-days <crafted-value>` or `--cleanup-days <crafted-value>`. 2. The argume ...[truncated 789 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Before arithmetic use, require the argument to match `^[0-9]+$`. - Parse decimal values explicitly, avoiding unintended octal interpretation where relevant. - Enforce a reasonable range, such as `0` through an operationally justified maximum. - Reject negative numbers, expressions, whitespace, signs, and variable names. - Add tests for empty, negative, extremely large, nonnumeric, and expression-like values. - Consider a dry-run mode and confirmation requirement for destructive cleanup. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented self-check behavior says that when an owner session dies, the script will automatically take over the task by rewriting session ownership. In a lock-based coordination system, undocumented or insufficiently constrained auto-takeover can cause unauthorized task resumption, conflicting agents, or corruption of task state, especially since the description does not clearly define safety checks or GRACE gating for reassignment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented self-check behavior says that when an owner session dies, the script will automatically take over the task by rewriting session ownership. In a lock-based coordination system, undocumented or insufficiently constrained auto-takeover can cause unauthorized task resumption, conflicting agents, or corruption of task state, especially since the description does not clearly define safety checks or GRACE gating for reassignment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The documented self-check behavior says that when an owner session dies, the script will automatically take over the task by rewriting session ownership. In a lock-based coordination system, undocumented or insufficiently constrained auto-takeover can cause unauthorized task resumption, conflicting agents, or corruption of task state, especially since the description does not clearly define safety checks or GRACE gating for reassignment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The documented self-check behavior says that when an owner session dies, the script will automatically take over the task by rewriting session ownership. In a lock-based coordination system, undocumented or insufficiently constrained auto-takeover can cause unauthorized task resumption, conflicting agents, or corruption of task state, especially since the description does not clearly define safety checks or GRACE gating for reassignment.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The documented policy says that once the owner session disappears, only dispatcher/main may take over, but the implementation only blocks unauthorized writers while the owner session is still active. If the owner session is gone, any caller that supplies a non-empty ALLOWED_SESSION/AGENT_SESSION_ID can proceed, which defeats the intended authorization boundary and allows unauthorized lock modification or task takeover. In this task-watchdog context, that is especially dangerous because lock files are the source of truth for task state and timeout monitoring.

Intent-Code Divergence

Medium
Confidence
84% confidence
Finding
The document gives conflicting instructions for dead sessions: one part treats them as abandoned and subject to supervisor archival, while another says self-check should automatically take over the task. In operational security terms, this ambiguity can lead to inconsistent ownership decisions, duplicate execution, or unintended continuation of tasks that should have been quarantined or reviewed.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger condition 'on heartbeat polling' is broad enough that an agent may invoke self-check during routine liveness events unrelated to active task management. Because self-check is documented to mutate lock state and even take over tasks, overly broad invocation can cause unintended state changes, ownership flips, or noisy task churn.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
The document title and all operational guidance are written entirely in Chinese, with no indication that other languages are supported or that the user can opt into this locale. Under the policy, forcing a specific language without user choice is a natural-language policy concern.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file's comments, usage text, and operational messages are all written in Chinese, which imposes a specific language on users. Under the policy, a forced language choice without opt-in or clear region-specific justification is a natural-language policy violation.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The archive logic contradicts its stated policy and archives every lock whose status is not 'in_progress'. That means unexpected states such as failed, pending_review, blocked, or malformed values can be silently removed from the active set, which can hide live operational issues and break monitoring or recovery workflows in this task-watchdog context.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This shell script includes user-facing comments, usage text, and error messages exclusively in Chinese, such as the usage line and unknown-argument errors. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The manifest describes a 'task lock and timeout monitoring system' centered on heartbeat + GRACE judgment and explicitly notes no immediate alerting. This script performs lifecycle state transition and archival operations by rewriting lock status to "done" and moving the file into an archive directory, which is broader than passive timeout monitoring and not conveyed by the manifest description.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code file contains natural-language comments and usage text entirely in Chinese, and later emits Chinese-only status/report messages. The policy requires flagging language or locale constraints when a skill forces a specific language without user opt-in or a documented justification.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The script's visible report headings, labels, statuses, and recommendation text are hard-coded in Chinese, so users receive output in a single locale with no opt-in or fallback. That is a natural-language policy issue under the language/locale rule.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The header promises takeover behavior gated by heartbeat plus a GRACE timeout, but the implementation immediately reassigns a lock whenever the recorded session is absent from `openclaw sessions list`. That mismatch can cause premature lock takeover during transient session-list failures, stale control-plane state, or short disconnects, leading to concurrent ownership and task corruption in this watchdog/locking context.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This shell script includes its operational description, usage guidance, and runtime messages in Chinese only. That creates a natural-language locale policy concern because users are forced into a specific language without opt-in or any documented region-specific justification.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The file’s description, usage text, and later error/status messages are written only in Chinese, indicating the skill is designed to communicate in a fixed language. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This shell script’s natural-language content, including the header comments, usage text, and error messages, is exclusively in Chinese. Under the policy, forcing a specific language without user opt-in or clear locale justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
Comments and the final user-facing console output are written in Chinese, including the completion message shown to users. The file does not indicate that the skill is region-specific or provide any language/locale opt-in, which can violate language policy requirements.

Description-Behavior Mismatch

Low
Confidence
76% confidence
Finding
The manifest describes a lock and timeout monitoring system that relies on heartbeat + grace and explicitly says it does not send immediate alerts. This script adds operational commands to list active tasks and show per-agent lock statistics, which surfaces live monitoring information beyond pure background state tracking/archival described in the manifest.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The script's comments, usage text, and runtime messages are written in Chinese only, which imposes a specific language on users without any opt-in or documented locale constraint. This matches the policy category for language or locale restrictions lacking user choice.

Missing User Warnings

Low
Confidence
79% confidence
Finding
This shell script performs a file write to a persistent location under $HOME/.openclaw/agents by overwriting or creating the lock file. Although the script prints a success message afterward, there is no prior warning, confirmation, or explanatory comment near the write itself about modifying on-disk state, and the script can also replace an abandoned lock.

Intent-Code Divergence

Low
Confidence
84% confidence
Finding
The comment says '立即归档到 archive/今天/' as if the archival target is a conceptual 'today' bucket, but the actual implementation uses `$(date +%Y-%m-%d)` from the host environment. Because the script also generates `done_at` using `date -u` with a hard-coded +08:00 offset, the effective archive day may diverge from the timestamp semantics described around completion.

Intent-Code Divergence

Low
Confidence
90% confidence
Finding
The script claims to process abandoned or timed-out locks, but the abandoned path is effectively unimplemented: `GRACE_MINUTES`, `abandoned`, and the related status message are unused. In a task-locking system this can mislead operators and dependent automation into assuming timeout recovery exists when it does not, reducing reliability and potentially leaving stale locks or causing unsafe manual intervention.

Missing User Warnings

Low
Confidence
86% confidence
Finding
This shell script performs a filesystem write/destructive state change by creating an archive directory and moving active lock files into it. Although the script logs the action to a file, there is no user-facing disclosure, confirmation, or stdout warning before the archival operation occurs.

Static analysis

No suspicious patterns detected.