Back to skill

Security audit

finddata.skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent FindData API helper, but it asks agents to collect API keys from chat and its Python client can send that key to a configurable API origin.

Only install this if you are comfortable sending your data questions to FindData and using a FindData API key. Do not paste the key into chat; prefer setting it through a trusted environment or secret manager. Also avoid setting FINDDATA_BASE_URL unless you fully trust the destination, because the client may send the API key there.

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/finddata.py:23
Finding

API Key Exposure Through an Unrestricted Base URL

Content
View full analysis

Vulnerability Details

File Location: scripts/finddata.py, lines 23–31 and 38–42
Vulnerability Type: Credential disclosure through an attacker-controlled API origin
Risk Level: Medium

Vulnerable Code

python
def __init__(
    self,
    api_key: Optional[str] = None,
    base_url: Optional[str] = None,
):
    self.api_key = api_key or os.environ.get("FINDDATA_API_KEY", "")
    self.base_url = (base_url or os.environ.get("FINDDATA_BASE_URL", self.DEFAULT_BASE_URL)).rstrip("/")
    self.session = requests.Session()
    if self.api_key:
        self.session.headers["X-API-Key"] = self.api_key
    self.session.headers["Content-Type"] = "application/json"

def query(self, question: str, strategy: str = "smart") -> dict:
    resp = self.session.post(
        f"{self.base_url}/query",
        json={"query": question, "strategy": strategy},
    )

The same credential-bearing session is also used by catalog() and health():

python
def catalog(self) -> dict:
    """List all available data sources."""
    resp = self.session.get(f"{self.base_url}/catalog")
    resp.raise_for_status()
    return resp.json()

def health(self) -> dict:
    """Check API health status."""
    resp = self.session.get(f"{self.base_url}/health")
    resp.raise_for_status()
    return resp.json()

Technical Analysis

The client stores X-API-Key as a default session header while allowing the request origin to be selected through either the base_url constructor parameter or the FINDDATA_BASE_URL environment variable. It performs no scheme enforcement, hostname allowlisting, or explicit authorization check before forwarding the credential.

Consequently, anyone who can influence client construction or the process environment can cause the API key to be transmitted to an arbitrary HTTP or HTTPS server. Allowing plaintext HTTP also permits interception by a network-positioned attacker.

Because the header is configured on the shared session, the issue aff ...[truncated 1339 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict authenticated requests to an explicit HTTPS origin allowlist, such as https://finddata.ai.
  2. Parse the URL and reject non-HTTPS schemes, embedded user information, malformed hosts, and unexpected ports.
  3. Do not attach credentials as global session headers when requests may target configurable origins. Add X-API-Key only after validating each request URL.
  4. If custom endpoints are required, make them an explicit opt-in and require separate credentials rather than reusing the production API key.
  5. Disable cross-origin redirects for authenticated requests or validate every redirect target before forwarding authentication headers.
  6. Treat FINDDATA_BASE_URL as security-sensitive configuration and prevent untrusted users from controlling the process environment.
  7. Add tests confirming that credentials are never sent to plaintext, unapproved, or redirected origins.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/finddata.py:38
Finding

Unbounded Network Requests Can Block the Client Indefinitely

Content
View full analysis

Vulnerability Details

File Location: scripts/finddata.py, lines 38–57
Vulnerability Type: Missing network timeouts causing denial of service
Risk Level: Low

Vulnerable Code

python
resp = self.session.post(
    f"{self.base_url}/query",
    json={"query": question, "strategy": strategy},
)
resp.raise_for_status()
return resp.json()

def catalog(self) -> dict:
    """List all available data sources."""
    resp = self.session.get(f"{self.base_url}/catalog")
    resp.raise_for_status()
    return resp.json()

def health(self) -> dict:
    """Check API health status."""
    resp = self.session.get(f"{self.base_url}/health")
    resp.raise_for_status()
    return resp.json()

Technical Analysis

None of the requests calls specifies a timeout. The Requests library does not apply a default timeout, so connection establishment or response reads may wait indefinitely.

A remote endpoint that accepts a connection but stalls before completing its response can retain the calling thread or worker for an unbounded period. The condition may also occur because of service degradation or network failure, without an active attacker.

Attack Path

  1. The client sends a request to the configured API endpoint.
  2. The endpoint accepts the connection but deliberately or accidentally stops sending response data.
  3. Because no connect or read timeout exists, the request remains blocked.
  4. Repeated calls occupy additional threads, workers, or agent execution slots.
  5. Available processing capacity may eventually be exhausted, degrading or denying service.

If an attacker can also control base_url, exploitation is direct. Otherwise, exploitation requires control of, or a network position affecting, the configured service.

Impact Assessment

Exploitation can block the current worker indefinitely and may cause broader resource exhaustion when multiple requests accumulate. Affected assets include application availability, worker capacity, and a ...[truncated 195 chars]

Remediation
View remediation

Remediation Suggestions

  1. Set explicit connect and read timeouts for every request, for example:
python
timeout = (5, 30)
resp = self.session.post(
    f"{self.base_url}/query",
    json={"query": question, "strategy": strategy},
    timeout=timeout,
)
  1. Apply equivalent timeout settings to catalog() and health().
  2. Catch requests.Timeout and return or raise a controlled, application-specific error.
  3. Use bounded retries only for transient failures, with exponential backoff and jitter.
  4. Limit total retry duration and concurrent outstanding requests so retries cannot amplify resource exhaustion.
  5. Add tests using a deliberately slow endpoint to verify that all methods terminate within the configured deadline.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
60% confidence
Finding

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).

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

Usage

bash
curl -s -X POST https://finddata.ai/api/query \
  -H "X-API-Key: $FINDDATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "Apple stock price"}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs the agent to extract a user-provided API key from the conversation and transmit it to an external service, but it provides no privacy warning, consent boundary, or safer credential-handling mechanism. This creates a clear risk of sensitive secret handling through natural-language input, which can lead to inadvertent disclosure, logging, or misuse of the key.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Telling the agent to extract a key from the user's message and use it as an HTTP header establishes a natural-language secret exfiltration pattern. Even if intended for convenience, it normalizes harvesting credentials from chat content, increasing the chance that secrets are retained in logs, reused in the wrong context, or sent to an attacker-controlled or unverified endpoint.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The repeated instruction to pull keys from user text reinforces unsafe secret-collection behavior and makes accidental leakage more likely. Repetition in setup guidance increases the odds that downstream agents or users will treat chat as an acceptable channel for transmitting credentials, which is dangerous in systems where prompts may be stored, inspected, or replayed.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 33)May include surrounding context.

Usage

bash
curl -s -X POST https://finddata.ai/api/query \
  -H "X-API-Key: $FINDDATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "Apple stock price"}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code sends the user's natural-language question to a remote service via HTTP and may include the X-API-Key header configured earlier, but the query method provides no warning, confirmation, or explicit disclosure that user input is transmitted off-system. The surrounding docstrings describe functionality but do not clearly warn about network transmission or credential use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The constructor automatically loads an API key from an environment variable and attaches it to outbound requests, which is sensitive credential handling. While this is common behavior for API clients, the file does not explicitly warn users that credentials are being sourced from the environment and transmitted to the service.

Content

No source excerpt is available for this finding.