Back to skill

Security audit

Neckr0ik Api Wrapper

Security checks for vulnerabilities and agentic risk

Overview

The skill has a legitimate API-wrapper purpose, but its generator handles untrusted API specs with too little containment, creating risks around file writes, generated code, prompt injection, network access, and credentials.

Use this only with trusted OpenAPI specs, preferably local files or known public HTTPS hosts. Always provide a safe --name and controlled --output directory, review generated SKILL.md and scripts/api.py before installing or running them, and use sandbox or read-only API credentials rather than production tokens.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/generator.py:259
Finding

Remote OpenAPI Fields Can Inject Executable Python into Generated Clients

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
scripts/generator.py:196
Finding

Remote OpenAPI Description Can Inject Instructions into Generated SKILL.md

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/generator.py:164
Finding

Specification-Controlled Skill Name Permits Output Path Traversal

Content
View full analysis
Path: """Generate OpenClaw skill from API spec.""" skill_name = name or spec.title skill_dir = self.output_dir / skill_name skill_dir.mkdir(parents=True, exist_ok=True) # Generate SKILL.md skill_md = self._generate_skill_md(spec, skill_name) (skill_dir / "SKILL.md").write_text(skill_md) # Generate claw.json claw_json = self._generate_claw_json(spec, skill_name) (skill_dir / "claw.json").write_text(claw_json) # Generate API client api_script = self._generate_api_client(spec, skill_name) scripts_dir = skill_dir / "scripts" scripts_dir.mkdir(exist_ok=True) (scripts_dir / "api.py").write_text(api_script) ``` The default name originates from the OpenAPI title: ```python title=info.get('title', 'API').replace(' ', '-').lower(), ``` ### Technical Analysis When `--name` is omitted, `skill_name` is controlled by `info.title` in the OpenAPI document. Only spaces are replaced during title processing. Directory separators, absolute paths, and `..` traversal components remain valid. `self.output_dir / skill_name` is used without canonicalization or a containment check. The generator then creates directories and writes predictable files with `write_text()`, which overwrites existing files. Although the filenames are fixed, an attacker can control their parent directory and cause `SKILL.md`, `claw.json`, and `scripts/api.py` to be written outside the selected output directory. ### Attack Path 1. An attacker creates an OpenAPI document whose title contains path traversal components or an absolute path. 2. A victim invokes `generate` without explicitly supplying a safe `--name`. 3. The title becomes `skill_name`. 4. The destination path ...[truncated 605 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/generator.py:112
Finding

Unrestricted OpenAPI URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
APISpec: """Parse OpenAPI specification from URL or file.""" # Load spec if spec_url.startswith(('http://', 'https://')): content = self._fetch_url(spec_url) else: content = Path(spec_url).read_text() ``` ```python def _fetch_url(self, url: str) -> str: """Fetch content from URL.""" try: req = urllib.request.Request( url, headers={'Accept': 'application/json, application/yaml'} ) response = urllib.request.urlopen(req, timeout=30) return response.read().decode('utf-8') except urllib.error.HTTPError as e: raise Exception(f"Failed to fetch {url}: {e.code}") ``` ### Technical Analysis The generator accepts arbitrary HTTP and HTTPS URLs and performs requests from the local execution environment. It does not restrict hosts, resolve and reject private addresses, prevent access to loopback or link-local networks, or validate redirect destinations. Consequently, a caller can make the generator contact services that are not reachable from the caller's own network position, including local development services, internal administrative endpoints, and cloud instance metadata services. The returned content must parse as JSON or YAML and resemble an OpenAPI document for generation to continue, but the outbound request occurs before that validation. Redirects can also move an initially public URL to a prohibited internal address. ### Attack Path 1. An attacker supplies a URL targeting a loopback, private, link-local, or cloud metadata address, or supplies a public URL that redirects to one. 2. The victim or agent runs the `generate` or `validate` command with that URL. 3. `urllib.request.urlopen()` p ...[truncated 874 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generator.py:318
Finding

Generated Clients Can Send Environment Credentials to Arbitrary or Redirected Origins

Content
View full analysis
Dict: """Make HTTP request to API.""" url = self.base_url + path # Add query parameters if params: query = '&'.join( f'{k}={v}' for k, v in params.items() if v is not None ) if query: url += '?' + query headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', } # Add authentication if self.api_key: {self._generate_auth_code(spec)} req_data = json.dumps(data).encode() if data else None req = urllib.request.Request( url, data=req_data, headers=headers, method=method ) try: response = urllib.request.urlopen(req, timeout=self.timeout) ``` Authentication is inserted into a header or query parameter: ```python if location == 'header': return f" headers['{name}'] = self.api_key" else: # query return " params['api_key'] = self.api_key" ``` ```python elif spec.auth_type == "bearer": return " headers['Authorization'] = f'Bearer {self.api_key}'" elif spec.auth_type == "basic": return " headers['Authorization'] = f'Basic {self.api_key}'" ``` The destination can be overridden: ```python parser.add_argument( '--base-url', default="{spec.base_url}", help='API base URL' ) parser.add_argument('--api-key', help='API key') args, ...[truncated 2091 chars]
Remediation
View remediation
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 (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises behaviors that imply network access, reading local files, writing generated files, and likely reading environment-based credentials, but it does not declare any tool scope or permission boundaries. This is dangerous because users and hosting platforms cannot clearly see or constrain what the skill may access, increasing the risk of over-privileged execution and unintended data exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill encourages generating files and testing against live APIs, but it does not warn users that these actions can write to disk, send requests to external systems, consume API quotas, or modify real remote data. In context, this wrapper is specifically designed to interact with arbitrary third-party APIs, which makes the omission more dangerous because generated clients and test operations may perform state-changing actions unexpectedly.

Content

No source excerpt is available for this finding.

External Transmission

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

md
API Wrapper Generator - Generate OpenClaw skills from REST APIs

Usage:
    python generator.py generate --spec https://api.example.com/openapi.json --name my-api
    python generator.py validate --spec ./openapi.yaml
    python generator.py test --skill ./my-api --endpoint <operationId>
"""

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · scripts/generator.py (reported line 6)May include surrounding context.

python
API Wrapper Generator - Generate OpenClaw skills from REST APIs

Usage:
    python generator.py generate --spec https://api.example.com/openapi.json --name my-api
    python generator.py validate --spec ./openapi.yaml
    python generator.py test --skill ./my-api --endpoint <operationId>
"""

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

When --spec is an HTTP(S) URL, the script automatically performs a network request to retrieve the specification. The docstring shows URL usage, but it does not warn that execution will contact external servers and transmit request metadata, so the network behavior lacks clear disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The generator creates directories and writes SKILL.md, claw.json, scripts/api.py, and references/endpoints.md, but provides no prior disclosure that running generation will modify the filesystem. Although the script prints output paths afterward, there is no confirmation prompt or pre-action warning in the code comments/docstrings for this safety-relevant behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.