Back to skill

Security audit

调整 token 鉴权机制

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its paid API purpose, but it handles reusable payment-service credentials and prompts with weak scoping and unsafe disclosure paths.

Review this skill carefully before installing. Use it only with a trusted Fast Claw service URL, avoid non-HTTPS remote endpoints, do not pass API keys on the command line, treat ~/.fast-claw/api-key.json as a secret, and confirm before any purchase, top-up, invoke, or report command because those actions can spend credits and transmit prompt content.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fast_claw_client.py:51
Finding

API Key File Is Stored Without Enforced Restrictive Permissions

Content
View full analysis
None: path = api_key_path() path.parent.mkdir(parents=True, exist_ok=True) path.write_text( json.dumps( { "api_key": api_key, "token": api_key, "service_url": service_url(), "saved_at": datetime.now(timezone.utc).isoformat(), }, indent=2, ) + "\n", encoding="utf-8", ) ``` ### Technical Analysis The client persists a reusable API key in plaintext but does not explicitly restrict the permissions of either the containing directory or the credential file. `Path.mkdir()` and `Path.write_text()` rely on the process's ambient `umask`. Under a permissive `umask`, the resulting file may be readable by other local users. If the destination file already exists with overly broad permissions, rewriting it does not correct those permissions. The implementation also does not verify file ownership or reject a symbolic-link destination before writing. Persisting a key is part of the Skill's declared functionality, but allowing ambient filesystem settings to determine access exceeds the minimum exposure required for that functionality. ### Attack Path 1. A user runs `purchase`, `wait`, or `set-api-key`. 2. The client saves the returned API key to `~/.fast-claw/api-key.json` or a path selected through `FAST_CLAW_API_KEY_PATH`. 3. The file is created or retained with permissions determined by the current `umask` or its previous mode. 4. Another local user or process with filesystem access reads the JSON file. 5. The attacker extracts the reusable `api_key` value. 6. The attacker uses the key to query the account or submit authenticated paid-service requests. A maliciously prepared dest ...[truncated 650 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fast_claw_client.py:212
Finding

Complete API Keys Can Be Exposed Through Output, Shell History, and Process Arguments

Content
View full analysis
str: if len(api_key) <= 12: return api_key return f"{api_key[:6]}...{api_key[-4:]}" ``` ```python def run_checkout_wait(session: Dict[str, object], args: argparse.Namespace) -> None: session_id = str(session["session_id"]) checkout_url = str(session["checkout_url"]) print(f"Checkout session: {session_id}") print(f"Checkout URL: {checkout_url}") if args.open_browser: webbrowser.open(checkout_url) completed = wait_for_completion(session_id, args.wait_seconds, args.poll_interval) api_key = completed.get("api_key") or completed.get("token") if api_key: write_local_api_key(str(api_key)) print(f"Saved API key to {api_key_path()}") print_json(completed) ``` ```python def cmd_set_api_key(args: argparse.Namespace) -> None: if not args.api_key: raise SystemExit("Provide --api-key.") write_local_api_key(args.api_key) print(f"Saved API key to {api_key_path()}") ``` ```python set_api_key_parser = subparsers.add_parser( "set-api-key", aliases=["set-token"], help="Manually save an API key", ) set_api_key_parser.add_argument("--api-key", dest="api_key", required=False, help="API key to save") set_api_key_parser.add_argument("--token", required=False, help="Legacy alias for API key") set_api_key_parser.set_defaults( func=lambda args: cmd_set_api_key( argparse.Namespace(api_key=args.api_key or args.token) ) ) ``` ### Technical Analysis Three credential-disclosure channels are present: 1. `mask_api_key()` returns short API keys unchanged, causing `status` to display the entire credential when its length is 12 characters or fewer. 2. Checkout completion data is printed through `print_json(c ...[truncated 2040 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fast_claw_client.py:100
Finding

API Keys and User Prompts Can Be Sent to an Arbitrary or Plaintext Service Endpoint

Content
View full analysis
str: return os.getenv("FAST_CLAW_SERVICE_URL", DEFAULT_SERVICE_URL).rstrip("/") ``` ```python def request_json( method: str, path: str, payload: Optional[Dict[str, object]] = None, api_key: Optional[str] = None, ) -> Dict[str, object]: headers = {"Accept": "application/json"} data = None if payload is not None: data = json.dumps(payload).encode("utf-8") headers["Content-Type"] = "application/json" if api_key: headers["X-API-Key"] = api_key headers["Authorization"] = f"Bearer {api_key}" request = urllib.request.Request( f"{service_url()}{path}", data=data, headers=headers, method=method.upper(), ) ``` ### Technical Analysis `FAST_CLAW_SERVICE_URL` fully controls the destination of authenticated requests. The code does not validate the scheme, hostname, port, or relationship between the configured endpoint and the origin associated with the saved key. Consequently, a modified environment can redirect `status`, `topup`, `invoke`, `report`, and `wait-report` requests to an attacker-controlled server. Both `X-API-Key` and `Authorization` contain the same credential, although the API documentation identifies `X-API-Key` as the primary header and the bearer header only as a compatibility mechanism. Sending both unnecessarily increases secret exposure. The client also does not require HTTPS for non-loopback destinations. Although the default `http://localhost:8033` endpoint is appropriate for a local service, the same plaintext scheme can be selected for a remote host. In that situation, credentials, account data, and user prompts can be exposed to network interception or manipulation. The audit fo ...[truncated 1832 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/fast_claw_client.py (reported line 302)May include surrounding context.

python
t(f"Saved API key to {api_key_path()}")


def cmd_set_token(args: argparse.Namespace) -> None:
    write_local_api_key(args.token)
    print(f"Saved API key to {api_key_path()}")


def cmd_clear_token(_: argparse.Namespace) -> None:
    clear_local_api_key()
    print(f"Cleared API key file at {api_key_path()}")


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Fast Claw demo service client")
    subparsers = parser.add_subparsers(dest="command", required=True)

    status_parser = subparsers.add_parser("status", help="Inspect the saved API key and remote balance")
    status_parser.set_defaults(func=cmd_status)

    purchase_parser = subparsers.add_parser("purchase", help="Start a purchase for a new account API key")
    purchase_parser.add_argument("--account-name", required=True, help="Account name to create")
    purchase_parser.add_argument("--credits", type=int, default=10, help="Credits to buy")
    purchase_parser.add_argument("-

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documents capabilities that involve reading environment variables, writing a local API key file, and making network requests, but it declares no explicit tool scope or permissions boundary. In an agent setting, this weakens least-privilege guarantees and can allow broader-than-expected access when handling credentials and external service calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill instructs saving a persistent API key to a local file but does not clearly warn that the key is a secret or describe risks such as local compromise, accidental disclosure, backups, or permissive file permissions. Because the same key is then reused for authenticated service calls and account top-ups, exposure could let another party spend credits or access account-backed operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest explicitly states that the skill saves a local API key and calls a paid service, yet it provides no visible warning about persistent credential storage, billing implications, or the need for user consent. In this context, the absence of an explicit warning is security-relevant because the skill handles sensitive credentials and can trigger financial actions, making accidental or opaque use more dangerous.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The default prompt broadly instructs use of the paid API skill to obtain or reuse a locally stored API key and call the microservice, but it does not define clear trigger conditions, user-consent requirements, or operational boundaries. This ambiguity can cause the agent to invoke a paid service or use persisted credentials in situations the user did not explicitly authorize, increasing the risk of unintended spending and credential misuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The entire skill reference is written in Chinese and does not indicate that other languages are available or that Chinese is a justified locale requirement. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The client persistently stores the API key in a local JSON file under the user's home directory without setting restrictive file permissions or warning the user that credentials are being cached on disk. On multi-user systems, shared environments, backups, or when the path is redirected via environment variables, this can expose a reusable bearer credential to unauthorized parties.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The skill tells the user to open a browser-based purchase or top-up checkout flow, including optional external success-url redirection, without a prominent warning that this leaves the local agent context and may disclose information to an external payment flow. This creates phishing, redirection, and privacy risks, especially if service URL or success URL values are changed from trusted defaults.

Content

No source excerpt is available for this finding.