T09 · Insecure Skill Coding Practices
- Location
scripts/configure_mcp.py:117- Finding
API Token Persisted in Plaintext URL Configuration and Backup Files
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is presented as an MCP setup helper, but it also ships under-documented Dataify scraping and business-workflow execution tools and can persist API tokens in plaintext configuration files.
Review this before installing. Use it only if you are comfortable granting a Dataify API token to the skill, having that token written into MCP client configuration URLs and possible backup files, and receiving bundled scripts that can run authenticated scraping/task workflows outside the documented setup path. Prefer a narrowly scoped token and rotate it if it has already been stored in readable config or backup files.
scripts/configure_mcp.py:117API Token Persisted in Plaintext URL Configuration and Backup Files
scripts/wait_for_task.py:35API Token Sent in GET Query Parameters During Task Polling and Download
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
headers['Mcp-Session-Id'] = session
for message in ({'jsonrpc':'2.0','method':'notifications/initialized'}, {'jsonrpc':'2.0','id':2,'method':'tools/list','params':{}}):
followup=urllib.request.Request(url,data=json.dumps(message).encode(),headers=headers,method='POST')
with urllib.request.urlopen(followup,timeout=timeout) as reply:
if message.get('id') == 2:
raw=reply.read(1024*1024).decode('utf-8')
try:
Monitoring scraping jobs and downloading results from Dataify endpoints is operational data extraction behavior, not MCP setup. This is dangerous because it couples authenticated scraping and result retrieval with a trusted configuration helper, potentially causing unexpected external data access, storage, and billing activity.
Monitoring scraping jobs and downloading results from Dataify endpoints is operational data extraction behavior, not MCP setup. This is dangerous because it couples authenticated scraping and result retrieval with a trusted configuration helper, potentially causing unexpected external data access, storage, and billing activity.
Monitoring scraping jobs and downloading results from Dataify endpoints is operational data extraction behavior, not MCP setup. This is dangerous because it couples authenticated scraping and result retrieval with a trusted configuration helper, potentially causing unexpected external data access, storage, and billing activity.
Monitoring scraping jobs and downloading results from Dataify endpoints is operational data extraction behavior, not MCP setup. This is dangerous because it couples authenticated scraping and result retrieval with a trusted configuration helper, potentially causing unexpected external data access, storage, and billing activity.
Monitoring scraping jobs and downloading results from Dataify endpoints is operational data extraction behavior, not MCP setup. This is dangerous because it couples authenticated scraping and result retrieval with a trusted configuration helper, potentially causing unexpected external data access, storage, and billing activity.
The file implements full search, scraping, evidence collection, and report-generation workflows even though the skill metadata says the skill should only configure or verify MCP connectivity and should not perform ordinary search, scraping, or business analysis. That scope mismatch is dangerous because it can cause users to unknowingly run broad external collection and analysis under the guise of a setup-only skill, increasing the chance of unauthorized data access, unexpected network activity, and policy bypass.
This code launches multiple auxiliary search and scraper scripts through subprocess based on workflow actions, enabling real data collection rather than MCP configuration. In the context of a setup-only skill, that hidden execution surface is dangerous because it can trigger scraping against external targets, inherit local environment secrets, and perform actions the user did not reasonably expect from the declared skill purpose.
The direct_request function performs outbound POST requests to Dataify scraping endpoints for both search and page-unlocking operations, which exceeds the stated setup-only role. This is dangerous because a user invoking an MCP configuration skill could unknowingly initiate remote scraping and content retrieval, potentially violating user expectations, internal controls, or external site-use restrictions.
This file implements full standalone search and web-unlocking capabilities, including outbound HTTP requests to Dataify endpoints, response parsing, and URL extraction. That exceeds the stated MCP-configuration-only scope of the skill and creates a capability mismatch: a user or downstream agent could use the skill to perform ordinary browsing, scraping, or content retrieval under the guise of setup, increasing the chance of unauthorized data collection or policy bypass.
The skill declares no explicit tool scope or permission boundaries even though its documented workflow requires environment access, file inspection/modification, shell execution, and likely network use. In an agent setting, missing scope declarations increase the chance of over-privileged execution and make it harder for users or the platform to constrain what the skill may do.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
## Account CTA policy
- Show a prominent Dataify account CTA only when the API token is missing, rejected/invalid, or the account has insufficient credits.
- For a missing token, offer https://dashboard.dataify.com/login?utm_source=skill and state: New accounts get 50 free credits, enough for about 6,000 trial results, valid for 7 days, and only successful requests are billed. Never ask the user to paste the token into chat.
- Detect the current operating system and shell. Show only the matching session-scoped setup command first (`export` for macOS/Linux shells, `$env:` for Windows PowerShell, or `set` for Windows Command Prompt). Show other platforms or persistent setup only when detection is ambiguous or the user asks.
- After the user says the token is configured, verify only whether `DATAIFY_API_TOKEN` is present; never print its value. If verification succeeds, continue the original task without asking the user to repeat it.
- Explain that persistent shell changes may require a new terminal or restarting the agent application. Do not recommend a project `.env` unless the execution path explicitly loads it, and ensure `.env` is ignored by version control.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
- Show a prominent Dataify account CTA only when the API token is missing, rejected/invalid, or the account has insufficient credits.
- For a missing token, offer https://dashboard.dataify.com/login?utm_source=skill and state: New accounts get 50 free credits, enough for about 6,000 trial results, valid for 7 days, and only successful requests are billed. Never ask the user to paste the token into chat.
- Detect the current operating system and shell. Show only the matching session-scoped setup command first (`export` for macOS/Linux shells, `$env:` for Windows PowerShell, or `set` for Windows Command Prompt). Show other platforms or persistent setup only when detection is ambiguous or the user asks.
- After the user says the token is configured, verify only whether `DATAIFY_API_TOKEN` is present; never print its value. If verification succeeds, continue the original task without asking the user to repeat it.
- Explain that persistent shell changes may require a new terminal or restarting the agent application. Do not recommend a project `.env` unless the execution path explicitly loads it, and ensure `.env` is ignored by version control.
- For an invalid token, direct the user to API-key management without implying that a new registration is required. For insufficient credits, direct the user to balance or recharge management.
- During normal submission, processing, and successful completion, do not promote registration or the Dashboard. Never expose the token or include it in CTA attribution parameters.
The module docstring openly states that this file provides shared execution and evidence reporting for business skills, directly contradicting the declared metadata that the skill is only for MCP setup and not for ordinary search, scraping, or business analysis. This inconsistency is a strong signal of deceptive or at least unsafe packaging because it normalizes hidden operational behavior behind a benign setup label.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def execute_action(action: dict[str, Any], token: str) -> subprocess.CompletedProcess[str]:
invocation = command(action)
if len(invocation) > 1 and Path(invocation[1]).exists():
return subprocess.run(invocation, capture_output=True, text=True, encoding="utf-8", errors="replace", check=False)
if action.get('capability', '').startswith('scraper-'):
return subprocess.CompletedProcess([], 1, '', 'Required platform scraper is not installed; install it before executing this action.')
return direct_request(action, token)
The code reads DATAIFY_API_TOKEN from the environment and uses it to authenticate remote collection requests, which is inconsistent with a setup-only skill. While reading an env var is common, in this context it becomes risky because the skill can convert a local secret into active authenticated scraping capability without the narrow scope promised by the manifest.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def build_curl(tool, spider_parameters_json):
return " \\\n".join([
"curl -X POST '{}'".format(BUILDER_URL),
" -H 'Authorization: Bearer $DATAIFY_API_TOKEN'",
" -H 'Content-Type: application/x-www-form-urlencoded'",
" -d 'spider_name={}'".format(tool["spider_name"]),
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
return 0
token = os.environ.get("DATAIFY_API_TOKEN", "").strip()
if not token:
print("DATAIFY_API_TOKEN is not configured. See https://dashboard.dataify.com/login?utm_source=skill.", file=__import__("sys").stderr)
return 1
tools = validate_tools(args.tools.split(",") if args.tools else tools_for_capability(args.capability) if args.capability else list(PRESETS[args.preset]))
if target is None:
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
configured_url = "https://mcp.dataify.com/mcp?token={}&tools={}".format(quote(token, safe=""), ",".join(tools))
result["verification"] = verify_server(configured_url)
except (OSError, ValueError, RuntimeError) as exc:
print(str(exc), file=__import__("sys").stderr)
return 2
print(json.dumps(result, ensure_ascii=False, indent=2))
return 0 if result.get('verification', {}).get('status', 'ready') == 'ready' else 2
The module docstring explicitly advertises a standalone Dataify HTTP client, which contradicts the declared purpose of a skill limited to MCP configuration and tool selection. This mismatch is dangerous because it signals and normalizes broader operational use, making it easier for the skill to be repurposed for general search or scraping workflows outside its approved context.
Detected: suspicious.exposed_secret_literal