Back to skill

Security audit

earn-hunter

Security checks for vulnerabilities and agentic risk

Overview

This skill has a legitimate OKX Earn monitoring purpose, but it also sets up persistent background execution and includes high-impact financial workflow instructions that need careful review.

Install only if you are comfortable with a skill that can create persistent scheduled jobs, write under ~/.okx/earn-hunter, use your OKX CLI login context for live account data, and send opportunity notifications to Telegram or Lark. Review the purchase guide before using subscription flows, and prefer explicit confirmation, pinned dependencies, restrictive file permissions, and exact scheduler cleanup before enabling unattended operation.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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

Warning
Location
scripts/scan.sh:37
Finding
Unvalidated executable environment snapshot permits recurring command execution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scan.sh:37-40`; snapshot creation is specified in `SKILL.md:58-66` **Vulnerability Type**: Unsafe sourcing of a writable configuration file **Risk Level**: Medium ### Complete Code Snippet Snapshot creation: ```bash cat > ~/.okx/earn-hunter/env.snapshot << SNAP # auto-generated by earn-hunter activation — $(date -Iseconds) OKX_BIN=$(command -v okx) NODE_BIN=$(command -v node) JQ_BIN=$(command -v jq) ACTIVATION_PATH=$PATH SNAP ``` Snapshot execution: ```bash _EH_SNAPSHOT="${EH_STATE_DIR:-$HOME/.okx/earn-hunter}/env.snapshot" # shellcheck disable=SC1090 [[ -f "$_EH_SNAPSHOT" ]] && source "$_EH_SNAPSHOT" ``` ### Technical Analysis The snapshot is intended only to preserve executable paths for cron, but it is stored as executable shell syntax and later loaded with `source`. Sourcing a file executes every command in that file rather than merely reading its data. The generated values are not safely shell-escaped. In particular, `ACTIVATION_PATH=$PATH` can produce additional shell statements if the environment value contains a newline or other shell syntax. Separately, any process capable of modifying `~/.okx/earn-hunter/env.snapshot` can insert arbitrary commands. The `EH_STATE_DIR` environment variable also controls the directory from which the snapshot is sourced. This is useful for tests, but it expands the execution surface because an invocation with an attacker-controlled value can cause a different snapshot to be executed. The risk is amplified by the scheduler: after activation, the vulnerable source operation is performed by every cron, LaunchAgent, or interactive scan. ### Attack Path 1. An attacker influences the activation environment, modifies `env.snapshot`, or causes the script to run with a malicious `EH_STATE_DIR`. 2. The selected snapshot contains shell commands in addition to the expected variable assignments. 3. `scan.sh` tests only whether the file exists; it performs no ow ...[truncated 1115 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not represent path data as executable shell code. 2. Store resolved paths in JSON, for example: ```json { "okx_bin": "/usr/local/bin/okx", "node_bin": "/usr/local/bin/node", "jq_bin": "/usr/local/bin/jq" } ``` 3. Read each value as data with `jq`: ```bash _OKX_BIN=$(jq -r '.okx_bin // empty' "$SNAPSHOT_FILE") _NODE_BIN=$(jq -r '.node_bin // empty' "$SNAPSHOT_FILE") _JQ_BIN=$(jq -r '.jq_bin // empty' "$SNAPSHOT_FILE") ``` 4. Validate that every resulting value is an absolute path to an executable regular file. 5. Create the state directory with mode `0700` and snapshot with mode `0600`. 6. Check that the snapshot is owned by the current user and is not group- or world-writable. 7. Remove `ACTIVATION_PATH` because the script reconstructs a restricted `PATH` from resolved executable directories. 8. Restrict `EH_STATE_DIR` to explicit test mode, or reject it when a production scheduler invokes the script. 9. If shell assignments must be retained, generate them with robust shell escaping such as `printf '%q'`; this is less safe than using a non-executable format and should not be the preferred fix. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:31
Finding
Preflight automatically installs unpinned external Skills used in sensitive account workflows<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:31-42` **Vulnerability Type**: Unpinned third-party Skill dependencies **Risk Level**: Medium ### Complete Code Snippet ```bash okx skill list --json ``` Optional skills: ```text - `okx-cex-earn` — needed for purchase guide (subscription execution) - `okx-cex-auth` — needed for authentication recovery ``` Automatic installation instructions: ```bash okx skill add okx-cex-earn okx skill add okx-cex-auth ``` Associated behavior: ```text - Install succeeds → continue - Install fails (network error, marketplace unavailable, etc.) → warn and continue - Preflight continues regardless of skill installation result ``` ### Technical Analysis The Skill automatically attempts to install two marketplace dependencies without specifying immutable versions, content digests, signatures, or verified source identities. Consequently, the code installed during activation can differ from the code reviewed with this project. This is particularly sensitive because: - `okx-cex-auth` is used for authentication recovery. - `okx-cex-earn` is handed control for subscription execution. - The latter workflow can place financial orders after user confirmation. Although the primary npm dependency is version-pinned in the Skill metadata, these two Skill dependencies are not. A compromised marketplace account, mutable release, namespace takeover, or malicious update could therefore introduce unexpected instructions or executable behavior after this package has passed review. ### Attack Path 1. An attacker compromises a dependency publisher or the marketplace distribution path, or publishes a malicious mutable version under the expected dependency name. 2. A user activates Earn Hunter when one of the optional Skills is absent. 3. Preflight automatically runs `okx skill add` for the dependency without pinning or verifying its content. 4. The malicious dependency is installed into the Agent environment. 5. A later authe ...[truncated 841 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin each dependency to an exact immutable version. 2. Where supported, verify a package digest, signature, or signed provenance statement. 3. Verify and display the resolved publisher identity, version, source repository, and checksum before installation. 4. Require explicit user confirmation before installing either dependency rather than installing automatically during preflight. 5. Separate monitoring activation from sensitive dependency installation. Install `okx-cex-auth` only when authentication recovery is requested and `okx-cex-earn` only when a purchase workflow is requested. 6. Review the dependency’s declared permissions and tool access before loading it. 7. Fail closed for purchase execution if the verified dependency is unavailable. A copy-and-paste manual fallback may remain available, but the Agent should not silently substitute an unverified package. 8. Re-verify dependency integrity before updates and before sensitive operations. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:312
Finding
Crontab management can duplicate scans and remove unrelated scheduled jobs<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:312-315` and `SKILL.md:475-477`; equivalent commands appear in `references/scheduler-setup.md:56-57,76-77` **Vulnerability Type**: Non-idempotent and overbroad scheduled-task modification **Risk Level**: Low ### Complete Code Snippet Scheduler installation: ```bash # Resolve tool directories from the current shell NODE_DIR=$(dirname "$(command -v node)") OKX_DIR=$(dirname "$(command -v okx)") JQ_DIR=$(dirname "$(command -v jq)") CRON_PATH=$(printf '%s\n' "$NODE_DIR" "$OKX_DIR" "$JQ_DIR" /usr/bin /bin | awk '!seen[$0]++' | paste -sd: -) # Add the scheduled job (crontab -l 2>/dev/null; echo "0 * * * * PATH=$CRON_PATH OKX_PROFILE=live ~/.okx/earn-hunter/scan.sh >> ~/.okx/earn-hunter/cron.log 2>&1") | crontab - ``` Pause and resume instructions: ```text **OS-crontab platforms (`cron`):** - **Pause:** `crontab -l | grep -v 'earn-hunter' | crontab -` - **Resume:** Re-add the crontab entry (same as Activation Step 5). ``` ### Technical Analysis The installation command appends a new line to the existing crontab every time it runs. It does not test for an existing managed entry, so repeated activation or resume operations can create duplicate hourly jobs. The pause command filters all crontab lines containing the substring `earn-hunter`. This is not scoped to the exact entry managed by this Skill. It can remove: - Another legitimate job whose command or comment contains that substring. - User comments documenting an unrelated job. - Multiple Earn Hunter entries without distinguishing which instance is managed. Both operations replace the user’s entire crontab from a generated stream. This is broader than necessary for managing one scheduled task. The persistence mechanism itself is justified by the declared automatic monitoring function and remains in user scope. The finding concerns unsafe lifecycle management rather than the existence of scheduling. ### Attack Path 1. The user activates or ...[truncated 1329 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Assign the managed task a unique, exact marker, for example: ```text # BEGIN OKX EARN-HUNTER MANAGED JOB 0 * * * * ... # END OKX EARN-HUNTER MANAGED JOB ``` 2. Before insertion, remove only the block between those exact markers and then add one canonical replacement. 3. Alternatively, compare against the exact normalized command rather than using a substring match. 4. Write the new crontab to a secure temporary file, validate it, and install it only after successful generation. 5. Preserve all unrelated comments, environment declarations, blank lines, and scheduled jobs. 6. Verify after installation that exactly one managed entry exists. 7. During pause or uninstall, remove only the exact managed block and report the resulting scheduler status. 8. Consider a per-user systemd timer on supported Linux systems or another scheduler with stable task identifiers, while retaining explicit user approval and uninstall instructions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (34)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill clearly instructs the agent to execute shell commands, install packages, edit files, and manipulate schedulers, but it does not declare equivalent permissions up front. This creates a trust and consent gap: users may invoke a monitoring skill without realizing it can make persistent system changes and run arbitrary shell operations.

Context-Inappropriate Capability

Low
Confidence
87% confidence
Finding
The setup flow tells users to call Telegram's getUpdates and inspect the returned payload to discover chat_id. That API can return recent messages and metadata unrelated to this skill's notification purpose, creating unnecessary exposure of conversational content and identifiers if logs or terminal history are retained.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The guide for a monitoring/notification skill includes concrete procedures for redeeming, transferring, and purchasing financial products, which expands the skill from read-only monitoring into transaction enablement. Even if framed as a handoff or manual fallback, these instructions can still lead the agent or user into executing real asset-moving actions, increasing the chance of unauthorized or mistaken trades.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The document claims earn-hunter does not directly execute write operations, but immediately provides step-by-step redeem, transfer, and purchase commands, including confirmed execution forms. This inconsistency is dangerous because downstream agents or users may trust the read-only claim while still being steered into asset-moving operations, undermining safety assumptions and permission scoping.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The documentation instructs users to copy an executable script into a persistent directory and install a recurring OS crontab entry, which expands the skill from a transient monitoring assistant into one that modifies local persistence and scheduling state. In this context the behavior appears functional rather than overtly malicious, but it still creates durable system changes that can continue running unattended and therefore meaningfully increases risk.

Vague Triggers

Medium
Confidence
79% confidence
Finding
The routing table includes broad natural-language triggers like 'monitor earn' and similar everyday phrases, which can cause the skill to activate in contexts where the user did not intend persistent monitoring setup. Because activation can install dependencies and configure scheduled tasks, accidental triggering materially increases risk.

Vague Triggers

Medium
Confidence
90% confidence
Finding
Using generic uninstall triggers like '卸载' or 'uninstall' is dangerous because they can overlap with unrelated conversation about removing other software. In this skill, the uninstall flow removes persistence artifacts and may delete the entire ~/.okx/earn-hunter directory, so ambiguous routing could cause destructive actions against the wrong target.

Missing User Warnings

Low
Confidence
71% confidence
Finding
Persisting the full PATH into env.snapshot can expose usernames, home-directory layouts, custom tool locations, or enterprise-installed binaries if the file is later read or leaked. While not a direct exploit by itself, it unnecessarily records environment details without a privacy warning or minimization.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill automates creation of persistent scheduled tasks via cron or LaunchAgent, but the warning about modifying scheduler state is not presented prominently before activation. Persistence changes are security-sensitive because they continue executing outside the current session and can generate network traffic and local side effects over time.

Missing User Warnings

Low
Confidence
76% confidence
Finding
The skill writes configuration, state, scripts, and environment snapshots under the user's home directory without an early, explicit disclosure of all filesystem modifications. Hidden persistence/state files are less severe than arbitrary writes, but they still affect user trust and can surprise users in managed environments.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The markdown tells users to install a persistent cron job and copy an executable script without prominently warning that this creates ongoing background execution on the host. That omission can lead users to authorize durable system modification without understanding the persistence or how to remove it.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documentation says notifications are sent via curl to Telegram/Lark but does not warn that scan results will leave the local system over the network. Even if expected for notifications, missing disclosure increases the risk of unintentionally transmitting sensitive financial or account-related metadata to third-party services.

External Transmission

Medium
Category
Data Exfiltration
Content
TOKEN=$(printenv "${config.telegram.bot_token_env}")
CHAT_ID=$(printenv "${config.telegram.chat_id_env}")

curl -s "https://api.telegram.org/bot${TOKEN}/sendMessage" \
  -d "chat_id=${CHAT_ID}" \
  -d "text=${message}" \
  -d "parse_mode=HTML"
Confidence
84% confidence
Finding
This file explicitly instructs the skill to send notification content and identifiers to Telegram via curl, which is an external third-party transmission channel. In this skill's context that behavior is expected, but it is still security-relevant because outbound notifications may leak sensitive trading preferences, opportunity data, or operational details if message content is not minimized and the channel is misconfigured.

External Transmission

Medium
Category
Data Exfiltration
Content
TOKEN=$(printenv "${config.telegram.bot_token_env}")
CHAT_ID=$(printenv "${config.telegram.chat_id_env}")

curl -s "https://api.telegram.org/bot${TOKEN}/sendMessage" \
  -d "chat_id=${CHAT_ID}" \
  -d "text=${message}" \
  -d "parse_mode=HTML"
Confidence
84% confidence
Finding
This file explicitly instructs the skill to send notification content and identifiers to Telegram via curl, which is an external third-party transmission channel. In this skill's context that behavior is expected, but it is still security-relevant because outbound notifications may leak sensitive trading preferences, opportunity data, or operational details if message content is not minimized and the channel is misconfigured.

Session Persistence

Medium
Category
Rogue Agent
Content
- Use `action: "list"` to find the job id.

**OS-crontab platforms (`cron`):**
- **Pause:** `crontab -l | grep -v 'earn-hunter' | crontab -`
- **Resume:** Re-add the crontab entry (same as Activation Step 5).

**macOS LaunchAgent (`launchagent`):**
Confidence
86% confidence
Finding
The skill manages OS-level persistence by editing the user's crontab to pause and resume monitoring. Persistent scheduler manipulation extends execution beyond the current session and can interfere with existing scheduled tasks if matching/removal logic is too broad.

Session Persistence

Medium
Category
Rogue Agent
Content
- No API key + `okx auth status --json` → `"status":"logged_in"` → **OAuth mode**. No `--profile` flag needed.
   - Neither → **stop**. Load `okx-cex-auth` skill and follow login steps.
5. Init config and state:
   - If `~/.okx/earn-hunter/` directory does not exist → `mkdir -p ~/.okx/earn-hunter`
   - If `~/.okx/earn-hunter/config.json` does not exist → copy `{baseDir}/config/default.json` to it
   - If `~/.okx/earn-hunter/state.json` does not exist → write `{"flash":{},"fixed":{},"flexible":{},"consecutive_failures":0,"last_error":""}`
   - If `~/.okx/earn-hunter/platform.json` does not exist → run [Platform Detection](#platform-detection-active-probe--user-confirmation)
Confidence
82% confidence
Finding
Creating and maintaining ~/.okx/earn-hunter with config, state, executable scripts, and logs is a persistence mechanism: the skill leaves executable artifacts and data behind after the session ends. In security terms this is not inherently malicious, but it is persistent local state that users must be clearly informed about.

Session Persistence

Medium
Category
Rogue Agent
Content
### Step 1 — Platform Detection & Confirmation

See [Platform Detection](#platform-detection-active-probe--user-confirmation). Probe environment → ask user to confirm → write `platform.json`.

### Step 2 — Detect Notification Channel & Confirm
Confidence
78% confidence
Finding
Writing platform.json to preserve platform and notification settings across runs is persistent state. The risk is moderate because it influences future behavior, including notification routing and scheduler logic, without requiring the user's presence on subsequent executions.

Session Persistence

Medium
Category
Rogue Agent
Content
LOG_FILE="$HOME/.okx/earn-hunter/cron.log"
INTERVAL=3600  # derive from scheduler.interval: "1h"→3600, "30m"→1800, "10m"→600

cat > ~/Library/LaunchAgents/com.okx.earn-hunter.plist << PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Confidence
90% confidence
Finding
This finding is the same underlying issue: writing a LaunchAgent plist establishes persistent scheduled execution outside the chat session. Although intended for monitoring, the persistence mechanism is powerful and should be treated as security-relevant.

Session Persistence

Medium
Category
Rogue Agent
Content
LOG_FILE="$HOME/.okx/earn-hunter/cron.log"
INTERVAL=3600  # derive from scheduler.interval: "1h"→3600, "30m"→1800, "10m"→600

cat > ~/Library/LaunchAgents/com.okx.earn-hunter.plist << PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Confidence
90% confidence
Finding
This finding is the same underlying issue: writing a LaunchAgent plist establishes persistent scheduled execution outside the chat session. Although intended for monitoring, the persistence mechanism is powerful and should be treated as security-relevant.

Session Persistence

Medium
Category
Rogue Agent
Content
cat > ~/Library/LaunchAgents/com.okx.earn-hunter.plist << PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
Confidence
90% confidence
Finding
Duplicate report of the same LaunchAgent persistence issue. The security concern is the unattended autorun behavior, not the plist syntax itself.

Session Persistence

Medium
Category
Rogue Agent
Content
cat > ~/Library/LaunchAgents/com.okx.earn-hunter.plist << PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
Confidence
90% confidence
Finding
Duplicate report of the same LaunchAgent persistence issue. The security concern is the unattended autorun behavior, not the plist syntax itself.

Session Persistence

Medium
Category
Rogue Agent
Content
cat > ~/Library/LaunchAgents/com.okx.earn-hunter.plist << PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.okx.earn-hunter</string>
Confidence
90% confidence
Finding
The com.okx.earn-hunter LaunchAgent label identifies a persistent background task. Even with benign intent, background autorun increases the blast radius of later config mistakes or supply-chain issues in the referenced script/CLI.

Session Persistence

Medium
Category
Rogue Agent
Content
<key>RunAtLoad</key>
    <true/>
</dict>
</plist>
PLIST

launchctl load ~/Library/LaunchAgents/com.okx.earn-hunter.plist
Confidence
91% confidence
Finding
Loading the LaunchAgent immediately activates persistent execution and may trigger a scan right away due to RunAtLoad. This is more sensitive than merely writing a config file because it begins unattended operation instantly.

Session Persistence

Medium
Category
Rogue Agent
Content
"macOS cron 服务未运行,已自动切换为 LaunchAgent 调度(无需 sudo,重启自动恢复)。"

**Notes:**
- **OAuth mode** → omit `OKX_PROFILE` from the plist `EnvironmentVariables` (or set to empty).
- LaunchAgent plist paths must be absolute (no `~`). The activation flow expands `$HOME` at generation time.
- `RunAtLoad: true` means the first scan runs immediately after loading.
- The script reads `config.json` / `platform.json`, writes `state.json` / `notify.log`, and sends notifications via curl to TG Bot API or Lark Webhook itself. No agent involvement needed at tick time.
Confidence
80% confidence
Finding
The notes explicitly describe LaunchAgent persistence and reboot survival, confirming the skill is designed to establish long-lived background execution. That context makes the persistence findings more credible, not less.

Session Persistence

Medium
Category
Rogue Agent
Content
**Notes:**
- **OAuth mode** → omit `OKX_PROFILE` from the plist `EnvironmentVariables` (or set to empty).
- LaunchAgent plist paths must be absolute (no `~`). The activation flow expands `$HOME` at generation time.
- `RunAtLoad: true` means the first scan runs immediately after loading.
- The script reads `config.json` / `platform.json`, writes `state.json` / `notify.log`, and sends notifications via curl to TG Bot API or Lark Webhook itself. No agent involvement needed at tick time.
- The script exits 0 and produces **no output** when there are no new opportunities and `verboseLog=false` — this is the intended silent behavior.
Confidence
77% confidence
Finding
The skill documents continued autonomous behavior via the script reading configs, writing state, and sending notifications without agent involvement. This is legitimate product behavior, but from a security perspective it is persistent automated execution and should be consented to explicitly.

Static analysis

No suspicious patterns detected.