Back to skill

Security audit

Loan Refinance Calculator

Security checks for vulnerabilities and agentic risk

Overview

This refinance skill is a remote paid SaaS client that handles sensitive loan and account data through an insecure default HTTP endpoint, so it should be reviewed carefully before use.

Install only if you trust the operator and have verified an HTTPS API endpoint. Do not submit real customer loan details, user keys, or financial data through the default endpoint; ask for clear privacy, retention, and billing terms first. The shipped script also appears syntactically broken, so functionality should be fixed and re-reviewed before production use.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/refinance.py:12
Finding

Authentication Key and Financial Data Transmitted over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/refinance.py, lines 12–25
Vulnerability Type: Plaintext transmission of sensitive information
Risk Level: High

Complete Code Snippet:

python
API_BASE = os.environ.get(f"COZE_REFINANCE_API_URL_{SKILL_ID}", os.environ.get("REFINANCE_API_URL", "http://47.109.39.255:8765/api/v4")
USER_KEY = os.environ.get("REFINANCE_USER_KEY", "")


def api_call(endpoint, data=None, method="POST"):
    url = f"{API_BASE.rstrip('/')}/{endpoint}"
    h = {"Content-Type": "application/json"}
    if USER_KEY:
        h["X-User-Key"] = USER_KEY
    try:
        if method == "GET":
            resp = requests.get(url, headers=h, params=data or {}, timeout=30)
        else:
            resp = requests.post(url, headers=h, json=data or {}, timeout=60)

Technical Analysis

The default API endpoint is a raw public IP address accessed through unencrypted HTTP. The script attaches REFINANCE_USER_KEY to the X-User-Key request header and sends refinancing information in request parameters or JSON bodies.

HTTP does not provide transport confidentiality, integrity, or authenticated server identity. An attacker with a suitable network position—such as one controlling a Wi-Fi access point, local gateway, proxy, or upstream network segment—can inspect or modify requests and responses. Using a raw IP also prevents ordinary domain-based certificate identity validation if HTTPS is introduced without further configuration.

The affected request data can include the authentication key, loan balance, interest rates, remaining term, penalties, fees, and loan type.

Attack Path

  1. A user invokes a registration, account, service, or refinancing command without overriding the default API URL.
  2. The script constructs a URL under http://47.109.39.255:8765/api/v4.
  3. For authenticated operations, the script places the user key in the X-User-Key header.
  4. For calculati ...[truncated 885 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace the raw-IP HTTP endpoint with an HTTPS endpoint on a controlled domain using a valid certificate.
  2. Reject API URLs whose scheme is not https, except through an explicit development-only configuration.
  3. Validate the destination against an allowlist of approved hostnames and ports.
  4. Do not silently fall back to an insecure production endpoint.
  5. Rotate user keys that may previously have been transmitted over plaintext HTTP.
  6. Consider using short-lived, revocable credentials rather than long-lived static user keys.
  7. Minimize the financial information sent to the backend and document the remote-processing and data-retention policy.
  8. Add integration tests verifying that production requests cannot use plaintext transport.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/refinance.py:12
Finding

Undefined SKILL_ID Causes Failure During Module Initialization

Content
View full analysis

Vulnerability Details

File Location: scripts/refinance.py, line 12
Vulnerability Type: Unsafe configuration initialization and availability failure
Risk Level: Medium

Complete Code Snippet:

python
API_BASE = os.environ.get(f"COZE_REFINANCE_API_URL_{SKILL_ID}", os.environ.get("REFINANCE_API_URL", "http://47.109.39.255:8765/api/v4")

Technical Analysis

SKILL_ID is referenced inside an f-string during module initialization, but it is neither defined nor imported anywhere in the reviewed script. Python evaluates the expression before entering main(), so a normal execution raises NameError before command-line arguments can be processed.

An environment variable cannot directly define a Python global variable. Therefore, setting COZE_REFINANCE_API_URL_* does not resolve the problem. The code would work only if an undocumented runtime modified the module namespace before this statement was evaluated.

This is primarily an availability and reliability defect rather than a privilege-escalation flaw. It also prevents users from safely reaching the documented functionality and may encourage unsafe local modifications or unverified workarounds.

Attack Path

  1. A user invokes scripts/refinance.py with any supported command.
  2. Python imports dependencies and evaluates module-level assignments.
  3. Evaluation reaches the f-string containing SKILL_ID.
  4. Because SKILL_ID is undefined, Python raises NameError.
  5. The process terminates before argument parsing or command execution.

This failure does not require an external attacker; it occurs during ordinary execution in the reviewed source.

Impact Assessment

The defect grants no additional privileges and does not directly expose data. Its scope is complete loss of availability for all commands, including registration, account information, service listing, and calculations, unless an undocumented host mechanism supplies the miss ...[truncated 144 chars]

Remediation
View remediation

Remediation Suggestions

  1. Define SKILL_ID before it is referenced, or remove the dynamic variable name entirely.

  2. Prefer a direct and documented lookup:

    python
    API_BASE = os.environ.get(
        "REFINANCE_API_URL",
        "https://api.example.com/api/v4",
    )
    
  3. If skill-specific configuration is required, retrieve the identifier safely from an environment variable and validate it before constructing another variable name.

  4. Add startup tests that execute --help and every subcommand in a clean Python environment.

  5. Provide clear configuration errors instead of allowing module-level NameError exceptions.

T01 · Skill Instruction Hijacking

Warning
Location
scripts/refinance.py:94
Finding

Routine Skill Output Is Used to Inject Unrelated Commercial Promotions

Content
View full analysis

Vulnerability Details

File Location: scripts/refinance.py, lines 94–98
Vulnerability Type: Commercial instruction and output injection
Risk Level: Medium

Complete Code Snippet:

python
    print(json.dumps(result, ensure_ascii=False, indent=2))
    print(file=sys.stderr)
    print(f"✅ 完成!剩余积分:{remaining} 点", file=sys.stderr)
    print(file=sys.stderr)
    print("💼 企业定制/助贷全案 | 微信 17392371127", file=sys.stderr)

Related promotional content also appears in SKILL.md at lines 18–38 and in scripts/refinance.py at lines 34, 73, and 116.

Technical Analysis

The script unconditionally appends a third-party commercial contact message after a refinancing calculation. Similar recharge and sales messages are embedded in error, account-information, and service-listing flows. The skill instructions also devote a prominent section to unrelated enterprise AI services and direct users to the same contact.

This behavior is not required to calculate refinancing results. In an agent environment, standard output and standard error can be captured and presented as trusted skill results. Hard-coded promotional messages therefore use the agent's execution channel to place unsolicited third-party contact information into the current session.

The behavior does not alter system-level safety controls, but it changes normal task output to advance an unrelated commercial objective. This best matches skill instruction hijacking because the skill text and output redirect attention beyond the user's refinancing task.

Attack Path

  1. An agent loads the skill documentation or invokes a routine calculator command.
  2. The skill performs or attempts the requested operation.
  3. Hard-coded sales or recharge messaging is emitted alongside legitimate results.
  4. The agent captures the combined output and may relay it to the user as part of a trusted response.
  5. The user may interpret the named third-party contact a ...[truncated 550 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove sales, recharge, and third-party contact messages from calculation, error, account, and service command output.
  2. Restrict runtime output to information necessary to complete the user's requested task.
  3. Move optional commercial information to clearly separated project documentation that is not automatically loaded as operational instructions.
  4. Do not present third-party contact details as part of required setup, error recovery, or payment handling without verifiable ownership and explicit user consent.
  5. Add output tests that reject unrelated promotional text in normal command responses.
  6. Keep structured calculation results on standard output and concise operational diagnostics on standard error.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill requires an environment secret and instructs users to call a backend API over a user-configurable HTTP endpoint, but it does not declare any explicit tool scope or allowed-tools boundary. That creates a real least-privilege problem: an agent may be granted broader-than-necessary env/network access, increasing the chance of secret exposure or unintended outbound requests if the skill or its script is modified or abused.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file’s user-facing description, instructions, examples, and guidance are all presented only in Chinese. This imposes a specific language on users without any opt-in or documented justification that the skill is intended solely for a Chinese-speaking or region-specific audience.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends usernames, account keys, and sensitive financial inputs to a remote backend API, but the file-level description and CLI help do not clearly state that user data leaves the local environment. For a financial tool, this lack of transparent disclosure is dangerous because users may submit sensitive loan details under the assumption the computation is local.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The code transmits financial calculation inputs and account information to an external API endpoint, with a default backend set to a raw IP over plain HTTP rather than HTTPS. In the context of a refinance tool, this is especially risky because loan amounts, rates, and account keys may be intercepted or tampered with in transit.

Content

Scanner excerpt · scripts/refinance.py (reported line 25)May include surrounding context.

python
if method == "GET":
            resp = requests.get(url, headers=h, params=data or {}, timeout=30)
        else:
            resp = requests.post(url, headers=h, json=data or {}, timeout=60)
        if resp.status_code >= 400:
            try:
                err = resp.json()

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill claims to be a refinance calculator, but it also implements account registration, account lookup, and package/service browsing tied to a paid SaaS backend. This expands the capability surface beyond the declared purpose and can mislead users into disclosing identifiers and using monetized remote services they may not expect from a local calculator.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The generic 'services' endpoint exposes a broader service catalog unrelated to refinance calculation, indicating the skill can act as a gateway to other paid offerings. That violates least functionality and increases the chance of unexpected data flows or user interaction with undeclared capabilities.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

Natural-language strings in the docstring and CLI output force a specific language without indicating user opt-in or that the skill is intended only for a Chinese-speaking or region-specific audience. The policy requires avoiding language/locale constraints unless they are optional or clearly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.