Back to skill

Security audit

Apify Bluesky Scraper

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for Bluesky searches through Apify, but it needs Review because it handles an Apify credential in request URLs and does not clearly warn users that search data is sent to Apify.

Install only if you are comfortable sending Bluesky search terms and requested limits to Apify under your Apify account. Use a minimally scoped token if possible, avoid shell tracing or logging full commands, and prefer revising the skill to use Authorization headers instead of token query parameters before use.

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
SKILL.md:28
Finding
Apify API Token Exposed in URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 28–54 **Vulnerability Type**: Sensitive credential exposure through URL query parameters **Risk Level**: Medium ### Vulnerable Code ```bash RESULT=$(curl -s -X POST "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/run-sync-get-dataset-items?token=$APIFY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"searchTerms": ["SEARCH_TERM"], "maxResults": 50, "sortBy": "relevance"}') ``` ```bash RUN_ID=$(curl -s -X POST "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/runs?token=$APIFY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"searchTerms": ["TERM"], "maxResults": 50}' | jq -r '.data.id') ``` ```bash STATUS=$(curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status') # Poll every 5s until SUCCEEDED or FAILED curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/dataset/items?token=$APIFY_TOKEN" | jq '.' ``` ```bash curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/log?token=$APIFY_TOKEN" ``` ### Technical Analysis The Skill places the sensitive `APIFY_TOKEN` directly into the query string of every Apify API request. Authentication is necessary for the declared scraping functionality, but including the credential in URLs is not the minimum-risk authentication method. Although HTTPS encrypts the URL while it is in transit, query-string credentials may still be exposed through: - Local process listings while `curl` is running. - Shell tracing or command-execution diagnostics. - HTTP proxy, gateway, access, or monitoring logs. - Debugging and error-reporting systems that record complete request URLs. - Copied terminal output or diagnostic records containing the executed command. The same unsafe pattern is used for starting synchronous and asynchronous Actor runs, polling status, retrieving dataset items, and retrieving logs. This unnecessarily broadens the opportunities for credential disclosure. The network communication with `api. ...[truncated 1711 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `token=$APIFY_TOKEN` from every request URL. 2. Pass the credential through Apify's supported authorization header: ```bash curl -s -X POST \ "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/run-sync-get-dataset-items" \ -H "Authorization: Bearer $APIFY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"searchTerms":["SEARCH_TERM"],"maxResults":50,"sortBy":"relevance"}' ``` 3. Apply the same header-based authentication pattern to Actor creation, status polling, dataset retrieval, and log retrieval. 4. Avoid enabling shell tracing such as `set -x` while handling credentials. If tracing is required, disable it before authenticated requests and restore it afterward. 5. Do not print complete authorization headers, request commands, or secret-bearing environment variables in logs or error messages. 6. Use a minimally privileged Apify token where supported and separate tokens by environment or workload. 7. Restrict access to execution logs, proxy logs, and monitoring data. 8. Rotate any token that may previously have appeared in URLs or retained logs. 9. Inform users that their Bluesky search terms and requested result limits are sent to the third-party Apify service as part of the Skill's declared operation. ]]>
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 (9)

Vague Triggers

Medium
Confidence
88% confidence
Finding
The invocation description says to use the skill when the user asks to 'search Bluesky, find Bluesky posts, monitor Bluesky discussions, or extract Bluesky data.' Several of these phrases are broad and the file does not provide exclusion conditions or narrower trigger constraints, which could cause the skill to activate on loosely related requests.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to send user-provided search terms and retrieve data through a third-party service, but it does not explicitly warn the user that their query will be transmitted to Apify. This creates a privacy and consent risk, especially if users provide sensitive topics, names, or investigative queries expecting only local processing.

External Transmission

Medium
Category
Data Exfiltration
Content
### Step 2: Run the Actor (synchronous)
```bash
RESULT=$(curl -s -X POST "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["SEARCH_TERM"], "maxResults": 50, "sortBy": "relevance"}')
echo "$RESULT" | jq '.'
Confidence
91% confidence
Finding
The hardcoded use of the Apify API endpoint confirms that data leaves the local environment and is processed by a third party. In this skill context that transmission is expected, but it is still security-relevant because there is no explicit warning, no consent gate, and the token is passed in a way that may be exposed in logs.

External Transmission

Medium
Category
Data Exfiltration
Content
### Step 2: Run the Actor (synchronous)
```bash
RESULT=$(curl -s -X POST "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["SEARCH_TERM"], "maxResults": 50, "sortBy": "relevance"}')
echo "$RESULT" | jq '.'
Confidence
91% confidence
Finding
The hardcoded use of the Apify API endpoint confirms that data leaves the local environment and is processed by a third party. In this skill context that transmission is expected, but it is still security-relevant because there is no explicit warning, no consent gate, and the token is passed in a way that may be exposed in logs.

External Transmission

Medium
Category
Data Exfiltration
Content
For larger jobs (async):
```bash
RUN_ID=$(curl -s -X POST "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["TERM"], "maxResults": 50}' | jq -r '.data.id')
```
Confidence
91% confidence
Finding
This external endpoint initiates an Apify actor run and therefore transfers user input and account-authenticated activity to a third-party platform. The skill context makes the transmission functionally necessary, but the absence of privacy notice and the use of token-in-URL make it a genuine security weakness rather than a pure false positive.

External Transmission

Medium
Category
Data Exfiltration
Content
For larger jobs (async):
```bash
RUN_ID=$(curl -s -X POST "https://api.apify.com/v2/acts/WAJfBnZBYR9mJrk5d/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["TERM"], "maxResults": 50}' | jq -r '.data.id')
```
Confidence
91% confidence
Finding
This external endpoint initiates an Apify actor run and therefore transfers user input and account-authenticated activity to a third-party platform. The skill context makes the transmission functionally necessary, but the absence of privacy notice and the use of token-in-URL make it a genuine security weakness rather than a pure false positive.

External Transmission

Medium
Category
Data Exfiltration
Content
### Step 3: Poll and fetch (if async)
```bash
STATUS=$(curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status')
# Poll every 5s until SUCCEEDED or FAILED
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/dataset/items?token=$APIFY_TOKEN" | jq '.'
```
Confidence
84% confidence
Finding
Polling the external run status does not itself add much new user-data exposure beyond the original submission, but it continues authenticated communication with Apify using a token in the URL. The main concern is credential handling and undisclosed ongoing interaction with the third-party service.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
STATUS=$(curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status')
# Poll every 5s until SUCCEEDED or FAILED
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/dataset/items?token=$APIFY_TOKEN" | jq '.'
```

### Step 4: Present results
Confidence
90% confidence
Finding
Fetching dataset items from Apify retrieves externally processed results and continues authenticated third-party data exchange. If the scraped results or the user’s original query are sensitive, this extends the privacy exposure surface, especially with query-string token usage and no explicit user notice.

External Transmission

Medium
Category
Data Exfiltration
Content
## Error Handling
- If APIFY_TOKEN not set: `export APIFY_TOKEN=your_token`
- If run FAILS: `curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/log?token=$APIFY_TOKEN"`
- Rate limited (429): wait 60s, retry
Confidence
82% confidence
Finding
The log retrieval endpoint continues external authenticated access and may expose operational details in third-party logs. While lower impact than the initial data submission, it still reflects insecure credential handling and undisclosed external interactions within the skill.

Static analysis

No suspicious patterns detected.