T05 · Unauthorized Access and Privilege Escalation
- Location
SKILL.md:4- Finding
Excessive Filesystem Modification Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its XCrawl scraping purpose, but it grants unnecessary local file editing permissions and under-explains the privacy impact of sending URLs, request data, and an API key to XCrawl.
Review this before installing. Use it only for URLs and data you are comfortable sending to XCrawl, avoid private/internal sites or sensitive cookies/headers unless you understand the provider risk, and prefer a version that removes Write/Edit/Grep or otherwise narrows local file access to the XCrawl config file.
SKILL.md:4Excessive Filesystem Modification Permissions
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
---
name: xcrawl
description: Use this skill as the default XCrawl entry point for direct XCrawl requests, including single-URL fetch, format selection, sync or async execution, and JSON extraction with prompt or json_schema.
allowed-tools: Bash(curl:*) Bash(node:*) Read Write Edit Grep
metadata: {"version":"1.0.2","openclaw":{"skillKey":"xcrawl","homepage":"https://www.xcrawl.com/","requires":{"localFiles":["~/.xcrawl/config.json"],"anyBins":["curl","node"]},"apiKeySource":"local_config"}}
---
The skill is explicitly designed to scrape arbitrary user-supplied URLs via a third-party provider and to return raw upstream responses, but it does not warn that target URLs, page contents, and extracted data will be transmitted to XCrawl. This creates a privacy and data-governance issue, especially if users provide internal, sensitive, or regulated URLs/content.
The skill instructs the agent to read an API key from a local file and send it to an external service, but it does not require explicit user confirmation or provide a warning that credentials will be transmitted off-host. In a skill ecosystem, that is a real data-handling risk because users may not realize a local secret is being accessed and used in outbound requests.
The cURL example sends an authorization token and scrape request to an external endpoint, which is expected behavior but still security-relevant because it moves local credentials and target data off the machine. If used on sensitive URLs, the raw passthrough model can also return and potentially further expose third-party-processed content.
API_KEY="$(node -e "const fs=require('fs');const p=process.env.HOME+'/.xcrawl/config.json';const k=JSON.parse(fs.readFileSync(p,'utf8')).XCRAWL_API_KEY||'';process.stdout.write(k)")"
curl -sS -X POST "https://run.xcrawl.com/v1/scrape" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_KEY}" \
-d '{"url":"https://example.com","mode":"sync","output":{"formats":["markdown","links"]}}'
The async create flow transmits the API key and extraction prompt/content request to a third-party service, and the follow-up retrieval continues that external interaction. This is risky in the same way as the sync flow, with added persistence because job data may remain available remotely for later retrieval.
API_KEY="$(node -e "const fs=require('fs');const p=process.env.HOME+'/.xcrawl/config.json';const k=JSON.parse(fs.readFileSync(p,'utf8')).XCRAWL_API_KEY||'';process.stdout.write(k)")"
CREATE_RESP="$(curl -sS -X POST "https://run.xcrawl.com/v1/scrape" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_KEY}" \
-d '{"url":"https://example.com/product/1","mode":"async","output":{"formats":["json"]},"json":{"prompt":"Extract title and price."}}')"
This example performs an outbound request to XCrawl containing both the bearer token and the user-specified scrape payload. External transmission is the core function of the skill, but without consent and target restrictions it can expose secrets, sensitive URLs, or scraped content to a third party.
const fs=require("fs");
const apiKey=JSON.parse(fs.readFileSync(process.env.HOME+"/.xcrawl/config.json","utf8")).XCRAWL_API_KEY;
const body={url:"https://example.com",mode:"sync",output:{formats:["markdown","json"]},json:{prompt:"Extract title and publish date."}};
fetch("https://run.xcrawl.com/v1/scrape",{
method:"POST",
headers:{"Content-Type":"application/json",Authorization:`Bearer ${apiKey}`},
body:JSON.stringify(body)
No suspicious patterns detected.