Back to skill

Security audit

LeadFlow

Security checks for vulnerabilities and agentic risk

Overview

This lead-generation skill is mostly coherent, but it needs Review because it automatically fetches untrusted business websites from the user's network and exports untrusted fields to spreadsheets without adequate safety controls.

Install only if you are comfortable with a CLI that stores lead data locally, calls several external data providers with your API keys, fetches websites discovered from business listings, and can send selected lead data to a webhook URL you provide. Run it in a network-restricted environment if possible, treat generated spreadsheet files as untrusted, avoid debug logging with proxy credentials, and use limited-scope API keys.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/enrichment/email-scraper.ts:91
Finding

Unrestricted Website Fetching Enables Server-Side Request Forgery

Content
View full analysis
0) { const best = scrapeResult.emails[0]!; ``` ```ts // src/enrichment/email-scraper.ts:91-108 let baseUrl = websiteUrl.trim(); if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) { baseUrl = 'https://' + baseUrl; } // Remove trailing slash baseUrl = baseUrl.replace(/\/$/, ''); const urlObj = new URL(baseUrl); const domain = urlObj.hostname.replace('www.', ''); logger.debug(`Scraping ${baseUrl} for emails`); // Try each contact path for (const path of CONTACT_PATHS) { const pageUrl = baseUrl + path; try { const pageEmails = await scrapePageForEmails(pageUrl, domain); ``` ```ts // src/enrichment/email-scraper.ts:162-177 const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 10000); try { const response = await fetch(url, { signal: controller.signal, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', }, redirect: 'follow', }); ``` ### Technical Analysis The enrichment waterfall automatically fetches website URLs stored in lead records. These URLs originate from external business listings and are not validated as public Internet destinations before being passed to `fetch`. The implementation accepts both HTTP and HTTPS, follows redirects automatically, and ...[truncated 2054 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/export/xlsx.exporter.ts:216
Finding

CSV Exports Permit Spreadsheet Formula Injection

Content
View full analysis
{ const exportLead = leadToExportRow(lead); return headers .map((header) => { const value = exportLead[header as keyof ExportLead]; // Escape quotes and wrap in quotes if contains comma if (value.includes(',') || value.includes('"') || value.includes('\n')) { return `"${value.replace(/"/g, '""')}"`; } return value; }) .join(','); }); const csv = [headers.join(','), ...rows].join('\n'); ``` ```ts // src/export/xlsx.exporter.ts:277-318 const instantlyRows = leads.map((lead) => { const nameParts = splitName(lead.contactName); return [ lead.email ?? '', nameParts.firstName, nameParts.lastName, lead.companyName, formatPhoneDisplay(lead.phone), lead.website ?? '', lead.city ?? '', lead.state ?? '', lead.trade, lead.source, lead.rating?.toString() ?? '', ] .map((value) => { // Escape quotes and wrap if contains comma/quote/newline if (value.includes(',') || value.includes('"') || value.includes('\n')) { return `"${value.replace(/"/g, '""')}"`; } return value; }) .join(','); }); ``` ```ts // src/export/xlsx.exporter.ts:351-370 function csvEscape(value: string): string { if (value.includes(',') || value.includes('"') || value.includes('\n')) { return `"${value.replace(/"/g, '""')}"`; } return value; } async function writeCsvFile(path: string, headers: string[], rows: string[][]): Promise { const dir = dirname(path); if (!existsSync(dir)) { await mkdir(dir, { recursive: true }); } const csv = [ headers.join(','), ...rows.map(row => row.map(csvEscape).join(',')), ].join('\n'); const { writeFile } = a ...[truncated 2154 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/enrichment/hunter.client.ts:30
Finding

Hunter API Credential Is Embedded in Request URLs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/core/http/proxy-rotator.ts:48
Finding

Authenticated Proxy URLs Can Be Written to Logs Without Redaction

Content
View full analysis
0) { const failRate = proxy.failCount / totalRequests; if (failRate >= this.maxFailRate) { if (this.autoRemove) { logger.warn(`Removing proxy ${proxy.url} (fail rate: ${(failRate * 100).toFixed(1)}%)`); this.proxies.splice(this.currentIndex, 1); ``` ```ts // src/core/http/proxy-rotator.ts:143-149 markFailure(proxy: Proxy): void { proxy.failCount++; logger.debug( `Proxy ${proxy.url} failed (${proxy.failCount}/${proxy.successCount + proxy.failCount} requests)` ); } ``` ```ts // src/utils/logger.ts:9-29 export const logger = pino({ level: config.LOG_LEVEL, transport: config.NODE_ENV === 'development' ? { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:standard', ignore: 'pid,hostname', destination: 2, }, } : undefined, base: { pid: process.pid, }, timestamp: pino.stdTimeFunctions.isoTime, }, config.NODE_ENV !== 'development' ? pino.destination(2) : undefined); ``` ### Technical Analysis Proxy agent libraries accept credential-bearing URLs in the conventional form: ```text https://username:password@proxy.example:8443 ``` `ProxyRotator` stores the complete URL and interpolates it into warning an ...[truncated 1595 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (117)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

bash
# 1. Set up your API keys
cp .env.example .env
# Edit .env — only GOOGLE_PLACES_API_KEY is required to get started

# 2. Scrape dental and legal businesses in Miami

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

bash
# 1. Set up your API keys
cp .env.example .env
# Edit .env — only GOOGLE_PLACES_API_KEY is required to get started

# 2. Scrape dental and legal businesses in Miami
leadflow scrape -t dental,legal -l "Miami, FL" --max-results 100

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/cli.ts (reported line 338)May include surrounding context.

ts
```bash
# 1. Set up your API keys
cp .env.example .env
# Edit .env — only GOOGLE_PLACES_API_KEY is required to get started

# 2. Scrape dental and legal businesses in Miami
leadflow scrape -t dental,legal -l "Miami, FL" --max-results 100

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/scrapers/google-maps.scraper.ts (reported line 159)May include surrounding context.

ts
```bash
# 1. Set up your API keys
cp .env.example .env
# Edit .env — only GOOGLE_PLACES_API_KEY is required to get started

# 2. Scrape dental and legal businesses in Miami
leadflow scrape -t dental,legal -l "Miami, FL" --max-results 100

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · src/scrapers/yelp.scraper.ts (reported line 172)May include surrounding context.

ts
```bash
# 1. Set up your API keys
cp .env.example .env
# Edit .env — only GOOGLE_PLACES_API_KEY is required to get started

# 2. Scrape dental and legal businesses in Miami
leadflow scrape -t dental,legal -l "Miami, FL" --max-results 100

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code chunk does not implement the advertised lead-list generation workflow. It merely configures scraper sources and operational parameters such as rate limits, retries, circuit breakers, and proxy/browser needs. While Google Maps and Yelp are present as enabled sources, the main declared capabilities—scraping leads, enriching emails, verifying contacts, scoring quality, and exporting to CRM—are not evidenced here. Additionally, the code references other lead sources not mentioned in the description, though that alone is less significant than the absence of the core advertised behavior. Therefore, the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full end-to-end lead generation and enrichment system. However, the provided code chunk is only a minimal barrel file that re-exports deduplication functionality. Based on this chunk alone, the observable behavior is limited to exposing a matcher/deduplication module, which is only a supporting utility and not representative of the broad capabilities claimed in the description. This is a material description-behavior mismatch because the actual code shown does not substantiate the primary advertised purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description promises an end-to-end lead list generation and enrichment product. The supplied code does not perform scraping, external data collection, email lookup, verification, scoring, or CRM integration. Instead, it is a narrowly scoped internal deduplication module using Fuse.js and simple merge logic for lead records. This is a materially different primary purpose from the declared description, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Yes, this is a mismatch based on the supplied code chunk. The declared description presents a full end-to-end lead generation system with specific business functionality. The actual code shown is only an index file that re-exports generic HTTP infrastructure modules. While such modules could support the described system, this chunk does not demonstrate the declared primary purpose or any of the key advertised capabilities. Therefore, the description is not accurately represented by this code chunk alone.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises end-user lead generation functionality: scraping business listings, enriching emails via multiple providers, verifying contacts, scoring leads, and exporting to CRM systems. The actual code chunk does none of those things directly. Instead, it provides infrastructure for rotating proxies to avoid blocks during network activity. While proxy rotation could be a supporting implementation detail for a scraper, this specific chunk’s behavior is not represented in the declared description, and its primary purpose is network proxy management rather than lead-list generation. Therefore this code chunk does not accurately match the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description describes a full lead-generation and data-enrichment product. However, the provided code chunk only contains infrastructure for HTTP/request throttling via a token bucket rate limiter. It does not scrape websites, process leads, enrich or verify emails, score contacts, or export to a CRM. While rate limiting could be a supporting component inside such a system, this specific chunk’s actual behavior is limited to request pacing and does not substantively implement the declared end-user functionality. Therefore, the description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a business-facing lead-list generation system with web scraping, contact enrichment, verification, scoring, and CRM export. The supplied code does none of those things. It only provides a circuit breaker abstraction for protecting async operations from repeated failures, plus metrics and logging. While such resilience code could support a larger scraping platform, this chunk's actual behavior is infrastructural and not representative of the declared end-user functionality. Therefore, the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a full lead-generation workflow with scraping external platforms, enriching/verifying contacts, scoring, and exporting results. The supplied code chunk contains only a simple index file that re-exports resilience utilities (retry and circuit-breaker). This is infrastructure/support code and does not substantiate the claimed primary functionality. Based on the provided chunk, the actual behavior is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises an end-to-end city-to-lead-list system with scraping, enrichment, verification, scoring, and CRM export. The actual code does none of those domain-specific tasks. It only provides infrastructure for retrying async operations after transient failures, including rate-limit handling and exponential backoff. While retry logic could be a supporting component inside a scraper, this chunk by itself is not representative of the declared purpose and instead reflects a materially different primary behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The description presents a broad end-to-end lead generation system, but this code chunk is narrowly focused on one enrichment provider: Dropcontact. It sends company/person data to an external API to retrieve email information and derives a basic confidence score from the returned qualification. There is no evidence here of scraping Google Maps or Yelp, orchestrating a 4-provider waterfall, verifying contacts, producing comprehensive 0-100 quality scores, exporting to a CRM, or generating lead lists from a city. Because the declared purpose substantially overstates and differs from the observed behavior of this code chunk, this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk is narrowly focused on scraping email addresses from provided company websites. It fetches a base URL and several common subpages, regex-extracts email addresses, filters generic or excluded domains, and assigns heuristic confidence scores to found emails. This is only one small subcomponent of the declared product. The declared description emphasizes a full lead-generation pipeline from city search sources (Google Maps/Yelp), enrichment, verification, lead scoring, and CRM export. None of those major capabilities appear in this code chunk. While the email scraping behavior could support the broader product, the supplied code does not accurately represent the declared end-to-end functionality on its own, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad end-to-end lead generation workflow: source businesses from Google Maps/Yelp, enrich and verify contacts, score lead quality, and export to CRM. The supplied code only covers one subsystem: enriching existing leads with an email via a provider waterfall and storing basic enrichment metadata. While the 4-provider waterfall portion substantially matches part of the description, several core advertised capabilities are absent from this code chunk, especially city-based lead generation, Google Maps/Yelp scraping, verification workflow, scoring, and CRM export. Therefore the description does not accurately represent what this specific code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This code does implement a subset of the declared functionality: email enrichment and email verification. However, the description presents the skill primarily as an end-to-end city-to-lead-list system with scraping from Google Maps and Yelp, multi-provider waterfall enrichment, lead scoring, and CRM export. None of those broader behaviors appear in this code chunk. Instead, the chunk is narrowly an API client for a single provider, Hunter.io, including domain search, person email finding, verification, and a simple best-email selection routine. That is a materially narrower and somewhat different behavior than the declared description, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code chunk is narrowly focused on phone-number validation via Twilio Lookup: it authenticates to Twilio, looks up phone metadata, maps line types, and batch-validates numbers. This does not match the declared headline functionality of city-to-lead-list generation, business scraping, email enrichment, lead scoring, or CRM export. While phone/contact verification could be considered loosely related to 'verifies contacts,' the specific implemented capability here is Twilio-based phone validation, which is only a small supporting piece and does not represent the declared purpose of the skill. Therefore this code chunk materially differs from the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a full lead-generation and enrichment workflow. However, the supplied code chunk contains only a TypeScript barrel file that re-exports error classes from another module. This behavior is merely structural/supporting code and does not substantiate any of the claimed core capabilities. Based on the provided chunk, the actual behavior is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a comprehensive lead scraping, enrichment, verification, scoring, and CRM-export system. The provided code chunk, however, is only an index file that re-exports './xlsx.exporter.js'. Based on this chunk alone, the observable behavior is limited to exposing XLSX export functionality. That is a materially narrower and different capability set than the declared purpose. While export functionality may be one supporting part of the described skill, the supplied code does not substantiate the core advertised behaviors, so the description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a full lead-generation and enrichment workflow, but this code chunk is narrowly focused on exporting already-stored leads. It reads leads from storage, formats them into spreadsheets/CSV variants, writes files to disk, and in one path marks leads as exported. While export is part of the declared feature set, the chunk does not implement the core advertised capabilities of scraping, enrichment, verification, or city-to-lead-list generation. It also says 'exports straight to your CRM,' but the code shown produces local CSV/XLSX files formatted for various CRMs rather than performing direct CRM integrations via API. Therefore, the supplied code does not accurately represent the declared primary purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises a full lead-generation and enrichment workflow with multiple concrete capabilities. However, the supplied code chunk contains only barrel exports from internal modules and no visible implementation of those behaviors. Based on this chunk alone, the actual behavior is just exposing library modules for programmatic use. That is materially different from the declared operational purpose, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Based solely on the supplied code chunk, the implementation does not substantiate the extensive functionality claimed in the description. The file is only an index module that re-exports another orchestrator file, so the actual behavior observable here is limited to module export wiring. Because none of the declared primary capabilities are implemented or evidenced in this chunk, the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The code supports part of the description: scraping leads from multiple sources, handling multiple trades/locations, deduplicating, saving, and progress reporting. However, several prominent advertised capabilities are absent from this chunk: email enrichment via a 4-provider waterfall, contact verification, lead scoring, and CRM export. The source handling is also generic rather than specifically demonstrating Google Maps and Yelp. This makes the declared description materially broader than the actual behavior shown here.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.