Back to skill

Security audit

API Endpoint Tester

Security checks for vulnerabilities and agentic risk

Overview

This is a real API testing skill, but it gives broad outbound request and file-write capability with weak scoping and safety guidance.

Review this before installing. Use it only with URLs you control or are authorized to test, avoid private/internal/metadata endpoints, do not paste live tokens or sensitive data into command-line headers or bodies, and avoid the output-file option until path containment and overwrite behavior are fixed. Pin the requests dependency for reproducible installs.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/main.py:48
Finding
Unrestricted Access to Internal, Private, and Cloud Metadata Endpoints<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:48-58`, `scripts/main.py:124-131` **Vulnerability Type**: Server-Side Request Forgery and unrestricted network access **Risk Level**: High ### Vulnerable Code ```python response = requests.request( method=method, url=url, headers=request_headers, json=json_data, data=data, timeout=timeout, verify=verify_ssl, allow_redirects=allow_redirects ) ``` ```python # Validate URL format if not args.url.startswith(("http://", "https://")): return { "status": "error", "error_message": "URL must start with http:// or https://" } ``` ### Technical Analysis The URL validation only checks whether the supplied string begins with `http://` or `https://`. It does not restrict the destination hostname or resolved IP address. Consequently, the requester can target: - Loopback addresses such as `127.0.0.1` and `::1` - Private network ranges - Link-local services - Cloud metadata endpoints such as `169.254.169.254` - Internal hostnames resolved by the host's DNS infrastructure - Public URLs that redirect to internal destinations Redirect following is enabled by default, and no validation is performed for redirect targets. The tool also accepts attacker-controlled HTTP methods, headers, and bodies, allowing both read and state-changing requests against reachable internal services. Although arbitrary API testing is part of the declared functionality, unrestricted access to infrastructure-only destinations violates least-privilege principles when invocation arguments can be influenced by untrusted content. ### Attack Path 1. An attacker influences the URL and related arguments passed to the Skill. 2. The attacker supplies a loopback, private-network, link-local, or cloud metadata URL. Alternatively, the attacker provides a public URL that redirects to an internal service. 3. The process sends the request from the Agent host's network context. 4. The ...[truncated 980 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse URLs with a standards-compliant URL parser rather than relying on a string-prefix check. 2. Resolve the destination hostname before sending the request. 3. Reject loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 addresses by default. 4. Explicitly block cloud metadata endpoints and relevant metadata hostnames. 5. Re-resolve and revalidate every redirect destination before following it. 6. Protect against DNS rebinding by ensuring the connection is made only to an address that was validated. 7. Prefer an explicit hostname or network allowlist for normal operation. 8. If private-network testing is required, place it behind a clearly documented, explicit opt-in and display a security warning. 9. Consider restricting state-changing methods when targeting destinations outside a configured allowlist. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.py:138
Finding
Output Path Validation Bypass Allows Files Outside the Skill Directory to Be Overwritten<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:138-146`, `scripts/main.py:172-175` **Vulnerability Type**: Path validation bypass and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```python # Validate output file path is within skill directory if args.output_file: try: skill_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) output_path = os.path.abspath(args.output_file) if not output_path.startswith(skill_dir): return { "status": "error", "error_message": f"Output file must be within skill directory: {skill_dir}" } except Exception as e: return { "status": "error", "error_message": f"Invalid output file path: {str(e)}" } ``` ```python # Output to file if requested if args.output_file and result.get("status") == "success": try: with open(args.output_file, "w") as f: json.dump(result, f, indent=2) except Exception as e: result["status"] = "error" result["error_message"] = f"Failed to write output file: {str(e)}" ``` ### Technical Analysis The containment check uses a string-prefix comparison: ```python output_path.startswith(skill_dir) ``` A string prefix does not establish that one path is a descendant of another. For example, if the Skill directory is `/tmp/artifact`, a path such as `/tmp/artifact-evil/result.json` begins with the same text and passes validation despite being outside the directory. The code also validates `output_path` but later opens the original `args.output_file` value. In addition, resolving a lexical absolute path does not prevent a symlink inside the allowed directory from referring to an external target. The file is opened using mode `"w"`, which creates a missing file or truncates an existing file. Therefore, successful exploitation can overwrite any file writable by the process. ### Attack Path ...[truncated 1268 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve both the Skill directory and requested output path using `pathlib.Path.resolve()`. 2. Enforce actual path containment using `Path.is_relative_to()` or a correctly applied `os.path.commonpath()` comparison. 3. Write only to the exact resolved path that was validated; do not reopen the original unvalidated argument. 4. Reject symlink targets where symlink-based output is unnecessary. 5. Use safe file-opening primitives that prevent symlink traversal where supported. 6. Consider exclusive creation mode to prevent unintended overwrites. 7. Require explicit overwrite confirmation if replacing an existing file is legitimate functionality. 8. Restrict output to a dedicated directory created with appropriately narrow permissions. Example containment logic: ```python from pathlib import Path skill_dir = Path(__file__).resolve().parent.parent output_path = Path(args.output_file).resolve() if not output_path.is_relative_to(skill_dir): return { "status": "error", "error_message": f"Output file must be within skill directory: {skill_dir}" } with output_path.open("x", encoding="utf-8") as f: json.dump(result, f, indent=2) ``` If overwriting is required, it should be separately authorized rather than changing `"x"` to `"w"` unconditionally. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:7
Finding
Unpinned Third-Party Dependency Creates Supply-Chain Exposure<![CDATA[ ## Vulnerability Details **File Location**: `README.md:7-11`, `SKILL.md:7-11` **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Configuration `README.md`: ```bash pip install requests ``` `SKILL.md`: ```yaml metadata: openclaw: requires: bins: - python3 packages: - requests ``` ### Technical Analysis The project instructs users or the Skill runtime to install `requests` without an exact version or integrity hash. No dependency lock file or hash-pinned requirements file is present in the reviewed project. As a result, installation is not reproducible and resolves whichever compatible package release is available from the configured package index at installation time. Changes in upstream releases, a compromised package distribution channel, or unsafe package-index configuration could introduce unreviewed code into the Skill environment. This finding is a supply-chain weakness. The reviewed files do not establish that the current `requests` package is malicious. ### Attack Path 1. A user or automated environment follows the documented installation command or processes the Skill dependency declaration. 2. The package installer queries its configured package index without requiring a specific audited artifact. 3. A changed, compromised, or otherwise unsafe release is selected. 4. The dependency is installed into the Skill environment. 5. Dependency code executes when imported or used by `scripts/main.py`. ### Impact Assessment A compromised dependency could execute with the same privileges as the Skill process. Depending on the environment, this could expose accessible files, environment variables, network resources, and data processed by the Skill. The practical likelihood depends on the security of the configured package index and upstream distribution. The issue does not itself prove malicious package installation, but it removes version and integrity controls ...[truncated 58 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `requests` to a reviewed version. 2. Store dependencies in a committed requirements or lock file. 3. Require cryptographic hashes during installation. 4. Use a trusted, explicitly configured package index. 5. Update dependency pins through a reviewed maintenance process. 6. Run vulnerability scanning against the resolved dependency set. A hardened installation pattern is: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` The requirements file should contain an exact version and hashes for the approved distribution artifacts, for example: ```text requests==<reviewed-version> \ --hash=sha256:<approved-artifact-hash> ``` The actual version and hashes should be selected from reviewed artifacts rather than copied from an unverified source. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (16)

Ae1

High
Category
analysis-evasion
Content
python3 scripts/main.py run --url "https://api.example.com/users" --method GET
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/main.py run --url "https://api.example.com/users" --method GET
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/main.py run --url "https://api.example.com/users" --method GET
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/main.py run --url "https://api.example.com/users" --method GET
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/main.py run --url "https://api.example.com/users" --method GET
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

External Transmission

Medium
Category
Data Exfiltration
Content
python3 scripts/main.py run --url "https://jsonplaceholder.typicode.com/posts" --method POST --body '{"title": "test", "body": "content"}'

# With custom headers
python3 scripts/main.py run --url "https://api.example.com/data" --method GET --headers '{"Authorization": "Bearer token123", "User-Agent": "MyApp"}'
```

## Command Reference
Confidence
50% 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
python3 scripts/main.py run --url "https://jsonplaceholder.typicode.com/posts" --method POST --body '{"title": "test", "body": "content"}'

# With custom headers
python3 scripts/main.py run --url "https://api.example.com/data" --method GET --headers '{"Authorization": "Bearer token123", "User-Agent": "MyApp"}'
```

## Command Reference
Confidence
50% 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
python3 scripts/main.py run --url "https://jsonplaceholder.typicode.com/posts" --method POST --body '{"title": "test", "body": "content"}'

# With custom headers
python3 scripts/main.py run --url "https://api.example.com/data" --method GET --headers '{"Authorization": "Bearer token123", "User-Agent": "MyApp"}'
```

## Command Reference
Confidence
50% 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
python3 scripts/main.py run --url "https://jsonplaceholder.typicode.com/posts" --method POST --body '{"title": "test", "body": "content"}'

# With custom headers
python3 scripts/main.py run --url "https://api.example.com/data" --method GET --headers '{"Authorization": "Bearer token123", "User-Agent": "MyApp"}'
```

## Command Reference
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README encourages sending headers and bodies to arbitrary endpoints but does not warn users against transmitting secrets, production credentials, or sensitive payloads during testing. In a tool specifically designed to make outbound HTTP requests, this omission can lead to accidental disclosure of API keys, tokens, or personal data to third-party or misconfigured endpoints.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation includes a DELETE example against a user resource without any warning that the action may be irreversible or harmful in real environments. For a generic API testing tool, such examples can normalize running destructive operations against live systems and increase the risk of accidental data deletion.

Ssd 3

Medium
Confidence
95% confidence
Finding
The DELETE example uses a JWT-like bearer token in plaintext, which more strongly resembles real credential material and can encourage copying, reuse, or normalization of exposing tokens in docs, terminals, and logs. Because it appears in a destructive request example, the combination raises the chance of misuse against real systems.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill is documented as sending arbitrary HTTP requests and static analysis detected network and file-write capable behavior, but the manifest does not declare any explicit tool scope or permissions boundary. This creates ambiguity about what the skill is allowed to do and weakens review and runtime guardrails, increasing the chance of unintended outbound requests or local artifact writes without clear user awareness.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill description explains how to send requests, headers, and bodies to external endpoints but does not warn users that sensitive data such as API tokens, personal data, or internal URLs may be transmitted off-system. In a tool specifically designed for arbitrary endpoint testing, omission of that warning materially raises the risk of accidental credential or data disclosure.

External Transmission

Medium
Category
Data Exfiltration
Content
python3 scripts/main.py run --url "https://api.example.com/users" --method POST --body '{"name": "John", "email": "john@example.com"}'

With custom headers:
python3 scripts/main.py run --url "https://api.example.com/users" --method GET --headers '{"Authorization": "Bearer token123"}'

## Examples
Confidence
93% confidence
Finding
This example explicitly demonstrates sending an Authorization bearer token to an external endpoint without any warning about credential exposure. In the context of a skill that facilitates arbitrary outbound requests, showing secret-bearing headers in documentation can normalize unsafe usage and lead users to transmit real tokens to untrusted or mistyped destinations.

Ssd 3

Low
Confidence
84% confidence
Finding
The example shows an Authorization header with a bearer token value, which encourages users to paste credential material directly into shell history, logs, and command output. Even though the token is illustrative, this pattern promotes insecure handling of secrets in a tool that transmits headers over the network.

Static analysis

No suspicious patterns detected.