Back to skill

Security audit

Apify Lead Generation

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned for Apify lead scraping, but it handles contact data and local exports with enough under-disclosed privacy and file-safety risk to require review.

Install only if you are comfortable sending search criteria and actor inputs to Apify and handling scraped public contact data. Treat exported CSV/JSON files as sensitive, avoid confidential inputs, review platform and privacy obligations before outreach, and be cautious opening CSV exports in spreadsheets or writing outputs in shared workspaces.

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

T09 · Insecure Skill Coding Practices

Warning
Location
reference/scripts/run_actor.js:58
Finding

Symlink-Based Arbitrary File Overwrite

Content
View full analysis
0) { const fieldnames = Object.keys(data[0]); const csvLines = [fieldnames.join(',')]; for (const row of data) { const values = fieldnames.map((key) => { let value = row[key]; // Truncate long text fields if (typeof value === 'string' && value.length > 200) { value = value.slice(0, 200) + '...'; } else if (Array.isArray(value) || (typeof value === 'object' && value !== null)) { value = JSON.stringify(value) || ''; } // CSV escape: wrap in quotes if contains comma, quote, or newline if (value === null || value === undefined) { return ''; } const strValue = String(value); if (strValue.includes(',') || strValue.includes('"') || strValue.includes('\n')) { return `"${strValue.replace(/"/g, '""')}"`; } ...[truncated 2564 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
reference/scripts/run_actor.js:239
Finding

CSV Formula Injection in Exported Scraping Results

Content
View full analysis
0) { const fieldnames = Object.keys(data[0]); const csvLines = [fieldnames.join(',')]; for (const row of data) { const values = fieldnames.map((key) => { let value = row[key]; // Truncate long text fields if (typeof value === 'string' && value.length > 200) { value = value.slice(0, 200) + '...'; } else if (Array.isArray(value) || (typeof value === 'object' && value !== null)) { value = JSON.stringify(value) || ''; } // CSV escape: wrap in quotes if contains comma, quote, or newline if (value === null || value === undefined) { return ''; } const strValue = String(value); if (strValue.includes(',') || strValue.includes('"') || strValue.includes('\n')) { return `"${strValue.replace(/"/g, '""')}"`; } return strValue; }); csvLines.push(values.join(',')); } writeFileSync(outputPath, csvLines.join('\n')); } ``` ### Technical Analysis The CSV exporter correctly escapes commas, quotation marks, and newlines for CSV syntax, but it does not neutralize spreadsheet formula prefixes. Values beginning with characters such as `=`, `+`, `-`, or `@` may be interpreted as formulas when the resulting CSV is opened in spreadsheet software. Because the exported records originate from websites and social-media profiles, an external party may be able to control fields such as business names, descriptions, usernames, addresses, or other scraped text. Quoting a value according to CSV syntax does not reliably prevent spreadsheet applications from evaluating it as a formula. Leadi ...[truncated 1599 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill states that scraped data does not include personally identifiable information, but the listed actors explicitly extract emails, phone numbers, profile details, and contact information. This materially misrepresents privacy risk and could lead to unsafe handling, under-classification of sensitive data, and regulatory or policy violations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill invokes networked tooling and consumes a sensitive environment variable (APIFY_TOKEN) but does not declare an explicit tool scope such as allowed tools or permissions. That weakens least-privilege boundaries and makes it harder for the host to constrain or review what the skill is permitted to do, especially since the workflow fetches remote actor metadata and runs remote scraping jobs.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill description contains broad trigger phrases like finding leads, prospects, businesses, and scraping profiles, which can cause over-selection for common user requests. Overly broad routing increases the chance that scraping and external data transmission are invoked when a simpler, lower-risk skill would suffice.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The skill sends data and authentication material to an external service (api.apify.com) to fetch actor details and run scraping workflows. External transmission is expected for this skill, but it still creates data-exfiltration and third-party processing risk because search inputs, scraped targets, and exported results may contain sensitive business or personal information.

Content

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

md
This skill instructs the agent to select an Apify Actor, fetch its schema (via mcpc), and run scrapers. The included script communicates only with api.apify.com and writes outputs to files under the current working directory; it does not access unrelated system files or other environment variables.

Apify Actors only scrape publicly available data and do not collect private or personally identifiable information beyond what is openly accessible on the target platforms. For additional security assurance, you can check an Actor's permission level by querying `https://api.apify.com/v2/acts/:actorId` — an Actor with `LIMITED_PERMISSIONS` operates in a restricted sandbox, while `FULL_PERMISSIONS` indicates broader system access. For full details, see [Apify's General Terms and Conditions](https://docs.apify.com/legal/general-terms-and-conditions).

## Error Handling

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The privacy section downplays collection of personal data even though the skill explicitly uses actors for contact enrichment, profile scraping, emails, phones, and similar lead data. Misleading security/privacy documentation can cause operators to approve or use the skill without appropriate legal review, consent checks, or data-handling safeguards.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This code performs an authenticated POST to Apify's external API and sends the full parsed input object in the request body. That means any data placed in --input leaves the local environment and is processed by a third party, which is dangerous if users provide confidential leads, internal targeting criteria, or personal data without understanding the disclosure.

Content

Scanner excerpt · reference/scripts/run_actor.js (reported line 155)May include surrounding context.

js
async function startActor(token, actorId, parsedInput) {
    // Convert "author/actor" format to "author~actor" for API compatibility
    const apiActorId = actorId.replace('/', '~');
    const url = `https://api.apify.com/v2/acts/${apiActorId}/runs`;

    const response = await fetch(url, {
        method: 'POST',

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script sends user-supplied actor input to Apify and later retrieves results from Apify's remote service, but it does not present any explicit warning, consent gate, or data-classification check before transmitting potentially sensitive data off-host. In a lead-generation skill, users may include prospect lists, search terms, or enriched contact details, so silent third-party disclosure is a real privacy and compliance risk even though the transmission is expected for functionality.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · reference/scripts/run_actor.js (reported line 187)May include surrounding context.

js
// Poll run status until complete or timeout
async function pollUntilComplete(token, runId, timeout, interval) {
    const url = `https://api.apify.com/v2/actor-runs/${runId}`;
    const startTime = Date.now();
    let lastStatus = null;

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This code downloads dataset results from Apify, meaning data generated or stored remotely is brought back into the local environment without any sensitivity warning or validation. In this skill context, those results can include scraped contact data or profile details, so the external data flow has privacy, compliance, and trust implications.

Content

Scanner excerpt · reference/scripts/run_actor.js (reported line 226)May include surrounding context.

js
// Download dataset items
async function downloadResults(token, datasetId, outputPath, format) {
    const url = `https://api.apify.com/v2/datasets/${datasetId}/items?format=json`;

    const response = await fetch(url, {
        headers: {

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

Quick-answer mode fetches dataset contents from Apify and prints top results directly into chat/output, which can surface externally sourced personal or business data without review. In a lead-generation tool, that increases the chance of inadvertent disclosure of scraped contact details or other sensitive attributes to downstream logs, transcripts, or users.

Content

Scanner excerpt · reference/scripts/run_actor.js (reported line 291)May include surrounding context.

js
// Display top 5 results in chat format
async function displayQuickAnswer(token, datasetId) {
    const url = `https://api.apify.com/v2/datasets/${datasetId}/items?format=json`;

    const response = await fetch(url, {
        headers: {

Static analysis

No suspicious patterns detected.