Back to skill

Security audit

Investigator

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent public OSINT helper, but one shipped domain-check script can execute shell commands from an unsanitized domain input and the skill performs broad third-party lookups on potentially sensitive identifiers.

Review carefully before installing. Do not run the domain helper until its shell command injection is fixed by validating domains and invoking whois/dig without bash. Use the skill only for authorized, public, defensive investigations, and remember that profile, IP, domain, and HIBP checks can disclose the target identifier to third-party services. Protect any exported reports because they may aggregate personal data.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check_domain.py:37
Finding

OS Command Injection Through Unsanitized Domain Input

Content
View full analysis

Vulnerability Details

File Location: scripts/check_domain.py, lines 37–46
Vulnerability Type: OS command injection caused by unsafe shell interpolation
Risk Level: High

Vulnerable Code

python
domain = sys.argv[1].strip()
whois_out = 'WHOIS command not available'
if shutil.which('whois'):
    whois_out = run(['bash', '-lc', f'whois {domain} | sed -n "1,80p"'])
result = {
    'domain': domain,
    'whois': whois_out,
    'rdap': fetch_rdap(domain),
    'dns_a': run(['bash', '-lc', f'dig +short {domain} A']),
    'dns_mx': run(['bash', '-lc', f'dig +short {domain} MX']),
    'dns_txt': run(['bash', '-lc', f'dig +short {domain} TXT']),
}

Technical Analysis

The domain value is read directly from sys.argv[1] and interpolated into four command strings passed to bash -lc. The application performs no hostname validation and applies no shell escaping.

Although subprocess.check_output is invoked with an argument list inside the run function, this does not prevent injection because the code explicitly starts Bash and asks it to interpret the constructed string. Shell metacharacters contained in the domain value—such as ;, |, command substitutions, redirects, or logical operators—are therefore interpreted as shell syntax.

For example, a value shaped like the following would append an additional command:

text
example.com; id #

The issue affects the WHOIS invocation when whois is installed and all three dig invocations. The DNS paths remain exploitable regardless of whether the optional WHOIS utility is available, provided the script is invoked and Bash can execute the injected command.

Attack Path

  1. An attacker supplies a crafted domain to a workflow that invokes scripts/check_domain.py.
  2. The script reads the attacker-controlled string from sys.argv[1].
  3. The string is inserted verbatim into the WHOIS and DNS command strings.
  4. bash -lc parses the supplied shell metacharacters.
  5. Bash executes t ...[truncated 1271 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the shell interpreter entirely. Invoke each utility with a literal argument array:
python
whois_out = run(['whois', domain])
dns_a = run(['dig', '+short', domain, 'A'])
dns_mx = run(['dig', '+short', domain, 'MX'])
dns_txt = run(['dig', '+short', domain, 'TXT'])
  1. Truncate WHOIS output in Python rather than piping it through sed:
python
def first_lines(value, limit=80):
    return '\n'.join(value.splitlines()[:limit])
  1. Strictly validate and normalize the input before use. Accept only a syntactically valid DNS hostname, enforce total and per-label length limits, reject empty labels and shell/control characters, and handle internationalized domain names through an explicit IDNA normalization policy.

  2. Do not rely only on shell escaping. Quoting may reduce immediate exploitability, but removing bash -lc is the safer architectural correction.

  3. Use least privilege and process isolation. Run the helper as a restricted account with limited filesystem access, no unnecessary credentials, and constrained outbound networking.

  4. Add regression tests covering metacharacters and malformed values, including semicolons, pipes, substitutions, redirects, newlines, leading hyphens, and oversized input. Tests should verify that invalid values are rejected and never reach a subprocess.

  5. Return structured validation errors before starting WHOIS, RDAP, or DNS requests so callers can distinguish malformed targets from lookup failures.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (13)

Tainted flow: 'headers' from os.environ.get (line 31, 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/check_hibp.py (reported line 36)May include surrounding context.

python
'user-agent': 'OpenClaw-username-email-investigator/1.0',
    }
    try:
        r = requests.get(url, headers=headers, timeout=20)
        if r.status_code == 404:
            print(json.dumps({'email': email, 'breach_found': False, 'breaches': []}, ensure_ascii=False, indent=2))
            return

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a broad public-footprint/OSINT research capability. The actual code chunk does not perform any investigative, enrichment, lookup, correlation, or reporting logic beyond basic JSON validation and pretty-print export. While JSON export could be a small supporting utility within such a skill, this code by itself materially does not implement the described primary purpose. Therefore this chunk is a mismatch relative to the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes a broad OSINT skill with online investigation and enrichment capabilities across many target types. The supplied code chunk instead only performs local username variant generation from a single input string and prints the results as JSON. This is at best a narrow helper utility that could support username-based searching, but it does not itself carry out the described investigative behavior. Therefore the actual behavior is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 79)May include surrounding context.

md
12. Return a concise human summary or a structured report depending on the request.
13. Export JSON if requested.

## Output rules

Always distinguish between:
- confirmed public match

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README explicitly advertises collection of public profile links, image URLs, and JSON export, but it does not provide any concrete guidance on privacy, data minimization, retention, consent, or safe handling of potentially sensitive personal data. In an OSINT skill, this omission increases misuse risk because even publicly accessible data can become privacy-invasive when aggregated, correlated, and exported into structured artifacts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill instructs use of scripts, web access, file reads, and potentially environment-backed configuration, but it does not declare an explicit tool scope such as allowed-tools or permissions. That increases the risk of over-broad agent execution, because a caller or runtime may permit shell, network, and file capabilities beyond what is minimally required for the task.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation text is extremely broad, covering many target types and many user intents, which can cause the agent to invoke this skill in ambiguous or sensitive contexts. In an OSINT skill, overbroad routing is more dangerous because it can steer ordinary requests into investigative workflows involving network access, data aggregation, and potential privacy-sensitive enrichment.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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.

Content

Scanner excerpt · references/configuration.md (reported line 21)May include surrounding context.

Example:

bash
mkdir -p ~/.openclaw/secrets
printf '%s\n' 'your_hibp_api_key' > ~/.openclaw/secrets/hibp_api_key
chmod 600 ~/.openclaw/secrets/hibp_api_key

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/configuration.md (reported line 23)May include surrounding context.

bash
mkdir -p ~/.openclaw/secrets
printf '%s\n' 'your_hibp_api_key' > ~/.openclaw/secrets/hibp_api_key
chmod 600 ~/.openclaw/secrets/hibp_api_key

Resolution order

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This subprocess wrapper is later used with bash -lc and f-string interpolation of the user-controlled domain value, which creates a shell command injection path. An attacker can supply shell metacharacters in the domain argument and execute arbitrary commands on the host running the skill, making this far more than a generic subprocess false positive.

Content

Scanner excerpt · scripts/check_domain.py (reported line 11)May include surrounding context.

python
def run(cmd):
    try:
        out = subprocess.check_output(cmd, stderr=subprocess.STDOUT, text=True, timeout=15)
        return out.strip()
    except Exception as e:
        return f'ERROR: {e}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script transmits a user-supplied email address to an external third-party breach-checking service, which is privacy-sensitive data disclosure. In an OSINT skill context this is more dangerous because users may investigate third parties, and the script provides no explicit consent, notice, or policy guardrails before sending that identifier off-platform.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script sends the queried IP address to external third-party services (ipinfo.io and ip-api.com) without any in-code disclosure, consent flow, or control over data sharing. Even though the target is an IP address used for OSINT enrichment, transmitting user-supplied targets to outside services can leak investigation activity, expose sensitive internal or customer IPs, and create privacy or compliance issues.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends the supplied username to a dozen third-party platforms by default, which creates an external disclosure of investigator interest and may expose the target identifier to those services, logs, and intermediaries without any notice or consent checkpoint. In an OSINT skill, this is especially relevant because usernames often correlate to real individuals and the act of querying many services can itself create privacy, attribution, or operational-security risk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.