Back to skill

Security audit

Test Skill

Security checks for vulnerabilities and agentic risk

Overview

The tool appears intended to publish skills to ClawHub, but it ships a hardcoded bearer token and can upload unintended local files.

Review the directory before using this tool, because matching top-level files will be uploaded to ClawHub. Do not install or run it with the bundled token as-is; the publisher should revoke that token and require each user to authenticate with their own scoped credential.

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

Error
Location
publish.py:10
Finding
Hard-Coded ClawHub Bearer Token Exposes Publishing Privileges<![CDATA[ ## Vulnerability Details **File Location**: `publish.py`, lines 10, 17-20, and 67-72 **Vulnerability Type**: Hard-coded authentication credential **Risk Level**: High ### Vulnerable Code ```python TOKEN = "clh_GKYQNYsiccGeacf6up29a0XJdyFdyPOCzzLWaWukx3k" API_URL = "https://clawhub.ai/api/v1/skills" ``` The token is then used by both supported network operations: ```python resp = requests.post( "https://clawhub.ai/api/cli/upload-url", headers={"Authorization": f"Bearer {TOKEN}"}, json={"filename": filename, "contentType": content_type} ) ``` ```python resp = requests.post( API_URL, headers={"Authorization": f"Bearer {TOKEN}"}, data={"payload": json.dumps(payload)}, files=file_data ) ``` ### Technical Analysis A bearer token is embedded directly in distributed source code. Bearer credentials do not provide proof of possession beyond knowledge of the token, so any party that can download or inspect the Skill can extract and replay it. The token is supplied to endpoints that create upload URLs and publish Skill packages. This authentication is required for the declared publishing functionality, but embedding a shared credential in the package exceeds safe least-privilege design. Each user should authenticate with an independently managed credential rather than inheriting the package author's identity and permissions. This also conflicts with `filter_tag.json`, which states that the Skill does not include authentication or an API key. The token's current validity and exact server-side permissions were not tested during this static audit, but it must be treated as compromised. ### Attack Path 1. An attacker downloads or otherwise obtains the Skill package. 2. The attacker opens `publish.py` and extracts the bearer token from line 10. 3. The attacker sends requests containing `Authorization: Bearer <token>` to the ClawHub upload or publishing APIs. 4. If the token remains valid, the API processes requests using the token ...[truncated 749 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke the exposed token immediately and inspect its ClawHub activity for unauthorized use. 2. Generate a replacement credential with only the minimum permissions required to publish Skills. 3. Remove the token from source code and all repository history where feasible. 4. Obtain a user-specific token from a protected source, such as: - An environment variable; - An operating-system credential store; - A secret manager; - An interactive ClawHub authentication workflow. 5. Fail closed with a clear error when no credential is configured. 6. Avoid printing credentials or including them in exception messages and logs. 7. Add automated secret scanning to commits, CI workflows, and release packaging. 8. Rotate credentials regularly and support immediate revocation. 9. Correct the package metadata so it accurately declares its authentication and API-key requirements. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
publish.py:35
Finding
Extension-Based Bulk Upload Can Disclose Unintended Files<![CDATA[ ## Vulnerability Details **File Location**: `publish.py`, lines 35-39 and 62-72 **Vulnerability Type**: Insufficiently constrained local-file upload **Risk Level**: Medium ### Vulnerable Code ```python files = [] for f in os.listdir(skill_dir): if f.endswith(('.md', '.py', '.js', '.json', '.txt')) and not f.startswith('__'): filepath = os.path.join(skill_dir, f) if os.path.isfile(filepath): files.append((f, filepath)) ``` Every selected file is read in full and included in the outbound request: ```python file_data = [] for filename, filepath in files: with open(filepath, 'rb') as f: content = f.read() file_data.append(('files', (filename, content, 'text/plain'))) # Publish resp = requests.post( API_URL, headers={"Authorization": f"Bearer {TOKEN}"}, data={"payload": json.dumps(payload)}, files=file_data ) ``` ### Technical Analysis Uploading local Skill files to ClawHub is necessary for the declared publishing functionality. The transfer is therefore not covert or unrelated network exfiltration. However, the implementation selects every top-level file whose name has one of several broad extensions, including `.json`, `.txt`, and source-code extensions. There is no explicit publication manifest, denylist, ignore-file processing, secret scan, size restriction, file preview, or confirmation step. A configuration file, development note, source file containing credentials, or other sensitive file with an accepted extension can consequently be uploaded without the user noticing that it was selected. In addition, `os.path.isfile()` follows symbolic links. A top-level symbolic link with an accepted filename can pass the check and cause `open()` to read its target, including a target located outside the selected Skill directory. This does not permit an external attacker to select arbitrary files by itself; exploitation requires the attacker or another process to place a suitable file or sym ...[truncated 1484 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace extension-based discovery with an explicit publication manifest listing each intended file. 2. Display the complete file list and destination before transmission, and require confirmation for interactive use. 3. Provide a deliberate non-interactive flag for automation rather than silently bypassing review. 4. Reject symbolic links by checking `os.path.islink()` or by opening files with platform-appropriate no-follow protections. 5. Resolve each path with `os.path.realpath()` and verify that it remains inside the resolved Skill directory. 6. Support ignore rules for secrets, local configuration, test data, and development artifacts. 7. Scan candidate files for common credential and private-key patterns before upload, blocking or warning on matches. 8. Enforce per-file and aggregate size limits to reduce accidental uploads and memory exhaustion. 9. Assign accurate MIME types instead of labeling every file as `text/plain`. 10. Add request timeouts, `raise_for_status()` handling, and clear reporting of partial or failed uploads. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill instructs users to publish a local skill directory to ClawHub but does not warn that local skill contents will be transmitted to an external service. This can lead users to unintentionally upload sensitive code, configuration, secrets, or proprietary material from the specified path, especially because the examples encourage publishing a whole local directory.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
A hardcoded bearer token is embedded directly in the source and then used for authenticated publication requests. Anyone with access to this file can reuse the credential to publish, modify, or abuse the associated account, and the token is difficult to rotate once copied or committed.

External Transmission

Medium
Category
Data Exfiltration
Content
def upload_file(filename, content_type="text/plain"):
    """获取上传URL并上传文件"""
    resp = requests.post(
        "https://clawhub.ai/api/cli/upload-url",
        headers={"Authorization": f"Bearer {TOKEN}"},
        json={"filename": filename, "contentType": content_type}
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
def upload_file(filename, content_type="text/plain"):
    """获取上传URL并上传文件"""
    resp = requests.post(
        "https://clawhub.ai/api/cli/upload-url",
        headers={"Authorization": f"Bearer {TOKEN}"},
        json={"filename": filename, "contentType": content_type}
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Tainted flow: 'upload_url' from requests.post (line 23, network input) → requests.put (network output)

Medium
Category
Data Flow
Content
if upload_url:
        # 上传文件内容
        requests.put(upload_url, data=content, headers={"Content-Type": content_type})
    
    return True
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script automatically reads local files from the provided directory and uploads them to a remote service without any explicit runtime warning, confirmation, or detailed disclosure of what will be transmitted. This increases the risk of accidental exfiltration of sensitive files, especially when users run the tool on the wrong directory or do not realize publication includes all matching files.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The natural-language documentation is entirely in Chinese, with no indication that this locale is optional or intentionally restricted to a specific audience. Per the policy, forcing a specific language without user opt-in or documented justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The natural-language fields on these lines are written only in Chinese, which suggests a fixed language choice in the skill metadata/output without any visible user opt-in or stated locale-specific constraint. The policy requires avoiding forced language or locale behavior unless choice or justification is provided.

Natural-Language Policy Violations

Low
Confidence
74% confidence
Finding
The top-level natural-language description is written only in Chinese and gives no indication that language is configurable or user-selected. This may violate language-choice policy when the skill is used in broader contexts without explicit locale opt-in.

Static analysis

No suspicious patterns detected.