Back to skill

Security audit

Apify Runner

Security checks for vulnerabilities and agentic risk

Overview

This Apify scraping skill is mostly purpose-aligned, but it handles Apify credentials unsafely and can send user targets to third-party actors with limited disclosure and confirmation.

Review this before installing if you will use real Apify account tokens or sensitive target lists. Prefer a limited-scope Apify token, avoid the documented --token command-line form, keep config files out of version control with restrictive permissions, and confirm which actor will receive your targets before running full jobs.

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

Warning
Location
scripts/apify_runner.py:44
Finding
Apify API Token Exposure Through URL Query Parameters and Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apify_runner.py:44-49, 60, 75, 83, 144`; `SKILL.md:22-26, 67-71` **Vulnerability Type**: Credential exposure through request URLs and process arguments **Risk Level**: Medium ### Complete Code Snippets `scripts/apify_runner.py:44-49`: ```python resp = requests.post( url, json=run_input, headers={"Content-Type": "application/json"}, params={"token": token}, ) ``` `scripts/apify_runner.py:60`: ```python resp = requests.get(url, params={"token": token}) ``` `scripts/apify_runner.py:75`: ```python requests.post(url, params={"token": token}) ``` `scripts/apify_runner.py:83`: ```python resp = requests.get(url, params={"token": token}) ``` `scripts/apify_runner.py:144`: ```python parser.add_argument("--token", default=None, help="直接传 Token(优先级最高)") ``` `SKILL.md:22-26`: ```markdown Token can be provided via: 1. `--token` flag (highest priority) 2. `config.json` tokens map (by `--token-name`) 3. `APIFY_TOKEN` env var (fallback) ``` `SKILL.md:67-71`: ```bash python3 scripts/apify_runner.py {actor_id} \ --input '{...}' \ --token {token} \ --probe-only \ --list-key {key} ``` ### Technical Analysis The Apify token is a legitimate credential required for the Skill's declared functionality, and the destination is the fixed official HTTPS endpoint `https://api.apify.com/v2`. The behavior therefore does not indicate intentional credential exfiltration. However, the implementation sends the token as a URL query parameter using `params={"token": token}`. Although TLS protects the URL in transit from ordinary network observers, complete URLs can be captured by HTTP client diagnostics, reverse proxies, monitoring systems, exception telemetry, request tracing, or other infrastructure logs. Query parameters are generally more likely to be retained than authentication headers. The documented and implemented `--token` option creates another unnecessary exposure path. Command-line ...[truncated 2424 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Use authorization headers instead of query parameters** Centralize authenticated requests and send the token in an HTTP authorization header: ```python def auth_headers(token): return { "Authorization": f"Bearer {token}", "Content-Type": "application/json", } resp = requests.post( url, json=run_input, headers=auth_headers(token), timeout=30, ) ``` Apply equivalent header-based authentication to polling, abort, and dataset requests. Confirm the exact supported authentication scheme against current Apify API documentation. 2. **Remove or de-emphasize direct command-line token entry** Remove `--token` if compatibility permits. Prefer `APIFY_TOKEN` or a protected configuration file. If direct entry must remain available, warn that command-line arguments may be observable and provide an interactive `getpass.getpass()` option that does not echo or store the credential in shell history. 3. **Correct the documentation** Replace examples containing `--token {token}` with environment-based invocation, such as: ```bash APIFY_TOKEN="$(secure-secret-provider read apify-token)" \ python3 scripts/apify_runner.py apify/instagram-scraper \ --input '{...}' \ --probe-only \ --list-key directUrls ``` Avoid literal secret values in shell commands where possible because environment assignments may also be captured by shell or orchestration tooling. A protected secret manager or inherited environment is preferable. 4. **Protect configuration files** Require restrictive file permissions for token configuration files, avoid storing them inside the project repository, and document that they must be excluded from version control. Reject configuration files that are group- or world-readable where supported. 5. **Reduce token privileges** Use a dedicated Apify token with only the permissions and account sc ...[truncated 640 chars]
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The code does support core Apify Actor execution behavior: starting actor runs, probe testing, batch splitting, polling/waiting, and collecting dataset results. However, it does not implement Actor discovery or any quality filtering/ranking of candidate Actors. Instead, it requires the caller to provide an explicit actor_id and simply executes that actor. So the description overstates important capabilities, making it a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises an end-to-end capability to run Apify Actors for scraping, including discovery, quality filtering, probe testing, batched execution, and result collection. The supplied code chunk implements only the discovery/filtering portion: it queries the Apify Store API, applies quality thresholds, scores actors, and returns ranked candidates. There is no code to invoke actors, pass inputs, monitor runs, test outputs, batch executions, or retrieve scraping results. So the actual behavior is a narrower subset and materially different from the declared primary purpose.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs use of environment variables, local config files, network fetches, and writing results to disk, but it declares no explicit tool scope or permission boundaries. In an agent setting, that omission makes the skill harder to sandbox and review, increasing the risk of unintended access to secrets, local files, and outbound data transmission.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger is broad enough to activate for many generic requests to extract website or social-media data, which can cause the agent to invoke third-party scraping workflows without a clear user expectation of external transmission. In context, this is more dangerous because the skill can target many platforms and automate actor selection and execution, expanding chances of over-collection or unintended use.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill does not warn users that their targets, URLs, usernames, keywords, and filters may be transmitted to a third-party service during actor discovery, documentation fetches, probe runs, and full execution. In a scraping skill, that missing disclosure materially affects privacy and data-handling expectations, especially when users may provide sensitive investigative or proprietary target lists.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- The user's targets and filters
- Sensible defaults from the documentation

**Do NOT ask the user to write JSON.** Build it from their natural language request.

### Step 5: Probe Test (Top 1 → Top 2 → Top 3 fallback)
Confidence
80% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

External Transmission

Medium
Category
Data Exfiltration
Content
def start_run(actor_id, run_input, token):
    """启动 Actor Run"""
    url = f"{API_BASE}/acts/{actor_id.replace('/', '~')}/runs"
    resp = requests.post(
        url,
        json=run_input,
        headers={"Content-Type": "application/json"},
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
import argparse
import requests

STORE_API = "https://api.apify.com/v2/store"

# 质量筛选阈值
MIN_SUCCESS_RATE = 0.95
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
import argparse
import requests

STORE_API = "https://api.apify.com/v2/store"

# 质量筛选阈值
MIN_SUCCESS_RATE = 0.95
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The workflow supports saving raw JSON results to an output path but does not warn that collected data may be written to local disk. That omission can lead to unintentional persistence of scraped content, including potentially sensitive data, in shared or insecure locations.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The module docstring and CLI help text are written in Chinese, which constitutes a language-specific instruction surface for users. Under the policy rule, locale or language constraints should either be optional for the user or clearly justified as region-specific; this file provides neither.

Static analysis

No suspicious patterns detected.