Back to skill

Security audit

Cyber Growth

Security checks for vulnerabilities and agentic risk

Overview

This is a real growth tracker, but it automatically saves activity and has script bugs that could let crafted logged text run local commands.

Install only after reviewing the privacy tradeoff. Do not enable automatic logging or external reporting for sensitive work unless users have explicitly opted in. The scripts should be fixed to serialize inputs safely, validate XP/date/month values, and avoid logging or forwarding secrets before this is used in normal agent sessions.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/grow.sh:261
Finding
Arbitrary Python Code Execution Through Shell-to-Python Source Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/grow.sh`, lines 261-286 **Vulnerability Type**: Python source injection leading to arbitrary command execution **Risk Level**: High ### Vulnerable Code ```bash # Add record python3 -c " import json with open('$DATA_FILE') as f: data = json.load(f) record = { 'id': '$record_id', 'date': '$date_short', 'timestamp': '$now', 'description': '$description', 'domain': '$domain', 'xp': $xp, 'type': '$type' } data['records'].append(record) data['totalXp'] = $new_xp data['chromeLevel'] = $new_level data['profile']['title'] = '$(get_title "$new_level")' if '$domain' not in data['domains']: data['domains']['$domain'] = {'xp': 0, 'level': 1} data['domains']['$domain']['xp'] = $new_domain_xp data['domains']['$domain']['level'] = $domain_level with open('$DATA_FILE', 'w') as f: json.dump(data, f, indent=2, ensure_ascii=False) " 2>/dev/null ``` The same unsafe construction pattern also occurs in other Python invocations, including configurable file paths and command options at `scripts/grow.sh:60-88`, `scripts/grow.sh:492-503`, `scripts/grow.sh:581-632`, `scripts/grow.sh:833-846`, `scripts/grow.sh:938-989`, and `scripts/grow.sh:1050-1067`. ### Technical Analysis The script creates Python source code inside a double-quoted shell string and directly inserts values such as `description`, `domain`, `type`, `xp`, and `DATA_FILE`. These values are treated as Python syntax rather than serialized data. For example, a description containing a single quote can terminate the Python string assigned to `description`. Additional Python statements can then be inserted into the generated program. Python provides direct access to operating-system functionality through modules such as `os` and `subprocess`, so successful source injection results in arbitrary command execution. Suppressing standard error with `2>/dev/null` does not prevent exploitation. It only hides syntax errors an ...[truncated 1873 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never construct Python source code by interpolating shell variables. 2. Pass values as command-line arguments or environment variables and retrieve them through `sys.argv` or `os.environ`. 3. Prefer a separate Python script over large `python3 -c` strings. 4. Serialize records with `json.dump` or `json.dumps`; do not manually quote input. 5. Validate `xp`, `days`, chart ranges, and log limits as bounded integers before use. 6. Validate months and dates against strict formats such as `^[0-9]{4}-[0-9]{2}$` and `^[0-9]{4}-[0-9]{2}-[0-9]{2}$`. 7. Restrict domains and event types to explicit allowlists. 8. Pass `DATA_FILE` as an argument and open the supplied path as data rather than embedding it in Python source. 9. Stop suppressing all Python errors. Handle failures explicitly and avoid reporting success when a database update failed. 10. Add regression tests containing quotes, backslashes, newlines, Unicode, and Python-like payload text. A safer pattern is: ```bash python3 - "$DATA_FILE" "$record_id" "$date_short" "$now" \ "$description" "$domain" "$xp" "$type" <<'PY' import json import sys data_file, record_id, date_short, now, description, domain, xp, event_type = sys.argv[1:] xp = int(xp) with open(data_file, encoding="utf-8") as handle: data = json.load(handle) record = { "id": record_id, "date": date_short, "timestamp": now, "description": description, "domain": domain, "xp": xp, "type": event_type, } PY ``` ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/accumulate.sh:34
Finding
Malformed JSON and Event Injection Through Unescaped JSONL Construction<![CDATA[ ## Vulnerability Details **File Location**: `scripts/accumulate.sh`, lines 34-36 **Vulnerability Type**: Improper output encoding and JSONL record injection **Risk Level**: High ### Vulnerable Code ```bash # Append one JSONL record without reading the file timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") printf '{"ts":"%s","desc":"%s","domain":"%s","xp":%d,"type":"%s"}\n' \ "$timestamp" "$description" "$domain" "$xp" "$type" >> "$LOG_FILE" ``` ### Technical Analysis The script manually creates JSON using `printf`, but it does not apply JSON escaping to string fields. Values containing double quotes, backslashes, carriage returns, newlines, tabs, or other control characters can produce invalid JSON. A newline in an input value can also terminate the current JSONL record and append one or more attacker-selected lines. This permits event-log injection rather than merely corrupting one record. The generated file is later treated as trusted structured input by `nightly.sh`. Parsed values are passed to `grow.sh record`, where they reach the independently vulnerable Python source-construction logic. Consequently, JSONL injection can be chained with the arbitrary Python execution vulnerability. The XP field is formatted with `%d`, but it is not validated as a bounded integer before use. Invalid or extreme values can cause errors, arithmetic failures, or integrity problems. ### Attack Path 1. An attacker provides content that becomes an event description, domain, type, or XP value. 2. The Agent invokes `accumulate.sh` according to the automatic event-recording workflow. 3. The attacker-controlled string is inserted into a JSON object without escaping. 4. Quotes or control characters corrupt the current record; a newline can introduce an additional JSONL record. 5. During nightly settlement, `nightly.sh` reads each injected line and parses its fields. 6. The injected event is recorded in the main database. 7. If an injected field contains a Python source ...[truncated 562 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate JSON with a real JSON serializer rather than `printf`. 2. Pass every field to the serializer as data. 3. Validate XP with a strict integer expression and enforce reasonable minimum and maximum values. 4. Restrict domain and type values to documented allowlists. 5. Reject NUL bytes and apply explicit length limits to descriptions. 6. Ensure each append operation emits exactly one serialized JSON object followed by one newline. 7. Make nightly processing fail safely on malformed records instead of silently converting fields to default values. 8. Record malformed input in a separate quarantine file for review. 9. Add tests for quotes, backslashes, embedded newlines, tabs, and multiple-record payloads. For example: ```bash python3 - "$timestamp" "$description" "$domain" "$xp" "$type" >> "$LOG_FILE" <<'PY' import json import sys timestamp, description, domain, xp, event_type = sys.argv[1:] record = { "ts": timestamp, "desc": description, "domain": domain, "xp": int(xp), "type": event_type, } print(json.dumps(record, ensure_ascii=False)) PY ``` ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/nightly.sh:12
Finding
Path Traversal in Nightly Archive Processing Permits Unauthorized File Relocation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/nightly.sh`, lines 12-18 and 37-40 **Vulnerability Type**: Path traversal and unauthorized filesystem modification **Risk Level**: Medium ### Vulnerable Code ```bash # Date, defaulting to yesterday because the script normally runs after midnight DATE="${1:-$(date -v-1d +"%Y-%m-%d" 2>/dev/null || date -d "yesterday" +"%Y-%m-%d")}" LOG_FILE="$LOG_DIR/$DATE.jsonl" if [ ! -f "$LOG_FILE" ]; then echo "No events for $DATE" >&2 exit 0 fi ``` ```bash # Archive log ARCHIVE_DIR="$LOG_DIR/archive" mkdir -p "$ARCHIVE_DIR" mv "$LOG_FILE" "$ARCHIVE_DIR/" ``` ### Technical Analysis Although the documentation describes the optional argument as a date, the script accepts any string. It appends `.jsonl` and joins the result to `LOG_DIR` without validating that the value matches `YYYY-MM-DD`. An argument containing `../` path components can escape the intended event directory. If the resulting target is an existing regular file, the script parses it as an event log and then moves it into the archive directory. Shell quoting prevents whitespace-based command injection, but it does not prevent filesystem path traversal. The absence of canonical-path verification allows access to any `.jsonl` file reachable by a relative path and readable/writable by the Agent account. ### Attack Path 1. An attacker influences an invocation of `nightly.sh` and supplies a traversal value instead of a date. 2. The script constructs a path such as: `$LOG_DIR/../../target.jsonl`. 3. The operating system resolves the `..` components outside the intended log directory. 4. If the target exists, the script reads it line by line and attempts to process its contents. 5. The script moves the target file into `$LOG_DIR/archive/`. 6. The original application or user loses access to the file at its expected location. If the selected file contains attacker-controlled JSON records, its contents may also be forwarded to the vulnerab ...[truncated 705 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate the argument before constructing a path: ```bash if [[ ! "$DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then echo "Invalid date; expected YYYY-MM-DD" >&2 exit 1 fi ``` 2. Verify that the value represents a real calendar date rather than only matching the textual format. 3. Reject all path separators and traversal components. 4. Canonicalize both `LOG_DIR` and `LOG_FILE`, then confirm that the target's parent directory is exactly the canonical log directory. 5. Do not follow symbolic links when selecting or archiving event files. 6. Confirm file ownership and expected permissions before processing. 7. Use a fixed destination filename derived from the validated date. 8. Refuse to overwrite an existing archive file unexpectedly. 9. Treat malformed event records as errors and do not move the source file until every record is processed successfully. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The core theme and part of the manual functionality do align: this is indeed a stylized growth tracker, and grow.sh record/status/report are implemented. However, the declared description prominently claims a two-mode system including automatic accumulation at conversation end, daily nightly settlement, and morning report scripts. None of those automation components appear in the supplied code chunk; only grow.sh is present. That is a material description/behavior mismatch because the declared primary operating mode includes capabilities and triggers not implemented here. Additionally, the actual code exposes several extra reporting and visualization commands not mentioned in the description, though those are secondary compared with the missing automation pieces.

Vague Triggers

High
Confidence
96% confidence
Finding
The skill directs the agent to automatically record events in many common scenarios such as task completion, learning, fixes, and helping others. Broad trigger conditions like these create a high likelihood of indiscriminate persistence of conversation-derived content, including sensitive operational details, without a clear necessity or user approval boundary.

Missing User Warnings

High
Confidence
98% confidence
Finding
The document describes automatic recording of user/system events and generation of reports, including delivery through Feishu, but it does not provide clear warnings, consent requirements, or data-sharing boundaries. In context, this is more dangerous because the skill is explicitly designed to harvest conversation outcomes continuously and package them for later review or onward transmission.

Missing User Warnings

High
Confidence
99% confidence
Finding
Automatically sending a morning report to 'Boss' via Feishu introduces third-party disclosure of agent activity and possibly user content without any stated notice, approval, or minimization. The specific context makes this especially risky because reporting to a supervisor encourages routine exfiltration of summaries that may contain confidential tasks, incidents, or user-supplied details.

Natural-Language Policy Violations

Medium
Confidence
76% confidence
Finding
The entire skill description is presented in Chinese, with no indication that other languages are supported or that the user can opt into this locale. The policy criteria call for flagging language or locale constraints when a skill forces a specific language without user choice or documented justification.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill instructs the agent to invoke shell scripts that append to local files and update a database, but it does not declare any explicit tool scope or permission boundary. That makes the write capability implicit rather than reviewable, increasing the chance the agent can write conversation-derived data to disk without informed approval or least-privilege constraints.

Ssd 3

Medium
Confidence
97% confidence
Finding
The skill tells the agent to proactively generate reports for a third party ('Boss') from conversation/task activity without any stated consent or minimization rules. This can convert ordinary interactions into surveillance-style telemetry and expose confidential user, task, or system information beyond the original interaction context.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Automatic synchronization to Feishu Bitable uploads stored records to an external service, but the documentation does not adequately warn about privacy, retention, access control, or what exact data leaves the local environment. This creates a real risk of unintended external exposure of work history, conversation summaries, or sensitive operational metadata.

Ssd 3

Medium
Confidence
96% confidence
Finding
The skill instructs the agent to proactively log conversation-derived events like completed tasks, learned information, fixes, and help given, but sets no boundaries on sensitive content. In practice, this can capture secrets, personal data, internal project details, or other confidential context merely because it appeared in a successful interaction.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
Lines L003-L004 state that the lexicon is used to generate cyber-style output, and the file is entirely framed as a Chinese terminology mapping. There is no indication that users can choose their preferred language or locale, which can violate language-choice policy when applied broadly.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This markdown file presents all instructional and descriptive content in Chinese, with no indication that users may choose another language or locale. The policy explicitly calls for flagging language or locale constraints when they are imposed without opt-in or documented justification.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The comments and usage text are written in Chinese, presenting the skill as Chinese-only without any opt-in, fallback, or justification for the locale restriction. This can violate language or locale policy when skills are expected to avoid forcing a specific language unless clearly documented and appropriate.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This shell script embeds user-facing text primarily in Chinese from the header onward, and all command help and status/report outputs continue that pattern. Because the file provides no opt-in, language selection, or justification for a Chinese-only locale, it conflicts with the policy against forcing a specific language without user choice.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script collects status and 7-day report data from grow.sh and unconditionally prints the combined report to stdout. In the stated deployment model this stdout is intended to be consumed by cron or heartbeat for onward delivery, but stdout is also commonly captured by logs, supervisors, CI runners, and shell history wrappers, which can expose potentially sensitive progress, task, or operational metadata without access controls or explicit destination validation.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
Line L40 moves the daily JSONL log into an archive directory, which changes the user's filesystem state and removes the file from its original location. Although the script prints a final summary, there is no earlier user-facing warning, confirmation, or explanatory comment/docstring disclosing this file-moving behavior.

Missing User Warnings

Low
Confidence
90% confidence
Finding
This markdown file documents that the skill stores all growth records, XP, and domain levels in `~/.openclaw/memory/cyber-growth.json`, but it does not include any user-facing warning about persistent local data storage or its privacy implications. Under the markdown-specific warning criteria, descriptions should warn when behavior can affect user data or privacy.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
This markdown file presents key protocol names, descriptions, and instructions in a mixed Chinese/English format, but does not state that the skill is intended for Chinese-speaking users or offer an alternative language. Under the policy rule for language/locale, forcing a specific language without opt-in can be a natural-language policy issue.

Missing User Warnings

Low
Confidence
91% confidence
Finding
This code creates a log directory under the user's home directory and writes events to a dated JSONL file. Although the script comments describe the logging behavior, there is no user-facing warning at runtime that the provided description will be stored persistently on disk.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The manifest describes a growth tracking system that records events and shows status/report views, but does not mention any external Feishu/Bitable integration. This file persists Feishu configuration in its data model and invokes a sync routine after recording events, which extends behavior beyond the stated description.

Description-Behavior Mismatch

Low
Confidence
91% confidence
Finding
The manifest says users should use grow.sh for status/report, but this file also implements multiple extra commands for historical logs, domain trees, progress forecasting, charts, and monthly reports. These are broader product behaviors than the manifest advertises, even though they remain in the same general domain.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The comment says the default should be the previous month, and if today is <= 5 then use the month before that. However, the code sets the month to one month ago when day <= 5, and to the current month otherwise. This is an active contradiction between documentation and behavior.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The human-facing title, schedule description, and usage context are written in Chinese, and the generated message header is also Chinese-only. This imposes a specific language presentation without any indication of user choice or documented locale constraint.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The file's natural-language comments and usage context are presented in Chinese, with no indication that users may choose another language or that the locale restriction is required for a region-specific purpose. This can violate language/locale policy when a skill implicitly enforces one language without opt-in or documented justification.

Static analysis

No suspicious patterns detected.