T09 · Insecure Skill Coding Practices
- Location
scripts/cf_markdown.py:42- Finding
Website Credentials and Session Cookies Exposed Through Command-Line Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly does what it claims, but it should be reviewed because it encourages passing website passwords and session cookies on the command line and sends them to Cloudflare without a clear warning.
Review before installing if you may use it on authenticated sites. Avoid passing real passwords, production session cookies, bearer tokens, or sensitive HTML through command-line arguments. Use least-privilege Cloudflare tokens, small scoped crawls, and temporary test accounts or short-lived sessions when authenticated rendering is unavoidable.
scripts/cf_markdown.py:42Website Credentials and Session Cookies Exposed Through Command-Line Arguments
The code clearly targets the Cloudflare /crawl endpoint and supports asynchronous crawl orchestration: creating jobs, checking results, waiting, cancelling, and exporting outputs. This aligns with the crawling portion of the description and with configurable crawl/render options such as gotoOptions, source, render, and inclusion flags. However, the declared purpose also claims the skill can convert a rendered page to Markdown with /markdown, which is not present in this code chunk at all. The markdown handling here only saves markdown returned from crawl records; it does not call the /markdown endpoint or perform single-page rendered extraction. Additionally, the code includes job-management capabilities beyond the description’s main emphasis, though those are related rather than unrelated. Because a prominent declared capability (/markdown extraction) is absent from the actual code, this is a description-behavior mismatch.
The code aligns well with the portion of the description about converting a rendered page to Markdown and controlling render/load behavior through gotoOptions, cookies, auth, userAgent, and request filtering. However, the declared purpose also presents the skill as supporting asynchronous whole-site crawling with /crawl, including use cases like documentation-site crawling and multi-page extraction. No crawling functionality, /crawl endpoint usage, async job handling, or multi-page orchestration appears in this code chunk. Because an important declared capability is missing from the actual behavior shown, this is a description-to-behavior mismatch for the supplied chunk.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
## Main endpoints
- `POST /accounts/{account_id}/browser-rendering/crawl`
- `GET /accounts/{account_id}/browser-rendering/crawl/{job_id}`
- `DELETE /accounts/{account_id}/browser-rendering/crawl/{job_id}`
## Create-job behavior
- Returns a crawl `job_id`
The skill declares environment, network, and file output capabilities but does not explicitly constrain or disclose tool scope through a permissions or allowed-tools section. That increases the chance of overbroad execution, unintended network access, or writing sensitive fetched/crawled data to disk without clear policy boundaries.
The documentation explicitly instructs users to pass session cookies and username/password authentication JSON to a third-party Cloudflare rendering API, but it does not clearly warn that these secrets will be transmitted off-host to an external service. In this skill context, that omission is more dangerous because the tool is specifically designed to proxy web content retrieval through Cloudflare, making credential leakage or unintended sharing of authenticated session state a realistic risk.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import urllib.parse
import urllib.request
API_BASE = "https://api.cloudflare.com/client/v4/accounts/{account_id}/browser-rendering/markdown"
def fail(msg: str, code: int = 1):
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import urllib.parse
import urllib.request
API_BASE = "https://api.cloudflare.com/client/v4/accounts/{account_id}/browser-rendering/markdown"
def fail(msg: str, code: int = 1):