Back to skill

Security audit

Binance Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Binance/X monitoring purpose, but it hard-codes a Feishu recipient and ignores the documented recipient configuration, so alerts may go to an unintended account.

Before installing, replace the hard-coded targetUser values in monitor.js, x-monitor.js, config.json, and config.example.json with a recipient you control, or require the scripts to load and validate config.json. Avoid the documented cron pkill restart; use one clearly scoped lifecycle manager and document how to stop or remove it. Confirm you are comfortable sending monitored Binance/X content through Jina AI and Feishu-related notification handling.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
monitor.js:21
Finding
Hard-Coded Feishu Recipient and Ignored Runtime Configuration<![CDATA[ ## Vulnerability Details **File Location**: `monitor.js:21-27`, `x-monitor.js:31-37`, `config.json:1-5`, `config.example.json:1-6` **Vulnerability Type**: Hard-coded destination and ineffective configuration **Risk Level**: Medium ### Vulnerable Code `monitor.js:21-27`: ```javascript targetUser: 'ou_c1bac9d5fa30ac354a3705a9c87993dd', // Notification channel channel: 'feishu' ``` `x-monitor.js:31-37`: ```javascript targetUser: 'ou_c1bac9d5fa30ac354a3705a9c87993dd', // Notification channel channel: 'feishu' ``` `config.json:1-5`: ```json { "checkIntervalSeconds": 30, "targetUser": "ou_c1bac9d5fa30ac354a3705a9c87993dd", "channel": "feishu" } ``` The queue destinations are constructed directly from the hard-coded values: ```javascript target: `user:${CONFIG.targetUser}`, ``` ### Technical Analysis Both monitoring scripts define a fixed Feishu open ID in source code. Neither script reads `config.json`, despite the documentation representing that file as the mechanism for selecting the recipient, channel, and polling interval. Consequently, changing `config.json` has no effect. Every announcement notification generated by `monitor.js` and every X notification generated by `x-monitor.js` contains the embedded recipient. The example configuration also contains the same real-looking identifier instead of a neutral placeholder, increasing the chance that users will deploy the Skill without noticing the fixed routing. This does not expose system credentials or grant operating-system privileges. However, it violates destination integrity and can cause notifications to be routed to an account that the deploying user did not authorize. ### Attack Path 1. A user installs the Skill and follows the documentation. 2. The user either leaves the example configuration unchanged or changes `targetUser` in `config.json`. 3. The monitoring scripts ignore that configuration and use the recipient embedded in source code. 4. `monitor.js` writes the fixed t ...[truncated 1286 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all concrete recipient identifiers from source code and example files. 2. Replace the example value with an unmistakable placeholder such as `ou_xxxxxxxxxxxxxx`. 3. Load configuration once at startup and validate it before initiating network activity: ```javascript const configPath = path.join(__dirname, 'config.json'); const userConfig = JSON.parse(fs.readFileSync(configPath, 'utf8')); if ( typeof userConfig.targetUser !== 'string' || !/^ou_[A-Za-z0-9]+$/.test(userConfig.targetUser) ) { throw new Error('A valid Feishu targetUser must be configured explicitly'); } const CONFIG = { checkIntervalMs: Math.max( Number(userConfig.checkIntervalSeconds || 30) * 1000, 10000 ), targetUser: userConfig.targetUser, channel: userConfig.channel || 'feishu' }; ``` 4. Fail closed if the recipient is absent instead of silently using a built-in account. 5. Show the resolved recipient and request confirmation during first-time setup where practical. 6. Add automated tests proving that changes to `config.json` alter the generated queue target. 7. Keep deployment-specific `config.json` excluded from version control, as the existing `.gitignore` intends. ]]>

T06 · System Persistence

Warning
Location
README.md:437
Finding
Persistent Cron Recommendation Uses Overbroad Process Matching<![CDATA[ ## Vulnerability Details **File Location**: `README.md:437-438` **Vulnerability Type**: Unsafe scheduled process termination **Risk Level**: Medium ### Vulnerable Code ```cron 0 0 * * * pkill -f "node monitor.js" && pkill -f "node x-monitor.js" && cd /path/to/skill && ./start-all.sh & ``` ### Technical Analysis The documentation recommends installing a daily cron job that invokes `pkill -f`. The `-f` option matches patterns against the complete command line rather than a verified process ID or a uniquely owned service. Any unrelated process whose command line includes `node monitor.js` or `node x-monitor.js` can therefore be terminated. The command is also persistent: after being placed in a user's crontab, it executes every day across sessions until explicitly removed. The persistence is disclosed and is intended to keep a continuous monitor operational, so it is not a covert backdoor. Nevertheless, the cron implementation exceeds what is necessary for safe lifecycle management and may affect programs outside this project. The separate systemd recommendation is materially safer because it defines an explicit service and specifies `User=your-user`. Enabling that service requires administrative access to register it, but the resulting monitor runs as the selected unprivileged account. That systemd approach is proportionate to the declared continuous-monitoring function when installed with informed user consent. ### Attack Path 1. An operator copies the documented command into a crontab. 2. Another legitimate Node.js process runs under the same user and has a command line containing one of the matching strings. 3. At midnight, cron executes the `pkill -f` commands. 4. `pkill` terminates all accessible matching processes, not only the instances launched from this project. 5. The script then starts another copy of the monitors, potentially while an existing instance survived or while systemd is also managing the service. An attacker who can influ ...[truncated 1031 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the cron-based `pkill -f` recommendation. 2. Use one lifecycle manager only. For persistent deployment, prefer the documented systemd service and restart it by exact unit name: ```bash systemctl --user restart binance-monitor.service ``` 3. Where a system service is genuinely required, retain `User=your-user`, use an absolute executable path, and add hardening controls such as: ```ini [Service] User=your-user WorkingDirectory=/absolute/path/to/binance-announce-monitor ExecStart=/usr/bin/node /absolute/path/to/binance-announce-monitor/monitor.js Restart=on-failure NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/absolute/path/to/binance-announce-monitor/runtime ``` 4. If systemd cannot be used, maintain PID files in a dedicated runtime directory and verify both process ownership and executable identity before signaling a PID. 5. Document exact removal commands for any persistent service or scheduled task. 6. Warn users not to combine `nohup`, cron, screen, and systemd for the same deployment. 7. Do not run the monitors or lifecycle commands as root; their declared functionality only requires outbound HTTPS and write access to a small application-owned state directory. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
monitor.js:65
Finding
Unbounded HTTP Response Buffering and Missing Network Safety Controls<![CDATA[ ## Vulnerability Details **File Location**: `monitor.js:65-87`, `x-monitor.js:78-100` **Vulnerability Type**: Resource exhaustion through unbounded remote responses **Risk Level**: Low ### Vulnerable Code `monitor.js:65-87`: ```javascript function fetchAnnouncements() { return new Promise((resolve, reject) => { https.get(CONFIG.announceUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Accept': 'application/json' } }, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const json = JSON.parse(data); const articles = json.data?.catalogs?.[0]?.articles || []; resolve(articles); } catch (e) { reject(new Error('JSON parse failed: ' + e.message)); } }); }).on('error', (e) => { reject(new Error('Network request failed: ' + e.message)); }); }); } ``` `x-monitor.js:78-100` follows the same pattern: ```javascript function fetchTweets(account) { return new Promise((resolve, reject) => { https.get(account.url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Accept': 'text/plain' } }, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const tweets = parseJinaResponse(data, account); resolve(tweets); } catch (e) { reject(new Error('Parse failed: ' + e.message)); } }); }).on('error', (e) => { reject(new Error('Network request failed: ' + e.message)); }); ...[truncated 2168 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set an explicit request timeout and destroy timed-out requests. 2. Reject responses whose status code is outside the expected successful range. 3. Validate the expected content type before buffering the body. 4. Enforce a conservative maximum response size and abort once exceeded. 5. Ensure that each Promise settles only once and that aborted responses are cleaned up. 6. Apply the same helper to both monitors. For example: ```javascript function getLimited(url, expectedType, maxBytes = 1024 * 1024) { return new Promise((resolve, reject) => { let settled = false; const fail = (error) => { if (settled) return; settled = true; reject(error); }; const req = https.get(url, { headers: { 'User-Agent': 'BinanceMonitor/1.1', 'Accept': expectedType } }, (res) => { if (res.statusCode !== 200) { res.resume(); return fail(new Error(`Unexpected HTTP status: ${res.statusCode}`)); } const type = String(res.headers['content-type'] || '').toLowerCase(); if (!type.includes(expectedType.split('/')[1])) { res.resume(); return fail(new Error(`Unexpected content type: ${type}`)); } let size = 0; const chunks = []; res.on('data', (chunk) => { size += chunk.length; if (size > maxBytes) { res.destroy(new Error('Response exceeded size limit')); return; } chunks.push(chunk); }); res.on('end', () => { if (settled) return; settled = true; resolve(Buffer.concat(chunks).toString('utf8')); }); res.on('error', fail); }); req.setTimeout(10000, () => ...[truncated 260 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (32)

Ae1

High
Category
analysis-evasion
Content
| `monitor.js` | 主监控脚本 |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| `monitor.js` | 主监控脚本 |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Memory Manipulation

High
Category
Memory Poisoning
Content
const tweetIds = Object.keys(state.seenTweets);
    if (tweetIds.length > 200) {
        tweetIds.slice(0, tweetIds.length - 200).forEach(id => {
            delete state.seenTweets[id];
        });
    }
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README explicitly states that monitored Binance/X content is fetched via Jina AI and delivered via Feishu, but it does not clearly warn users that monitored content and related metadata may be transmitted to third-party services. In a monitoring skill, this matters because users may assume content stays local except for notifications, while the design depends on external processors.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
sudo systemctl start binance-monitor

# 查看状态
sudo systemctl status binance-monitor

# 查看日志
sudo journalctl -u binance-monitor -f
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The entire skill description and operating instructions are presented in Chinese, with no indication that other languages are supported or that the locale restriction is intentional and justified. Per the policy, forcing a specific language without user opt-in or documented justification is a natural-language policy violation.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill describes continuous polling of Binance/X and immediate delivery to Feishu, but it does not clearly warn users that content and metadata are transmitted to external services. This can mislead users about privacy exposure, especially if monitored content, recipient identifiers, timestamps, or logs are sensitive in their environment.

Session Persistence

Medium
Category
Rogue Agent
Content
### 后台运行(推荐)

```bash
# 使用 nohup
nohup node monitor.js > monitor.log 2>&1 &

# 或使用 screen
Confidence
65% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
### 后台运行(推荐)

```bash
# 使用 nohup
nohup node monitor.js > monitor.log 2>&1 &

# 或使用 screen
Confidence
65% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
### 后台运行(推荐)

```bash
# 使用 nohup
nohup node monitor.js > monitor.log 2>&1 &

# 或使用 screen
Confidence
65% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
### 后台运行(推荐)

```bash
# 使用 nohup
nohup node monitor.js > monitor.log 2>&1 &

# 或使用 screen
Confidence
65% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
### 后台运行(推荐)

```bash
# 使用 nohup
nohup node monitor.js > monitor.log 2>&1 &

# 或使用 screen
Confidence
65% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
80% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
# Ctrl+A, D 退出屏幕

# 或使用 systemd(生产环境)
sudo systemctl enable binance-monitor
sudo systemctl start binance-monitor
```
Confidence
80% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

External Transmission

Medium
Category
Data Exfiltration
Content
const OKX_ANNOUNCE_URL = 'https://www.okx.com/api/v5/support/announcements';

// 示例:Bybit 公告
const BYBIT_ANNOUNCE_URL = 'https://api.bybit.com/spot/v1/announcement';
```

### 添加其他通知渠道
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
const OKX_ANNOUNCE_URL = 'https://www.okx.com/api/v5/support/announcements';

// 示例:Bybit 公告
const BYBIT_ANNOUNCE_URL = 'https://api.bybit.com/spot/v1/announcement';
```

### 添加其他通知渠道
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The file presents its description and runtime messages in Chinese, including the stated purpose and multiple console outputs, without any indication that the user can choose another language or that the skill is intentionally limited to Chinese-speaking users. This is a natural-language locale constraint that appears hard-coded rather than optional.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The file’s natural-language description and user-facing messages are written in Chinese and present the skill as a Binance notification sender without any indication that language is configurable or optional. Under the stated policy, forcing a specific language or locale without user opt-in is a natural-language policy violation unless clearly justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The script's user-facing comments and runtime messages are written in Chinese throughout, including errors, status, and usage guidance. For a general-purpose startup script, this imposes a specific language on users without any opt-in, fallback, or documented region-specific justification.

Static analysis

No suspicious patterns detected.