T09 · Insecure Skill Coding Practices
- Location
SKILL.md:30- Finding
APIFY_TOKEN Exposed Through URL Query Parameters
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill does what it says: it uses an Apify token to scrape Hacker News, with some credential-handling and input-safety cautions users should understand.
Install only if you are comfortable sending Hacker News search parameters to Apify and using an Apify token from the agent environment. Prefer a narrowly scoped token, avoid logging full curl commands, and update the commands to use an Authorization header plus jq-built JSON before using this with sensitive terms or shared systems.
SKILL.md:30APIFY_TOKEN Exposed Through URL Query Parameters
SKILL.md:20Unsafe User Input Substitution in Shell and JSON Request Template
The description says to use the skill when the user asks to "search HN, find Hacker News posts, monitor tech discussions, or extract HN data." Phrases like "monitor tech discussions" are broad and lack clear scope or exclusion conditions, which could cause unintended invocation for general tech-monitoring requests not specifically about Hacker News.
The presence of a direct HTTPS call to api.apify.com confirms that the skill relies on an external service, which is a legitimate but real security-relevant data egress path. In this context, the danger is not the domain itself but the combination of third-party transmission and URL-based token handling.
RESULT=$(curl -s -X POST "https://api.apify.com/v2/acts/0UDODOnpTkxY3Oc90/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"searchTerms": ["TERM"], "maxResults": 30}')
echo "$RESULT" | jq '.'
The presence of a direct HTTPS call to api.apify.com confirms that the skill relies on an external service, which is a legitimate but real security-relevant data egress path. In this context, the danger is not the domain itself but the combination of third-party transmission and URL-based token handling.
RESULT=$(curl -s -X POST "https://api.apify.com/v2/acts/0UDODOnpTkxY3Oc90/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"searchTerms": ["TERM"], "maxResults": 30}')
echo "$RESULT" | jq '.'
This external call initiates an actor run against a third-party API and therefore constitutes genuine outbound transmission of user-requested data. Because the token is again placed in the URL, the skill increases the attack surface for secret leakage beyond the intended external processing.
RUN_ID=$(curl -s -X POST "https://api.apify.com/v2/acts/0UDODOnpTkxY3Oc90/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"searchTerms": ["TERM"], "maxResults": 100}' | jq -r '.data.id')
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status'
This external call initiates an actor run against a third-party API and therefore constitutes genuine outbound transmission of user-requested data. Because the token is again placed in the URL, the skill increases the attack surface for secret leakage beyond the intended external processing.
RUN_ID=$(curl -s -X POST "https://api.apify.com/v2/acts/0UDODOnpTkxY3Oc90/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"searchTerms": ["TERM"], "maxResults": 100}' | jq -r '.data.id')
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status'
Polling the actor-run status is an external network operation to Apify, but it appears to send minimal new user data beyond the run identifier. The main concern remains that the APIFY_TOKEN is in the URL, which can leak through logs even in low-sensitivity status checks.
RUN_ID=$(curl -s -X POST "https://api.apify.com/v2/acts/0UDODOnpTkxY3Oc90/runs?token=$APIFY_TOKEN"
-H "Content-Type: application/json"
-d '{"searchTerms": ["TERM"], "maxResults": 100}' | jq -r '.data.id')
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status'
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/dataset/items?token=$APIFY_TOKEN" | jq '.'
Fetching dataset items from Apify retrieves externally processed results and again authenticates with a URL token. This reinforces that the skill sends and receives data through a third-party boundary, and the URL-based secret handling makes accidental credential disclosure more likely.
-H "Content-Type: application/json"
-d '{"searchTerms": ["TERM"], "maxResults": 100}' | jq -r '.data.id')
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID?token=$APIFY_TOKEN" | jq -r '.data.status'
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/dataset/items?token=$APIFY_TOKEN" | jq '.'
### Step 4: Present results
No suspicious patterns detected.