Back to skill

Security audit

Dataify Brand Monitoring

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent Dataify brand-monitoring tool, but it uses a Dataify API token and external collection workflows in ways that need review before installation.

Install only if you are comfortable using a Dataify account token and sending brand queries, source URLs, and public collection targets to Dataify. Prefer bounded runs with dry-run, max-actions, and no-wait controls when needed; avoid running generated curl previews from untrusted parameters; consider rotating the Dataify token if this version has already been used for task polling.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/wait_for_task.py:30
Finding
API Token Exposed in URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wait_for_task.py:30-39`, with vulnerable calls at `scripts/wait_for_task.py:100-105` and `scripts/wait_for_task.py:124-129` **Vulnerability Type**: Sensitive credential exposure through request URLs **Risk Level**: Medium ### Vulnerable Code ```python def request_json(endpoint, params, api_key, timeout): url = endpoint + "?" + urllib.parse.urlencode(params) request = urllib.request.Request(url, method="GET") try: with urllib.request.urlopen(request, timeout=timeout) as response: content = response.read() charset = response.headers.get_content_charset() or "utf-8" text = content.decode(charset, errors="replace") ``` The function is invoked with the API token included in `params`: ```python payload = request_json( STATUS_ENDPOINT, {"api_key": api_key, "task_id": task_id}, api_key, request_timeout, ) ``` The same behavior occurs when downloading results: ```python return request_json( DOWNLOAD_ENDPOINT, {"api_key": api_key, "task_id": task_id, "type": "json"}, api_key, request_timeout, ) ``` ### Technical Analysis The `DATAIFY_API_TOKEN` value is serialized into the query string of GET requests. Although the requests use HTTPS and are sent to the declared Dataify domain, HTTPS only protects the request in transit. It does not prevent complete URLs from being recorded by the destination server, reverse proxies, API gateways, observability systems, browser or HTTP debugging tools, network security products, or exception-reporting infrastructure. The response-body redaction performed later by the function does not protect request metadata: ```python if api_key: text = text.replace(api_key, "<redacted>") ``` This replacement only applies to the received response text. It cannot remove the token from access logs or telemetry generated before or during request processing. The token is required for legitima ...[truncated 1419 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `api_key` from all URL query parameters. 2. Transmit the credential using an authorization header: ```python def request_json(endpoint, params, api_key, timeout): url = endpoint + "?" + urllib.parse.urlencode(params) request = urllib.request.Request( url, headers={"Authorization": "Bearer {}".format(api_key)}, method="GET", ) ``` 3. Retain only non-secret values such as `task_id` and `type` in the query string. 4. If the provider does not support authorization headers, use a POST body where supported and document the residual logging risk. 5. Configure application, proxy, and API gateway logging to redact authorization headers and known secret fields. 6. Rotate any tokens that may already have appeared in URL logs. 7. Add tests asserting that generated request URLs never contain the API token or an `api_key` parameter. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/catalog_builder.py:66
Finding
Shell Command Injection in Generated curl Preview<![CDATA[ ## Vulnerability Details **File Location**: `scripts/catalog_builder.py:66-78`, with the preview path at `scripts/catalog_builder.py:119-126` **Vulnerability Type**: Shell command injection through unsafe command generation **Risk Level**: Medium ### Vulnerable Code ```python 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"]), " -d 'spider_id={}'".format(tool["tool_sign"]), " -d 'spider_parameters={}'".format(spider_parameters_json), " -d 'spider_errors=true'", " -d 'file_name={{TasksID}}'", ]) ``` The generated string is exposed as an executable preview: ```python payload_json = json.dumps(rows, ensure_ascii=False, separators=(",", ":")) if args.preview: print(build_curl(tool, payload_json)) return 0 ``` ### Technical Analysis The function interpolates `spider_parameters_json` into a shell command enclosed in single quotes without shell escaping. The JSON originates from `--params-json` or `--values-file` and can contain attacker-controlled string values. JSON escaping does not provide shell escaping. In a POSIX shell, a single quote inside the JSON terminates the surrounding shell argument. Subsequent shell metacharacters can then introduce additional commands. For example, a parameter value containing a payload shaped like: ```text '; attacker-command; # ``` can terminate the `-d` argument and append a command when the generated preview is copied into a shell. The Python script does not execute this preview directly, so exploitation requires a user or automation system to execute the emitted curl command. Nevertheless, the feature deliberately emits a ready-to-run command, making this a credible command-generation vulnerability. The catalog ...[truncated 1463 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer a non-executable structured preview that displays the HTTP method, endpoint, headers with redacted credentials, and form fields as JSON. 2. If curl output is required for POSIX shells, apply `shlex.quote()` separately to every dynamic argument: ```python import shlex def curl_data(name, value): return "-d {}".format(shlex.quote("{}={}".format(name, value))) ``` 3. Escape all dynamic values, including `spider_parameters_json`, `spider_name`, `tool_sign`, and the endpoint. 4. Do not claim that one generated command is portable across POSIX shells, PowerShell, and Command Prompt. Generate shell-specific output only when explicitly requested. 5. Add tests with single quotes, newlines, command substitutions, semicolons, backticks, and shell redirection characters. 6. Clearly label any command preview as potentially unsafe to execute when its values originate from untrusted sources. 7. Avoid passing secrets in generated command text; continue referencing the environment variable rather than expanding its value. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill describes capabilities that involve environment access, shell execution, networking, and file operations, yet no explicit permission declaration is present. This creates a transparency and governance gap: an agent may perform sensitive actions without clear user-visible scoping, increasing the risk of overbroad execution or misuse if the surrounding platform relies on declared permissions for policy enforcement.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The dependency skill’s declared purpose is task monitoring and token setup, which is materially different from the parent brand-monitoring capability. This kind of scope mismatch can cause the agent to invoke unrelated operational behavior, including credential-handling and external task control, increasing the attack surface and enabling actions the user did not reasonably expect from a brand-listening skill.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The skill includes cross-platform guidance for configuring an API token, which is a sensitive operational capability not obviously required by a brand-monitoring feature. Even though it says not to print the token, teaching the agent to steer users through environment credential setup broadens the chance of credential mishandling, social-engineering-like prompting, or unauthorized workflow escalation.

Context-Inappropriate Capability

High
Confidence
92% confidence
Finding
The skill instructs the agent to manage asynchronous task lifecycles, poll remote status, download results, and resume workflows automatically. In the context of a brand-monitoring skill, this is an unnecessary operational expansion that can trigger external actions, consume credits, process data without renewed user intent, and make it easier to hide unintended behavior behind 'automation.'

Description-Behavior Mismatch

High
Confidence
89% confidence
Finding
This agent file defines a generic task-monitoring helper that waits on Dataify tasks and returns results, which is functionally different from the declared brand-monitoring skill purpose. That mismatch can enable unintended cross-skill invocation or broaden the skill's effective capability surface, causing users or orchestrators to invoke operational task-handling behavior they did not expect from a brand-monitoring package.

Context-Inappropriate Capability

High
Confidence
90% confidence
Finding
The script exposes a generic task submission path driven by a shared catalog and arbitrary tool_sign values, allowing use of Dataify capabilities beyond the brand-monitoring skill’s declared scope. In a skill context, this scope mismatch is dangerous because callers may invoke unrelated collection or processing jobs under the cover of a narrower skill, defeating least-privilege and review expectations.

Description-Behavior Mismatch

Medium
Confidence
82% confidence
Finding
The file is a reusable builder client for any catalog entry, not code narrowly implementing brand monitoring behavior. That broad, generic design increases the chance that this skill can be repurposed to run unintended jobs, making the skill more dangerous than its metadata suggests.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
This dependency skill performs Amazon review scraping, while the enclosing skill is described as brand monitoring across public sources. That scope mismatch is dangerous because it can introduce undisclosed data-collection behavior, bypass user expectations, and expand the agent’s effective permissions/workflows beyond its declared purpose.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
The skill’s behavior is materially different from the parent skill metadata: it performs Amazon review scraping and tokenized task submission rather than broad brand monitoring across public sources. This scope mismatch can cause an orchestrator or user to invoke the skill in contexts they did not intend, leading to unauthorized collection workflows, policy bypass, or data-handling actions outside the declared purpose.

Intent-Code Divergence

Medium
Confidence
84% confidence
Finding
The file contains contradictory instructions about whether to send users to the Dataify dashboard after successful completion. Conflicting post-action guidance increases the chance that an agent will follow the wrong branch, potentially exposing users to unintended external navigation, inconsistent handling of results, or policy noncompliance.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This script submits Amazon product comment scraping jobs, which is materially different from the declared brand-monitoring use case. That mismatch is dangerous because hidden or unrelated collection capabilities can bypass user expectations and governance controls, and may cause unauthorized scraping or policy violations under the guise of a different skill.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The workflow sends user-supplied queries and URLs to third-party Dataify endpoints and may also fetch arbitrary URLs through the web unlocker service, but this code path provides no in-band consent, warning, or destination allowlisting. In a skill context, that means user input and monitoring targets can be silently transmitted off-system, creating privacy, compliance, and potential SSRF-style relay concerns depending on what URLs are accepted upstream.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Enabling implicit invocation without a narrowly scoped trigger allows the agent to call this data-collection skill automatically in response to loosely related prompts. In a brand-monitoring context, that can cause unintended scraping requests, over-collection of third-party content, and user-surprising actions without clear authorization boundaries.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- 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.
Confidence
84% confidence
Finding
The instruction to continue the original task automatically after token verification removes an additional consent checkpoint before performing external operations. In a skill already handling authentication state and asynchronous workflows, that increases the risk of unintended execution, especially if the prior context was ambiguous or stale.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
2. Read `DATAIFY_API_TOKEN` from the environment. Never accept or print it as a command-line argument. If it is missing, follow [Token setup](references/token-setup.md), show only the current platform's setup command, and resume this workflow after safe verification.
3. Use an installed Dataify task-status/result tool when available. Do not invent an endpoint that is not documented in the repository or exposed by a connected tool.
4. After a scraper submission, monitor by default with `scripts/wait_for_task.py`. Stop at submission only when the user explicitly asks for a task ID or `--no-wait` behavior.
5. If status is queued or running, continue bounded monitoring. Do not ask the user to request monitoring separately.
6. If succeeded, download and return the available result. Summarize large results and preserve access to raw data.
7. If failed, return the provider error, likely corrective action, and whether retrying is safe.
8. If monitoring times out or is interrupted, report the task ID and exact resume command. Never resubmit merely because monitoring stopped.
Confidence
90% confidence
Finding
The skill explicitly tells the agent not to ask the user to request monitoring separately and to continue bounded monitoring automatically. That is autonomous external action: it can spend time, resources, and potentially credits while retrieving data the user may not have intended to fetch immediately.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
_dependencies/skills/dataify-task-operations/scripts/task_runtime.py:38

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/task_runtime.py:38