Back to skill

Security audit

Lead Hunter

Security checks for vulnerabilities and agentic risk

Overview

This lead-generation skill is not clearly malicious, but it needs review because it can install scraping software, browse arbitrary sources, write persistent data, schedule recurring runs, and create Asana tasks with weak guardrails.

Install only if you are comfortable with an autonomous lead-research agent that scrapes the web, stores lead history locally, may download browser tooling, and can write to Asana. Prefer running it in a sandboxed environment, avoid untrusted custom source URLs, require explicit approval before dependency installation or cron setup, and review any Asana command/output before execution.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Error
Location
scripts/scrape.py:47
Finding

Unpinned Runtime Dependency and Browser Installation

Content
View full analysis

Vulnerability Details

File Location: scripts/scrape.py:47-56
Vulnerability Type: Supply-chain exposure through mutable runtime dependencies
Risk Level: High

python
print("Installing crawl4ai...", file=sys.stderr)
pip = os.path.join(VENV_DIR, "bin", "pip")
result = subprocess.run(
    [pip, "install", "crawl4ai", "-q"],
    capture_output=True, text=True
)
if result.returncode == 0:
    # Install playwright chromium
    pw = os.path.join(VENV_DIR, "bin", "playwright")
    subprocess.run([pw, "install", "chromium"], capture_output=True, text=True)

Technical Analysis

The scraper automatically installs the latest available crawl4ai release and its transitive dependencies when the package is unavailable. It subsequently downloads Playwright Chromium artifacts. Neither operation uses an exact version, hash verification, a lockfile, or a restricted package source.

Consequently, the effective executable code can change after the Skill has been audited. Python package installation may run package build hooks and other installation logic. The downloaded package and its dependencies later execute inside the Agent environment during scraping.

This network activity is required only to provision an optional scraping fallback, but automatic installation is broader than the minimum privileges needed for ordinary lead generation. Installation should be a separate, explicit, integrity-verified administrative action.

Attack Path

  1. A user or scheduled run invokes the Crawl4AI fallback or executes scrape.py --check.
  2. The script creates a virtual environment if needed.
  3. If crawl4ai cannot be imported, the script retrieves the current package and transitive dependencies from pip's configured index.
  4. It also retrieves Playwright Chromium artifacts without local integrity enforcement.
  5. A compromised package release, dependency, index, mirror, or artifact distribution channel supplies ...[truncated 632 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin exact direct and transitive dependency versions in a reviewed lockfile.
  • Require hashes for every Python distribution, such as with pip install --require-hashes.
  • Pin and verify the Playwright browser revision and artifact checksum.
  • Use a trusted, explicitly configured package index rather than the ambient pip configuration.
  • Move dependency installation out of normal Skill execution and require informed user or administrator approval.
  • Build and distribute a reviewed environment or container instead of downloading mutable code on demand.
  • Run the browser and scraper under a sandboxed account with restricted filesystem access, no unnecessary credentials, and limited outbound networking.
  • Fail closed if integrity verification cannot be completed.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scrape.py:63
Finding

Unrestricted Browser Navigation Permits Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/scrape.py:63-81 and scripts/scrape.py:121-130
Vulnerability Type: SSRF through unvalidated user- or configuration-controlled URLs
Risk Level: High

python
async def scrape_url(url, output_format="markdown"):
    """Scrape a URL using Crawl4AI with stealth mode."""
    from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
    
    browser_config = BrowserConfig(
        headless=True,
        verbose=False,
    )
    
    crawler_config = CrawlerRunConfig(
        wait_until="networkidle",
        page_timeout=30000,
    )
    
    async with AsyncWebCrawler(config=browser_config) as crawler:
        result = await crawler.arun(
            url=url,
            config=crawler_config,
        )
python
url = sys.argv[1]
output_format = "markdown"

if "--output" in sys.argv:
    idx = sys.argv.index("--output")
    if idx + 1 < len(sys.argv):
        output_format = sys.argv[idx + 1]

result = asyncio.run(scrape_url(url, output_format))
print(json.dumps(result, indent=2))

The related source policy in references/sources.md:62-67 expressly permits users to add any URL:

markdown
## Custom Sources

Users can add any URL as a source. The skill will attempt to:
1. Fetch the page and extract funding/company announcements
2. If blocked, use search fallback: `site:<domain>` with freshness filter
3. If the site has an RSS feed, prefer that (more reliable, rarely blocked)

Technical Analysis

The command-line URL is forwarded directly to a headless browser. There is no validation of the URL scheme, embedded credentials, hostname, resolved address, destination port, or redirect targets.

A browser running on the Agent host may therefore be induced to request resources that are not reachable by an external attacker, including loopback services, private-network applicati ...[truncated 1739 chars]

Remediation
View remediation

Remediation Suggestions

  • Accept only canonical http and https URLs.
  • Reject URLs containing embedded usernames or passwords and reject unnecessary or dangerous destination ports.
  • Resolve the hostname before connecting and block loopback, private, link-local, multicast, unspecified, reserved, and cloud metadata address ranges for both IPv4 and IPv6.
  • Revalidate every redirect destination and resolved address; do not rely solely on validation of the initial URL.
  • Defend against DNS rebinding by ensuring the validated address is the address actually used for the connection.
  • Prefer an explicit allowlist of approved public lead-source domains.
  • Run the scraper in an isolated network namespace that cannot reach localhost, internal networks, or metadata services.
  • Apply response-size and execution-time limits and prevent downloads where they are unnecessary.
  • Require explicit confirmation before accepting a new custom domain.
  • Keep internal response material out of logs, memory, lead files, and external output destinations.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:88
Finding

Untrusted Scraped Content Is Interpolated into a Shell Command Template

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:88-94
Vulnerability Type: Potential shell command injection through untrusted lead data
Risk Level: High

bash
node skills/asana-pat/scripts/asana.mjs create-task \
  --workspace <workspace_id> \
  --parent <parent_task_id> \
  --assignee me \
  --name "Lead: <Company> - <Round> <Amount>" \
  --notes "<full research + DM draft>"

Technical Analysis

The Skill directs the Agent to insert company names, funding information, research, and generated outreach text into a shell command. Much of this data originates from arbitrary websites and is therefore untrusted.

Merely surrounding data with double quotes does not make it safe for a POSIX shell. Embedded double quotes can terminate the intended argument, while command substitutions such as $(...) and backticks remain active inside double-quoted strings. Newlines and other shell syntax can further alter command parsing.

The underlying Asana script may be legitimate, but execution through a rendered shell command exposes a command-injection boundary. The vulnerability is reached if the Agent materializes this documented template as a shell command without robust argument-safe invocation.

Attack Path

  1. An attacker publishes a funding announcement, company name, article text, or other scraped field containing a shell payload.
  2. The Skill collects the malicious field during source scraping or lead research.
  3. The lead qualifies for output and the Agent places the field into --name or --notes.
  4. The Agent executes the rendered command through a shell.
  5. Shell quoting is broken or command substitution is evaluated.
  6. The attacker's command runs with the Agent process's local privileges.

For example, a malicious value containing a closing quote followed by shell syntax could escape the intended argument. A value containing command substitution could ...[truncated 602 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not build or execute a shell command containing dynamic lead data.
  • Invoke the Asana program through an API that accepts an argument array, with shell processing disabled.
  • Prefer passing structured task data through a JSON file or standard input rather than command-line interpolation.
  • If a shell is unavoidable, apply a proven shell-escaping routine independently to every dynamic value; simple quote replacement is insufficient.
  • Validate workspace and parent identifiers against strict expected formats.
  • Treat all scraped page content, metadata, company names, and generated drafts as untrusted.
  • Add adversarial tests covering double quotes, backticks, command substitution, newlines, option-like values, and shell metacharacters.
  • Run the output integration with only the minimum filesystem, credential, and network permissions required to create the requested Asana task.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill claims a bounded lead-generation purpose, but the documented behavior includes generic scraping fallbacks, stealth browsing, package installation, browser setup, and external integrations that materially expand its real capability set. This mismatch undermines informed consent and can cause the agent to perform risky actions a user would not reasonably expect from the description alone.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The post-onboarding instructions authorize automatic file writes, directory creation, immediate execution of the first hunt, and optional cron-job creation without requiring a separate user confirmation at the point of action. In an autonomous agent context, this creates a clear risk of unintended local state changes, recurring execution, and external side effects that the user may not fully understand or consent to.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The invocation phrase "Find me some leads" is broad and likely to overlap with ordinary user conversation, making accidental activation plausible. In an autonomous skill that performs scraping, research, file output, and possible scheduler setup, ambiguous triggering can cause unintended execution of networked and persistent actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README states the skill will auto-create a cron job for recurring execution, which introduces host-level persistence beyond a simple on-demand lead-generation workflow. Even if intended for convenience, unattended scheduled execution expands attack surface and can be abused to keep a skill running, repeatedly accessing the network and local files without fresh user approval.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The additional examples (e.g. "Run lead hunter", "Find leads for me today", "Hunt for new prospects") remain semantically broad and overlap with routine sales-assistant requests. Because this skill performs autonomous external research and can run on a schedule, weak trigger specificity increases the chance of unintended or over-broad activation.

Content

No source excerpt is available for this finding.

YARA rule 'network_reconnaissance': Network reconnaissance and scanning patterns [hacktools]

Medium
Category
YARA Match
Confidence
65% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · README.md (reported line 100)May include surrounding context.

md
unds, acquisitions
- TechCrunch Startups — US-heavy, Series A+
- PR Newswire — press releases
- EU-Startups — European funding
- Tech in Asia — APAC startup funding
- UKTN — UK tech
- Startup Daily — Australia/NZ

### Industry-Specific
- **SaaS:** ProductHunt, BetaList, Y Combinator, Wellfound
- **Fintech:** Fintech Global, The Fintech Times, Finovate
- **Healthtech:** MobiHealthNews, Fierce Healthcare, Digital Health
- **E-commerce:** Retail Dive, Modern Retail
- **AI/ML:** AI News, VentureBeat AI, The AI Journal
- **HR Tech:** HR Tech Feed, Recruiting Daily, HR Dive
- **Proptech:** Propmodo, The Real Deal, CREtech
- **Climate:** CleanTechnica, GreenBiz
- **EdTech:** EdSurge, EdTech Magazine
- **Legal Tech:** Artificial Lawyer, Legaltech News

Add any custom source — the skill auto-detects RSS feeds for reliable, block-free scraping.

---

## Scraping Architecture

Lead Hunter uses a **4-tier fallback chain** to handle anti-bot protection:

| Tier | Method | Speed | Reli

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

The documented behavior includes auto-managing a Python virtual environment and installing Crawl4AI plus Playwright Chromium, which materially expands the runtime with executable dependencies and browser automation. That is risky because it enables a much broader capability set than simple lead lookup and scraping, and increases supply-chain, code-execution, and stealth automation exposure on the host.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill directs use of network access (web_fetch, web_search) and shell execution (bash, python3, node) but does not declare any explicit tool scope or permissions boundaries. This makes the skill's operational reach implicit rather than reviewable, increasing the chance of unintended execution, external data exfiltration, or filesystem modification when invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The invocation text is broad enough to trigger on ordinary prospecting or pipeline-related requests, even when the user did not ask for autonomous scraping, persistence, or outreach-draft generation. Over-broad auto-activation increases the risk of the skill collecting data, browsing external sites, or modifying local/external systems without sufficiently specific user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill persists lead data to local files (leads/, memory/, seen.json) and may send content to external systems like Asana, but it does not clearly warn users about this storage and sharing behavior. That omission creates privacy, compliance, and data-retention risk, especially because prospect information and personalized outreach content may contain sensitive business or personal data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The onboarding flow asks for Asana workspace and parent task identifiers and stores them in configuration, but provides no user-facing notice about persistence, sensitivity, or least-privilege handling. While these are not secrets in the same class as API keys, they are sensitive operational identifiers that can expose internal project structure and enable unintended writes when combined with existing agent permissions.

Content

No source excerpt is available for this finding.

YARA rule 'network_reconnaissance': Network reconnaissance and scanning patterns [hacktools]

Medium
Category
YARA Match
Confidence
65% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · references/sources.md (reported line 32)May include surrounding context.

md
## By Vertical

### SaaS / Software
- ProductHunt (new launches needing dev help)
- BetaList (pre-launch startups)
- Y Combinator company directory (ycombinator.com/companies)
- AngelList / Wellfound (wellfound.com)

### Fintech
- Fintech Global (fintechglobal.com)
- The Fintech Times (thefintechtimes.com)
- Finovate (finovate.com)

### Healthtech / Biotech
- MobiHealthNews (mobihealthnews.com)
- Fierce Healthcare (fiercehealthcare.com)
- Digital Health (digitalhealth.net)

### E-commerce / Retail
- Retail Dive (retaildive.com)
- Modern Retail (modernretail.co)
- eCommerce Magazine (ecommercemagazine.com)

### AI / ML
- AI News (artificialintelligence-news.com)
- VentureBeat AI (venturebeat.com/ai)
- The AI Journal (aijourn.com)

### Recruiting / HR Tech
- HR Tech Feed (hrtechfeed.com)
- Recruiting Daily (recruitingdaily.com)
- HR Dive (hrdive.com)

### Real Estate / Proptech
- Propmodo (propmodo.com)
- The Real Deal (therealdeal.com)
- CREtech (cretech.com)

### Climate / Clean Tech
-

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/scrape.py (reported line 28)May include surrounding context.

python
import subprocess
    print("Creating virtual environment...", file=sys.stderr)
    subprocess.run([sys.executable, "-m", "venv", VENV_DIR], check=True)
    return venv_python

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill self-installs scraping libraries and browser tooling at runtime, which is broader than merely fetching page content and causes unannounced code execution and environment modification. In the context of an autonomous lead-generation skill, this is more concerning because it enables network access, package retrieval, and local changes without a clear installation boundary or operator review.

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/scrape.py (reported line 38)May include surrounding context.

python
venv_python = ensure_venv()
    
    # Check if crawl4ai is importable in venv
    check = subprocess.run(
        [venv_python, "-c", "import crawl4ai; print(crawl4ai.__version__)"],
        capture_output=True, text=True
    )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script installs packages and browser components automatically without explicit warning or consent, creating side effects that exceed a typical scraping action. This is dangerous because users or calling agents may assume read-only behavior, while the script performs network downloads, writes to disk, and introduces new executable dependencies.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

This call performs automatic package installation at runtime, which executes unpinned third-party code and trusts external package indexes during normal skill operation. In a security-sensitive environment, that expands the attack surface to dependency confusion, malicious upstream releases, or unintended system/network changes beyond simple scraping.

Content

Scanner excerpt · scripts/scrape.py (reported line 49)May include surrounding context.

python
print("Installing crawl4ai...", file=sys.stderr)
    pip = os.path.join(VENV_DIR, "bin", "pip")
    result = subprocess.run(
        [pip, "install", "crawl4ai", "-q"],
        capture_output=True, text=True
    )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
89% confidence
Finding

Downloading and installing Chromium browser components at runtime introduces additional network retrieval and executable content into the host environment. Even without shell injection, this behavior materially increases risk because it modifies the system and trusts remote artifacts during execution.

Content

Scanner excerpt · scripts/scrape.py (reported line 56)May include surrounding context.

python
if result.returncode == 0:
        # Install playwright chromium
        pw = os.path.join(VENV_DIR, "bin", "playwright")
        subprocess.run([pw, "install", "chromium"], capture_output=True, text=True)
        print(json.dumps({"installed": True, "fresh_install": True, "venv": VENV_DIR}))
    else:
        print(json.dumps({"installed": False, "error": result.stderr}))

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/scrape.py (reported line 117)May include surrounding context.

python
venv_python = os.path.join(VENV_DIR, "bin", "python3")
    if os.path.exists(venv_python) and sys.executable != venv_python:
        import subprocess
        result = subprocess.run([venv_python] + sys.argv, capture_output=True, text=True)
        print(result.stdout, end="")
        if result.stderr:
            print(result.stderr, file=sys.stderr, end="")

Static analysis

No suspicious patterns detected.