T09 · Insecure Skill Coding Practices
- Location
scripts/lead_enrich.py:115- Finding
Hostname-Only SSRF Filtering Can Be Bypassed Through DNS Resolution or Redirects
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a review concern because it performs lead enrichment but also collects scraped email addresses and has an implemented outreach-drafts feature that contradicts its documentation and can send lead data to an external LLM.
Review before installing. Use only with public company data, avoid sensitive CRM exports, assume scraped email addresses may be collected despite the privacy setting, and assume MiniMax may receive company or lead details whenever MINIMAX_API_KEY is set and enrichment or drafts are run. Choose output paths carefully because existing files may be replaced.
scripts/lead_enrich.py:115Hostname-Only SSRF Filtering Can Be Bypassed Through DNS Resolution or Redirects
scripts/lead_enrich.py:150Personal Email Collection Occurs Despite an Enabled Privacy Control
scripts/lead_enrich.py:415Undocumented Outreach Command Transmits Lead Data to an External LLM
The activation guidance includes broad phrases like 'look up a company' and 'find info on a company', which can overlap with ordinary user requests and cause the skill to trigger unexpectedly. In a skill that performs network scraping and writes output files, overly broad invocation criteria increase the chance of unintentional data collection, external requests, and misuse outside the user's precise intent.
The tool advertises a no_personal_emails privacy control, but never applies it when scraping and exporting emails. This can cause collection and storage of personal email addresses despite user expectations, creating privacy, compliance, and data-handling risk in a lead-enrichment context where scraped contact data is the primary output.
The script sends company names, domains, and scraped descriptions to an external LLM service without an explicit consent prompt or prominent disclosure at the point of use. In a data-enrichment workflow, users may not realize scraped or customer-derived data leaves the local environment, which can create privacy, contractual, or regulatory exposure.
This finding is valid because the tool transmits lead-enrichment data to a third-party service over the network. While the destination is pinned to a legitimate HTTPS API and not obviously malicious, the skill context makes outbound transfer more sensitive because the application processes scraped business/contact data that may be subject to privacy expectations or contractual limits.
)
LLM_API_KEY_MISSING_WARNED = True
return None
base_url = "https://api.minimax.chat/v1" # pinned, no env override
try:
data = json.dumps({
"model": model,
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.
# Allow env override
env_level = os.environ.get("CLAWHUB_LOG_LEVEL", "").upper()
if env_level in ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"):
level = getattr(logging, env_level)
logging.basicConfig(
level=level,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
The docstring represents the function as a robots.txt compliance check, but the implementation merely scans for any Disallow: line and compares it to the path, without parsing User-agent sections or honoring the passed user_agent argument semantically. This is an intent/documentation mismatch because the code suggests standards-aware enforcement while implementing only a simplistic approximation.
The enrich command opens the user-supplied output path in write mode, which will silently overwrite any existing file. While writing output is part of the tool's purpose, there is no visible disclosure or confirmation about the destructive overwrite behavior.
The drafts command writes to the specified markdown output using write mode, replacing any existing file contents. There is no user-facing warning or confirmation before this irreversible file overwrite occurs.
The filter command truncates and rewrites the specified output CSV path if it already exists. This is a destructive file operation with no confirmation prompt or warning to the user.