Back to skill

Security audit

Fintech Customer Support

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its fintech support purpose, but it handles sensitive customer data with unsafe command/file patterns and under-disclosed third-party processing.

Review carefully before installing in a real support environment. Use only with a trusted, pinned package source; disable or explicitly approve third-party LLM classification for customer messages; replace shell-string examples with structured, non-shell tool calls; validate customer IDs and transaction references; and define retention, permissions, redaction, and approved network destinations for all stored or transmitted support data.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
triage.py:42
Finding

Unredacted fintech customer messages are transmitted to a third-party LLM service

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:62
Finding

Skill instructions interpolate untrusted customer content into shell command templates

Content
View full analysis
"` to get the intent label. ``` ```text - Run `python3 handlers.py escalate --customer-id --summary ""` ``` ### Technical Analysis The Skill directs the Agent to place customer-controlled messages, identifiers, and generated summaries directly inside shell command strings. Quoting a value with double quotes does not safely neutralize shell constructs such as command substitution, backticks, embedded quotes, or shell metacharacters. For example, if a message containing `$(command)` is substituted into the documented double-quoted command and executed by a shell, command substitution may occur before Python receives the argument. The Python scripts themselves use `argparse`, but this does not protect against evaluation that occurs earlier in the invoking shell. The vulnerable operation is unnecessary. The declared functionality only requires passing text to a Python process, which can be done with an argument-array process API or through standard input without invoking a shell. ### Attack Path 1. An attacker submits a support message or escalation content containing shell syntax. 2. The Skill instructs the Agent to substitute that untrusted content into a quoted command template. 3. The Agent executes the constructed command through a shell. 4. The shell evaluates command substitution or syntax embedded in the content. 5. The injected command runs with the same operating-system identity and environment as the Agent. Actual exploitability depends on whether the host Agent uses a shell to execute the displayed command. The instructions nevertheless create an unsafe and directly exploitable invocation pattern for shell-based hosts. ### Impact Assessment Successful exploitation ...[truncated 384 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
handlers.py:48
Finding

Unsanitized customer IDs allow persistent-memory path traversal

Content
View full analysis
dict: path = MEMORY_DIR / f"{customer_id}.json" if path.exists(): try: return json.loads(path.read_text()) except json.JSONDecodeError: return {} return {} def save_customer_memory(customer_id: str, data: dict) -> None: path = MEMORY_DIR / f"{customer_id}.json" existing = load_customer_memory(customer_id) existing.update(data) path.write_text(json.dumps(existing, indent=2)) ``` ### Technical Analysis `customer_id` is incorporated directly into a filesystem path without validation or containment checking. Values containing `../` components can escape `~/.openclaw/memory/support`, while an absolute path can cause `pathlib` to discard the intended base directory. Because both reading and writing use the resulting path, an attacker-controlled customer ID can target JSON files outside the support-memory directory. The `.json` suffix limits some target choices but does not prevent access to arbitrary reachable JSON paths. The command-line dispatcher accepts `--customer-id` without applying any validation before these functions are called. The code also does not explicitly enforce restrictive permissions on customer-memory files. ### Attack Path 1. An attacker provides or influences a customer ID containing traversal components or an absolute path. 2. The Agent invokes a handler with that value through `--customer-id`. 3. A handler calls `load_customer_memory()` or `save_customer_memory()`. 4. `MEMORY_DIR / f"{customer_id}.json"` resolves outside the intended support directory. 5. The process reads an external JSON file or updates and writes the selected JSON path. For example, a traversal-form identifier can cause the final path to resolve into another ...[truncated 520 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:22
Finding

Executable package dependency is installed without a pinned version or integrity verification

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (18)

Tainted flow: 'req' from os.environ.get (line 120, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · handlers.py (reported line 92)May include surrounding context.

python
url = f"{API_BASE}{path}"
    req = urllib.request.Request(url, headers=HEADERS, method="GET")
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            return json.loads(resp.read())
    except (urllib.error.URLError, json.JSONDecodeError) as exc:
        print(f"[API ERROR] GET {path}: {exc}", file=sys.stderr)

Tainted flow: 'req' from os.environ.get (line 120, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · handlers.py (reported line 110)May include surrounding context.

python
url = f"{API_BASE}{path}"
    req = urllib.request.Request(url, headers=HEADERS, method="GET")
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            return json.loads(resp.read())
    except (urllib.error.URLError, json.JSONDecodeError) as exc:
        print(f"[API ERROR] GET {path}: {exc}", file=sys.stderr)

Tainted flow: 'req' from os.environ.get (line 120, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The escalation webhook URL is taken directly from an environment variable and used for outbound POSTs without validation or allowlisting. If deployment configuration is compromised or mis-set, sensitive escalation payloads containing customer identifiers, summaries, and prior issue context could be exfiltrated to an attacker-controlled endpoint.

Content

Scanner excerpt · handlers.py (reported line 127)May include surrounding context.

python
method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=8) as resp:
            return resp.status < 300
    except urllib.error.URLError:
        return False

Tainted flow: 'req' from os.environ.get (line 52, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · triage.py (reported line 63)May include surrounding context.

python
)

    try:
        with urllib.request.urlopen(req, timeout=8) as resp:
            data = json.loads(resp.read())
            label = data["choices"][0]["message"]["content"].strip().upper()
            if label in INTENT_LABELS:

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full customer support agent with operational support workflows and autonomous resolution capabilities. The supplied code only classifies a single incoming message into a small set of intents and prints the label. While the intent categories align with parts of the declared domain, the code does not execute any support actions, compose responses, retrieve transfer status, initiate refunds, handle suspensions, guide KYC, escalate cases, or maintain handoff context. Its actual purpose is a narrow triage/classification component, which is materially narrower than the declared end-to-end support agent.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger patterns are extremely broad, including 'any message that reads like a support request in any language,' which can cause accidental activation on unrelated conversations. In a fintech setting, false activations may lead the agent to access transaction/account data, write memory, or initiate support workflows without sufficient relevance or user confirmation.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

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

md
tell them you don't need that information and they should keep it private.
- If a customer appears distressed about a large sum of money, prioritise
  speed — escalate immediately rather than attempting auto-resolution.
- Always respond in the language the customer used to contact you.
- Keep responses short. Customers using remittance apps are often on mobile,
  often in a hurry. One or two paragraphs maximum unless they ask for detail.
- Do not use jargon. "Your transfer is being processed by the receiving

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · README.md (reported line 52)May include surrounding context.

md
"fintech-support-agent": {
        "env": {
          "LLM_API_KEY": "your-openai-or-other-key",
          "TRANSFER_API_BASE_URL": "https://api.yourproduct.com/v1",
          "TRANSFER_API_KEY": "your-internal-api-key",
          "SUPPORT_EMAIL": "ops@yourproduct.com",
          "ESCALATION_WEBHOOK_URL": "https://hooks.slack.com/your-webhook"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares access to environment variables, Python execution, curl/network use, and implies file read/write behavior, but it does not define any explicit permission boundary such as allowed tools or scoped capabilities. In a fintech support context, this increases the chance of over-privileged execution, unintended data access, or misuse of sensitive credentials like API keys and webhook URLs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill mandates persistent storage of customer IDs, issue types, outcomes, and timestamps without any notice, consent flow, retention limit, or privacy controls. Because this is a fintech support agent, the stored data can be sensitive and regulated, creating privacy, compliance, and unauthorized profiling risks if retained or reused improperly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Customer-related support state is written to local disk under the user's home directory without any encryption, retention policy, access control checks, or disclosure. In a fintech context, even seemingly limited fields like transfer references, statuses, and escalation history can expose sensitive financial-support metadata to other local users, backups, or compromised processes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
78% confidence
Finding

The skill persistently stores all ticket events and uses them to compute weekly summaries and stale-ticket statistics. While basic case memory supports customer handling, aggregated operational analytics and digest generation are not an obvious requirement of resolving tier-1 fintech support conversations across messaging channels.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The ticket log appends customer-linked records to a local JSON file without user-facing notice or technical safeguards. Because this log aggregates incidents over time, it creates a richer dataset of support interactions that could reveal account issues, disputes, and escalations if the host is shared or compromised.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a customer support agent focused on handling transfer lookups, refunds, account suspensions, KYC guidance, and complaint escalation for customer tickets. The weekly_digest handler instead generates an internal operational analytics report from accumulated ticket logs, which is a distinct reporting/management function not reflected in the stated skill description.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The weekly digest prints customer-linked ticket details, including customer identifiers and issue types, in plain-language output intended for forwarding. In a fintech support environment, this increases the risk of unnecessary internal disclosure or accidental sharing of sensitive customer support history beyond personnel with a need to know.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Customer messages are sent verbatim to an external LLM API, which can expose sensitive financial-support content such as transfer details, account issues, KYC information, or complaints containing personal data. In a fintech support context, this increases privacy, compliance, and data-handling risk, especially if users are not informed and the message content is not minimized or redacted before transmission.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

The code transmits customer-supplied support content to an external service endpoint. In a fintech-support skill, those messages may contain personal, financial, or identity-verification data, so the external transmission itself is security-relevant and potentially risky if not tightly governed.

Content

Scanner excerpt · triage.py (reported line 53)May include surrounding context.

python
}

    req = urllib.request.Request(
        "https://api.openai.com/v1/chat/completions",
        data=json.dumps(payload).encode(),
        headers={
            "Content-Type": "application/json",

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The module docstring says handlers provide human-readable summaries and never print raw JSON. However, the KYC handler outputs UPLOAD_URL taken directly from API response data, which contradicts the documented claim of exclusively human-readable summarized output and exposes raw machine-provided fields verbatim.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.