Back to skill

Security audit

Async Task

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent async-task purpose, but it can send session-linked task content to active sessions or arbitrary custom endpoints with insufficient transport and recipient safeguards.

Review this before installing if tasks may contain secrets, private code, customer data, or sensitive logs. Prefer an explicit OPENCLAW_SESSION, avoid the direct push command in multi-session contexts, use only trusted HTTPS custom endpoints with scoped tokens, and treat the local async-task history file as sensitive.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
async-task.js:120
Finding

Custom push endpoint permits plaintext transmission of bearer tokens and session data

Content
View full analysis
{ const url = new URL(CUSTOM_PUSH_URL); const lib = url.protocol === 'https:' ? https : http; const data = JSON.stringify({ sessionId: sessionId, content: content, role: 'assistant' }); const headers = { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) }; if (CUSTOM_AUTH_TOKEN) { headers['Authorization'] = `Bearer ${CUSTOM_AUTH_TOKEN}`; } const req = lib.request({ hostname: url.hostname, port: url.port || (url.protocol === 'https:' ? 443 : 80), path: url.pathname, method: 'POST', headers: headers }, (res) => { let body = ''; res.on('data', chunk => body += chunk); res.on('end', () => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(body); } else { reject(new Error(`HTTP ${res.statusCode}: ${body}`)); } }); }); ``` ### Technical Analysis The custom push implementation explicitly selects Node.js's unencrypted `http` module whenever `ASYNC_TASK_PUSH_URL` does not use HTTPS. The request can contain all of the following sensitive values: - The `ASYNC_TASK_AUTH_TOKEN` bearer token - The target session identifier - Agent-generated result or error content - The asserted message role No protocol restriction, TLS requirement, or warning prevents use of an `http:` endpoint. Consequently, an HTTP configuration causes authentication and session information to be transmitted in plaintext. A network-positioned attacker can observe or modify these requests. This issue a ...[truncated 1310 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
async-task.js:17
Finding

Task and session state is persisted without explicitly restrictive file permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
async-task.js:63
Finding

Automatic active-session selection can send task content to the wrong conversation

Content
View full analysis
/dev/null`, { encoding: 'utf8', timeout: 5000 }); const data = JSON.parse(output); if (data.sessions && data.sessions.length > 0) { // 返回最近活跃的 session key const session = data.sessions[0]; if (session.key) { // 处理不同格式: "webchat:xxx" -> "xxx", "telegram:123" -> keep as is const parts = session.key.split(':'); return parts.length > 1 ? parts.slice(1).join(':') : session.key; } } } catch (err) { // 静默失败 } return null; } ``` The inferred identifier is subsequently used as the message recipient: ```javascript const sessionId = state.currentTask?.sessionId || getActiveSession(); if (!sessionId) { console.error('Error: No session ID. Set OPENCLAW_SESSION or ensure CLI is available.'); process.exit(1); } try { await pushMessage(sessionId, `✅ ${message}`); ``` ### Technical Analysis When no explicit session environment variable is present, the implementation requests up to five active sessions and unconditionally selects `data.sessions[0]`. It does not verify that this session initiated the task, belongs to the expected user, or corresponds to the current agent invocation. The code also removes the first colon-delimited component from every session key. Although the comment suggests format-specific handling, the implementation applies stripping generically. This can alter namespaced identifiers and create ambiguity between ch ...[truncated 1870 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly promotes sending task updates and results to an active session or to a custom HTTP endpoint, but it does not warn that task content may leave the current process boundary and could be transmitted to a remote service. In an agent setting, long-running tasks often involve sensitive prompts, code, logs, or analysis results, so this omission can lead to unintentional disclosure if operators assume the mechanism is purely local or do not apply data minimization.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger list includes generic phrases like "long running," "timeout," and "background task," which are likely to appear in normal user or agent conversation and can cause this skill to activate in unintended contexts. Because the skill is designed to run commands and push results asynchronously, accidental activation increases the chance of unnecessary command execution or data being sent outside the normal response flow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill documents sending sessionId, assistant content, and authentication data to a custom external endpoint without warning about data sensitivity, trust boundaries, or validation requirements. In practice, this can lead to session-linked content exfiltration to arbitrary servers, especially if a user or operator configures an untrusted push URL or assumes the feature is safe by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The header comment presents the skill description entirely in Chinese, while the rest of the CLI help and behavior are not documented as intentionally region-specific. Under the policy, language or locale constraints should not be imposed without opt-in or clear justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The optional custom HTTP push feature sends session identifiers and arbitrary task content to a user-configurable remote endpoint, which can expose sensitive conversational data outside the primary platform boundary. While this appears to be intended functionality for advanced users rather than overtly malicious behavior, the code provides no validation, allowlisting, confirmation prompt, or visible warning to reduce accidental exfiltration risk.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
async-task.js:29