Back to skill

Security audit

CEO小茂能力包

Security checks for vulnerabilities and agentic risk

Overview

This is a real business messaging automation skill, but it needs Review because it can automatically monitor chats, send messages/files, store customer data, and fetch untrusted media with limited safeguards.

Review carefully before installing. Use only trusted HTTPS provider endpoints, test with non-production accounts and recipients, restrict workspace file permissions, confirm customer consent for monitoring and retention, and patch or disable auto-discovery, unconditional catalog sending, and unvalidated media downloads before running the auto-reply loop unattended.

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
scripts/oneabc.js:2
Finding

Credentials and Sensitive Request Data Can Be Sent to Arbitrary Configured Endpoints

Content
View full analysis
{ const h = {}; h['Author' + 'ization'] = ACCESS_CREDENTIAL; h['Content-Type'] = 'application/json'; return h; })(), body: JSON.stringify({ model, messages: [{ role: 'user', content: prompt }], max_tokens: maxTokens }) }); const data = await response.json(); if (data.error) return `❌ Error: ${data.error.message}`; return data.choices?.[0]?.message?.content || JSON.stringify(data, null, 2); } ``` ```javascript const response = await fetch(`${BASE_URL}/v1/models`, { headers: (() => { const h = {}; h['Author' + 'ization'] = ACCESS_CREDENTIAL; return h; })() }); ``` `scripts/send_whatsapp.py`: ```python SERVICE_URL = os.environ.get('GREEN_API_URL') INSTANCE_ID = os.environ.get('GREEN_API_INSTANCE_ID') SERVICE_CREDENTIAL = ( os.environ.get('GREEN_API_CREDENTIAL') or os.environ.get('SERVICE_CREDENTIAL') ) def send_message(phone, message): phone = phone.strip().replace('+', '').replace(' ', '') chat_id = f"{phone}@c.us" url = f"{SERVICE_URL}/waInstance{INSTANCE_ID}/sendMessage/{SERVICE_CREDENTIAL}" response = requests.post( url, json={'chatId': chat_id, 'message': message}, timeout=30 ) result = response.json() return ('idMessage' in resul ...[truncated 3443 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/auto_reply.py:176
Finding

Untrusted Message URLs Are Downloaded Without SSRF or Size Protections

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auto_reply.py:96
Finding

Customer Identifiers and Message Content Are Persisted in Plaintext Without Access or Retention Controls

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (37)

Tainted flow: 'url' from os.environ.get (line 133, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 123)May include surrounding context.

python
def api(url, method='POST', json_data=None):
    try:
        if method == 'GET':
            r = requests.get(url, timeout=15)
        else:
            r = requests.post(url, json=json_data, timeout=20)
        if r.status_code == 200 and r.text.strip():

Tainted flow: 'url' from os.environ.get (line 133, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 125)May include surrounding context.

python
if method == 'GET':
            r = requests.get(url, timeout=15)
        else:
            r = requests.post(url, json=json_data, timeout=20)
        if r.status_code == 200 and r.text.strip():
            return r.json()
    except Exception as e:

Tainted flow: 'API_URL' from os.environ.get (line 24, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 152)May include surrounding context.

python
with open(file_path, 'rb') as f:
            files = {'file': ((file_name or os.path.basename(file_path)), f, mime)}
            data = {'chatId': f"{phone}@c.us", 'caption': caption}
            r = requests.post(
                f"{API_URL}/waInstance{INSTANCE_ID}/sendFileByUpload/{SERVICE_CREDENTIAL}",
                data=data, files=files, timeout=120
            )

Tainted flow: 'url' from os.environ.get (line 133, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The script downloads a file from a URL taken from incoming message metadata without validating the scheme, host, or content type. That enables SSRF-like behavior against internal services or attacker-chosen endpoints, and also allows untrusted content to be fetched and stored locally.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 179)May include surrounding context.

python
def download_file(url, save_path):
    try:
        r = requests.get(url, timeout=60, stream=True)
        if r.status_code == 200:
            with open(save_path, 'wb') as f:
                for chunk in r.iter_content(8192): f.write(chunk)

Tainted flow: 'url' from os.environ.get (line 15, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/send_whatsapp.py (reported line 16)May include surrounding context.

python
phone = phone.strip().replace('+', '').replace(' ', '')
    chat_id = f"{phone}@c.us"
    url = f"{SERVICE_URL}/waInstance{INSTANCE_ID}/sendMessage/{SERVICE_CREDENTIAL}"
    response = requests.post(url, json={'chatId': chat_id, 'message': message}, timeout=30)
    result = response.json()
    return ('idMessage' in result), result

Tainted flow: 'url' from os.environ.get (line 16, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/send_whatsapp_batch.py (reported line 17)May include surrounding context.

python
phone = phone.strip().replace('+', '').replace(' ', '')
    chat_id = f"{phone}@c.us"
    url = f"{SERVICE_URL}/waInstance{INSTANCE_ID}/sendMessage/{SERVICE_CREDENTIAL}"
    return requests.post(url, json={'chatId': chat_id, 'message': message}, timeout=30).json()

if __name__ == '__main__':
    if len(sys.argv) < 2:

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script automatically enumerates chats, discovers new contacts, and begins monitoring message history without any consent, notification, or scope restriction. In this skill context, which is explicitly designed for broad business workflow automation, that makes privacy over-collection more dangerous because it silently expands monitoring beyond explicitly onboarded contacts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill bundles capabilities that can read/write files, access environment secrets, invoke shell commands, and perform outbound network actions, but it does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this increases the risk of over-privileged execution because users and runtime policy layers are not clearly informed that the skill can send messages, modify local state, and use credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill documentation describes email and WhatsApp sending workflows but does not prominently warn that these scripts contact real external recipients and may transmit attachments or business content. This can lead to unintended spam, data leakage, or reputational damage if a user runs examples against real contact lists without realizing the effect.

Content

No source excerpt is available for this finding.

Tainted flow: 'LOG_FILE' from os.environ.get (line 34, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 100)May include surrounding context.

python
line = f"[{ts}] {msg}"
    print(line)
    try:
        with open(LOG_FILE, 'a', encoding='utf-8') as f:
            f.write(line + '\n')
    except Exception:
        pass

Tainted flow: 'STATE_FILE' from os.environ.get (line 33, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 117)May include surrounding context.

python
return state

def save_state(state):
    with open(STATE_FILE, 'w') as f:
        json.dump(state, f, ensure_ascii=False, indent=2)

def api(url, method='POST', json_data=None):

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The prompt explicitly instructs the AI to 'reply in English' regardless of the customer's language or any operator preference. This is a language-policy violation because it imposes a specific language without offering choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 197)May include surrounding context.

python
)
    try:
        openclaw_bin = shutil.which('openclaw')
        result = subprocess.run(
            [openclaw_bin, 'agent', '--agent', AI_AGENT,
             '--message', prompt, '--timeout', '40'],
            capture_output=True, text=True, timeout=50

Tainted flow: 'AI_AGENT' from os.environ.get (line 28, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 197)May include surrounding context.

python
)
    try:
        openclaw_bin = shutil.which('openclaw')
        result = subprocess.run(
            [openclaw_bin, 'agent', '--agent', AI_AGENT,
             '--message', prompt, '--timeout', '40'],
            capture_output=True, text=True, timeout=50

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 213)May include surrounding context.

python
def ai_generate_reply(prompt_text):
    try:
        openclaw_bin = shutil.which('openclaw')
        result = subprocess.run(
            [openclaw_bin, 'agent', '--agent', AI_AGENT,
             '--message', prompt_text, '--timeout', '25'],
            capture_output=True, text=True, timeout=35

Tainted flow: 'AI_AGENT' from os.environ.get (line 28, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 213)May include surrounding context.

python
def ai_generate_reply(prompt_text):
    try:
        openclaw_bin = shutil.which('openclaw')
        result = subprocess.run(
            [openclaw_bin, 'agent', '--agent', AI_AGENT,
             '--message', prompt_text, '--timeout', '25'],
            capture_output=True, text=True, timeout=35

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script persists customer phone numbers and message content into local notification files without explicit warning or consent controls. In a business messaging skill, this can expose sensitive contact and conversation data to anyone with filesystem access and may violate privacy/compliance expectations.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Persistent storage of customer identifiers and message contents enlarges the local attack surface and creates lasting exposure of sensitive business communications. Because this runs continuously and logs operational workflow data, compromise of the host or backups could reveal contact intelligence and message history.

Content

No source excerpt is available for this finding.

Tainted flow: 'NOTIFY_FILE' from os.environ.get (line 36, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 359)May include surrounding context.

python
n = json.load(open(NOTIFY_FILE)) if os.path.exists(NOTIFY_FILE) else []
    n.append({'time': datetime.now().isoformat(), 'phone': phone, 'name': phone,
              'message': text, 'text': text})
    json.dump(n, open(NOTIFY_FILE, 'w'), ensure_ascii=False, indent=2)

def get_chat(phone, count=5):
    return api(

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Automatic discovery plus chat-history retrieval broadens the set of conversations collected beyond direct interaction handling. In this monitoring-heavy skill, that increases surveillance scope and data exposure, especially if operators did not intentionally enroll those contacts for automated processing.

Content

No source excerpt is available for this finding.

Tainted flow: 'CUSTOMERS_FILE' from os.environ.get (line 35, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/auto_reply.py (reported line 385)May include surrounding context.

python
log(f"🆕 自动发现新回复号码: {phone}")
        if new_found:
            all_p = list(known | set(new_found))
            json.dump(all_p, open(CUSTOMERS_FILE, 'w'), ensure_ascii=False)
            log(f"✅ 联系人列表已更新: {len(all_p)} 个号码")
        return new_found
    except Exception as e:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code sends all configured catalog files after any incoming text message, regardless of whether the user requested a catalog or the AI inferred that action. In a sales automation context this can leak more business material than intended, increase spam behavior, and violate least-disclosure expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Customer-supplied images are downloaded and written to local disk without any transparency, retention control, or cleanup. This creates unnecessary persistence of potentially sensitive customer content and increases exposure if the host is later compromised.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Chrome options explicitly set '--lang=en-US', which imposes a specific language/locale on the skill's behavior. The file does not provide an opt-in, configuration option, or documented regional justification for this locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill embeds Chinese-only branding/instructions ("CEO小茂") in its user-facing docstring, and the generated setup file continues that locale-specific presentation. Under the policy, forcing a specific language or locale without explicit user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/oneabc.js:2