Back to skill

Security audit

Scraper Builder

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Bright Data scraper-building guide, but it broadly steers agents to send arbitrary sites, APIs, and scraped content through a third-party service without enough scoping or safety checks.

Install only if you intend to use Bright Data for authorized scraping and are comfortable sending target URLs, request metadata, and fetched page content to that provider. Use scoped API keys, do not print secrets, avoid private/internal/authenticated or regulated pages unless approved, and review generated scrapers before letting them run bulk 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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:692
Finding

Bright Data API Key Disclosed Through Terminal Output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/pagination-patterns.md:279
Finding

JavaScript Injection Through Unescaped CSS Selector Interpolation

Content
View full analysis
Array.from(document.querySelectorAll('{item_selector}')).map(el => ({{ # Customize extraction per site: text: el.textContent.trim(), # name: el.querySelector('.name')?.textContent?.trim(), # price: el.querySelector('.price')?.textContent?.trim(), }})) """) ``` Load-more extraction uses the same unsafe construction: ```python items = await page.evaluate(f""" () => Array.from(document.querySelectorAll('{item_selector}')).map(el => ({{ text: el.textContent.trim(), }})) """) ``` ### Technical Analysis The examples insert `item_selector` directly into JavaScript source code using Python f-strings. A selector containing a quote can terminate the JavaScript string literal. Additional JavaScript syntax can then be injected into the expression evaluated by Playwright. This is a code-generation injection flaw rather than an ordinary invalid-selector error. It becomes exploitable when the selector is copied from untrusted content, supplied by a user, derived from a remote page, or generated without strict validation. Playwright supports passing values separately to `page.evaluate()`, so executable source-code interpolation is unnecessary. ### Attack Path 1. An attacker influences the value used as `item_selector`, such as through a user request, malicious selector recommendation, or remotely sourced site-analysis content. 2. The generated scraper places that value between single quotes inside `page.evaluate()`. 3. A crafted value clo ...[truncated 1233 chars]
Remediation
View remediation
document.querySelectorAll(selector).length", item_selector, ) ``` Secure extraction pattern: ```python items = await page.evaluate( """ (selector) => Array.from(document.querySelectorAll(selector)).map(el => ({ text: el.textContent.trim(), })) """, item_selector, ) ``` Apply the same correction to both infinite-scroll and load-more examples. Additional hardening measures: 1. Treat user-provided and remotely derived selectors as untrusted data. 2. Validate that the selector is non-empty and impose a reasonable length limit. 3. Catch selector syntax errors and report them without falling back to dynamic code construction. 4. Prefer Playwright locator APIs where practical: ```python locator = page.locator(item_selector) current_count = await locator.count() ``` 5. Never use Python f-strings or string concatenation to place untrusted values into JavaScript evaluated by `page.evaluate()`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (43)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill’s trigger phrases are unusually broad and can activate on common requests like 'get data from [website]' or 'pull data from', causing the skill to engage in many contexts beyond explicit scraper-building. That increases the chance of unintended delegation to a scraping workflow that encourages third-party data extraction and external requests without clear user intent or scope validation.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
79% confidence
Finding

The instruction to query the live Dataset List API causes authenticated outbound communication to a third-party service and can reveal usage intent and environment configuration. While less severe than content scraping, it still expands the skill’s external dependency surface and normalizes automatic third-party lookups without a consent checkpoint.

Content

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

bash
curl -H "Authorization: Bearer $BRIGHTDATA_API_KEY" \
     https://api.brightdata.com/datasets/list

This returns every available scraper with its dataset_id and name. Search the results for the target domain. You can also browse the full documentation index at https://docs.brightdata.com/llms.txt to discover scraper-specific docs and supported parameters.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The embedded request includes bearer-authenticated transmission to an external scraping provider, which creates a clear trust-boundary crossing. Even though the API key itself is only used as an auth header, the surrounding pattern still enables external processing of arbitrary user-specified targets and returned content.

Content

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

md
API_KEY = os.environ["BRIGHTDATA_API_KEY"]
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

response = requests.post(
    "https://api.brightdata.com/request",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The embedded request includes bearer-authenticated transmission to an external scraping provider, which creates a clear trust-boundary crossing. Even though the API key itself is only used as an auth header, the surrounding pattern still enables external processing of arbitrary user-specified targets and returned content.

Content

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

md
API_KEY = os.environ["BRIGHTDATA_API_KEY"]
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

response = requests.post(
    "https://api.brightdata.com/request",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This request transmits the target URL and zone information to Bright Data, creating a third-party data path for every scrape target. In a tool advertised for 'any website,' the lack of destination restrictions or consent language makes the external transmission more risky.

Content

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

md
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

response = requests.post(
    "https://api.brightdata.com/request",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "zone": ZONE,

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This helper demonstrates a standard external fetch pattern but lacks any visible controls over what destinations may be sent to the third-party service. In context, the skill’s broad mandate to scrape 'any website' makes that omission more dangerous than it would be in a tightly scoped integration.

Content

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

md
def fetch_page(url: str) -> str:
    """Fetch a page through Bright Data Web Unlocker."""
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": url, "format": "raw"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

This helper demonstrates a standard external fetch pattern but lacks any visible controls over what destinations may be sent to the third-party service. In context, the skill’s broad mandate to scrape 'any website' makes that omission more dangerous than it would be in a tightly scoped integration.

Content

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

md
def fetch_page(url: str) -> str:
    """Fetch a page through Bright Data Web Unlocker."""
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": url, "format": "raw"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The code sample shows a reusable mechanism for sending arbitrary user-selected URLs to an external provider for retrieval. That is inherently sensitive because the user may supply confidential, internal, or regulated resources, and the skill does not include trust-boundary enforcement.

Content

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

md
def fetch_page(url: str) -> str:
    """Fetch a page through Bright Data Web Unlocker."""
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": url, "format": "raw"}
    )

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Direct external fetching of API URLs is a meaningful security concern because it lowers the barrier to harvesting structured data from internal or semi-public endpoints. Combined with the skill’s advice to probe for 'hidden APIs,' the pattern can support unauthorized or excessive data extraction beyond ordinary page scraping.

Content

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

md
def fetch_api(api_url: str) -> dict:
    """Fetch a JSON API endpoint through Web Unlocker."""
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": api_url, "format": "raw"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Direct external fetching of API URLs is a meaningful security concern because it lowers the barrier to harvesting structured data from internal or semi-public endpoints. Combined with the skill’s advice to probe for 'hidden APIs,' the pattern can support unauthorized or excessive data extraction beyond ordinary page scraping.

Content

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

md
def fetch_api(api_url: str) -> dict:
    """Fetch a JSON API endpoint through Web Unlocker."""
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": api_url, "format": "raw"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

Forwarding API endpoint URLs externally is especially dangerous because APIs often expose complete structured records, making extraction more scalable and impactful than HTML scraping. The surrounding guidance to seek out hidden APIs increases the likelihood of aggressive or unauthorized collection behaviors.

Content

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

md
def fetch_api(api_url: str) -> dict:
    """Fetch a JSON API endpoint through Web Unlocker."""
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": api_url, "format": "raw"}
    )

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This concurrent bulk scraping example operationalizes high-volume external transmission, allowing many arbitrary URLs to be fetched in parallel through Bright Data. The concurrency guidance materially increases the scale and speed of collection, amplifying abuse potential and the impact of scraping sensitive or unauthorized targets.

Content

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

md
async def fetch_one(session, url):
        async with sem:
            async with session.post(
                "https://api.brightdata.com/request",
                headers={"Authorization": f"Bearer {API_KEY}"},
                json={"zone": ZONE, "url": url, "format": "raw"},
                timeout=aiohttp.ClientTimeout(total=60),

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

As part of the production template, this code normalizes repeated external transmission behavior into copy-paste-ready scraper logic. That makes accidental misuse more likely, especially by users who may not appreciate that all targets and responses are being routed through a third-party provider.

Content

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

md
def fetch_page(url: str, retries: int = 3) -> str:
    for attempt in range(retries):
        try:
            response = requests.post(
                "https://api.brightdata.com/request",
                headers={"Authorization": f"Bearer {API_KEY}"},
                json={"zone": ZONE, "url": url, "format": "raw"},

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

As part of the production template, this code normalizes repeated external transmission behavior into copy-paste-ready scraper logic. That makes accidental misuse more likely, especially by users who may not appreciate that all targets and responses are being routed through a third-party provider.

Content

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

md
def fetch_page(url: str, retries: int = 3) -> str:
    for attempt in range(retries):
        try:
            response = requests.post(
                "https://api.brightdata.com/request",
                headers={"Authorization": f"Bearer {API_KEY}"},
                json={"zone": ZONE, "url": url, "format": "raw"},

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The template’s outbound request code embeds the core third-party transmission behavior into a production-ready script, making it easy to deploy without considering destination sensitivity. This increases operational risk because users may adopt it as-is and scrape arbitrary sites through an external processor.

Content

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

md
for attempt in range(retries):
        try:
            response = requests.post(
                "https://api.brightdata.com/request",
                headers={"Authorization": f"Bearer {API_KEY}"},
                json={"zone": ZONE, "url": url, "format": "raw"},
                timeout=60,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation repeatedly instructs users to send target URLs, page content, and scraping inputs to Bright Data services, but it does not clearly warn that this shares potentially sensitive browsing targets and retrieved content with a third party. In a scraper-building skill, this matters because users may apply the examples to internal, authenticated, regulated, or otherwise sensitive pages without understanding the data-sharing implications.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This duplicate finding reflects the same external transmission behavior in the fetch_page example: target URLs are sent off-platform to Bright Data for retrieval. The risk is not code execution but undisclosed third-party data sharing that may surprise users and violate internal data-handling expectations.

Content

Scanner excerpt · references/pagination-patterns.md (reported line 37)May include surrounding context.

md
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

def fetch_page(url: str) -> str:
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": url, "format": "raw"},

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This duplicate finding reflects the same external transmission behavior in the fetch_page example: target URLs are sent off-platform to Bright Data for retrieval. The risk is not code execution but undisclosed third-party data sharing that may surprise users and violate internal data-handling expectations.

Content

Scanner excerpt · references/pagination-patterns.md (reported line 37)May include surrounding context.

md
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

def fetch_page(url: str) -> str:
    response = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"zone": ZONE, "url": url, "format": "raw"},

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This duplicate finding points to the same bulk API trigger call that transmits user-provided URL inventories to a third party. In a production scraper guide, that becomes more dangerous because users may operationalize it at scale without reviewing privacy, contractual, or compliance consequences.

Content

Scanner excerpt · references/pagination-patterns.md (reported line 477)May include surrounding context.

md
def bulk_scrape_with_trigger(urls: list[str], dataset_id: str) -> list:
    """Submit all URLs to Web Scraper API at once."""
    # Trigger
    response = requests.post(
        "https://api.brightdata.com/datasets/v3/trigger",
        params={"dataset_id": dataset_id, "format": "json"},
        headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This duplicate finding points to the same bulk API trigger call that transmits user-provided URL inventories to a third party. In a production scraper guide, that becomes more dangerous because users may operationalize it at scale without reviewing privacy, contractual, or compliance consequences.

Content

Scanner excerpt · references/pagination-patterns.md (reported line 477)May include surrounding context.

md
def bulk_scrape_with_trigger(urls: list[str], dataset_id: str) -> list:
    """Submit all URLs to Web Scraper API at once."""
    # Trigger
    response = requests.post(
        "https://api.brightdata.com/datasets/v3/trigger",
        params={"dataset_id": dataset_id, "format": "json"},
        headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

Downloading the completed snapshot from Bright Data means scraped content is being stored and later retrieved from a third-party service, which increases confidentiality and retention concerns beyond simple transit. In this skill context, users may unknowingly cause externally hosted copies of scraped data to exist, including potentially sensitive content.

Content

Scanner excerpt · references/pagination-patterns.md (reported line 500)May include surrounding context.

md
# Download
    data = requests.get(
        f"https://api.brightdata.com/datasets/v3/snapshot/{snapshot_id}",
        params={"format": "json"},
        headers={"Authorization": f"Bearer {API_KEY}"}
    ).json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The guide instructs users to send arbitrary target URLs and returned page content through Bright Data's external service using environment-based credentials, but it does not clearly warn that this transmits browsing targets and scraped content to a third party. In a scraper-building skill, that omission is security-relevant because users may unknowingly process sensitive URLs, session-bound pages, or regulated data through external infrastructure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This code performs an outbound request to Bright Data and includes a user-supplied target URL in the JSON payload, causing external transmission of the browsing target and resulting fetched content path through a third-party service. In context, this is expected product behavior for a scraping skill, but it is still a real data-exposure concern if users apply it to confidential endpoints or authenticated pages without understanding the trust boundary.

Content

Scanner excerpt · references/site-analysis-guide.md (reported line 31)May include surrounding context.

md
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

# Fetch raw HTML
response = requests.post(
    "https://api.brightdata.com/request",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={"zone": ZONE, "url": TARGET_URL, "format": "raw"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This code performs an outbound request to Bright Data and includes a user-supplied target URL in the JSON payload, causing external transmission of the browsing target and resulting fetched content path through a third-party service. In context, this is expected product behavior for a scraping skill, but it is still a real data-exposure concern if users apply it to confidential endpoints or authenticated pages without understanding the trust boundary.

Content

Scanner excerpt · references/site-analysis-guide.md (reported line 31)May include surrounding context.

md
ZONE = os.environ["BRIGHTDATA_UNLOCKER_ZONE"]

# Fetch raw HTML
response = requests.post(
    "https://api.brightdata.com/request",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={"zone": ZONE, "url": TARGET_URL, "format": "raw"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This example sends the same target URL to the external Bright Data endpoint and additionally requests markdown-formatted output, which still involves third-party handling of fetched page content. The extra formatting step may encourage users to send full page material off-platform without considering confidentiality or terms-of-service implications.

Content

Scanner excerpt · references/site-analysis-guide.md (reported line 39)May include surrounding context.

md
html = response.text

# Also fetch as markdown for a quick readable overview
md_response = requests.post(
    "https://api.brightdata.com/request",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={"zone": ZONE, "url": TARGET_URL, "format": "raw", "data_format": "markdown"}

Static analysis

No suspicious patterns detected.