Back to skill

Security audit

Ontopo Hotfix

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a legitimate restaurant-search helper that sends user-directed queries to Ontopo and does not place reservations or persist on the system.

Before installing, understand that your restaurant searches and booking criteria are sent to Ontopo's external service, and that the installer resolves the current httpx package version. Use it for manual booking-link generation only; it does not complete reservations for you.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (1)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:7
Finding
Unpinned Third-Party Dependency Creates a Mutable Supply-Chain Risk## Vulnerability Details **File Location**: `SKILL.md`, line 7 **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Medium **Vulnerable Code**: ```yaml metadata: {"openclaw": {"emoji": "🍽️", "os": ["darwin", "linux"], "requires": {"bins": ["python3"]}, "install": [{"kind": "uv", "package": "httpx", "label": "Install httpx via pip/uv"}]}} ``` ### Technical Analysis The Skill installation metadata requests the `httpx` package without specifying an exact audited version, a lockfile, or an integrity hash. Consequently, the package resolver may install a different version—and potentially different transitive dependencies—each time the Skill is installed. The script imports this dependency at `scripts/ontopo-cli.py:18-22`. No evidence indicates that the current `httpx` package is malicious. The risk arises because the dependency set is mutable after the Skill has been reviewed. If the package, a transitive dependency, its publisher account, or the relevant package distribution infrastructure were compromised, attacker-controlled code could enter the runtime without any change to this repository. ### Attack Path 1. An attacker compromises a future `httpx` release, one of its transitive dependencies, a publisher account, or the package distribution path. 2. The Skill installer resolves the unversioned package declaration to the compromised release. 3. The compromised package is installed with the privileges of the user or automation running the Skill installation. 4. The Skill imports `httpx` when `scripts/ontopo-cli.py` starts. 5. Malicious import-time or runtime code executes in the Skill process and can act with that process's permissions. ### Impact Assessment Successful exploitation could provide arbitrary code execution under the account that installs or runs the Skill. The resulting access would be limited by that account's operating-system and sandbox permissions, but could include reading or modi ...[truncated 408 chars]
Remediation
## Remediation Suggestions 1. Pin `httpx` to an exact version that has been reviewed, for example: ```yaml "package": "httpx==<audited-version>" ``` 2. Use a lockfile that records the complete transitive dependency graph. 3. Require cryptographic hashes during installation, such as pip's `--require-hashes` workflow. 4. Generate dependency artifacts from a trusted registry and avoid untrusted mirrors or additional package indexes. 5. Run automated vulnerability and provenance checks against all direct and transitive dependencies. 6. Review and deliberately update the pinned version rather than allowing installation-time resolution to select arbitrary future releases. 7. Install and run the Skill with least privilege in an isolated environment that does not expose unrelated credentials or sensitive files.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill clearly performs live API queries to Ontopo-backed endpoints and therefore has network capability, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization and review gap: users and platforms cannot easily determine or constrain what external access the skill may perform, increasing the risk of unexpected outbound requests or future abuse if the implementation changes.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
if self.token:
            return

        response = await self._request("POST", "/loginAnonymously", auth_required=False)
        self.token = response.get("jwt_token")
        if not self.token:
            raise RuntimeError("Failed to obtain authentication token")
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
if self.token:
            return

        response = await self._request("POST", "/loginAnonymously", auth_required=False)
        self.token = response.get("jwt_token")
        if not self.token:
            raise RuntimeError("Failed to obtain authentication token")
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
if self.token:
            return

        response = await self._request("POST", "/loginAnonymously", auth_required=False)
        self.token = response.get("jwt_token")
        if not self.token:
            raise RuntimeError("Failed to obtain authentication token")
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
if self.token:
            return

        response = await self._request("POST", "/loginAnonymously", auth_required=False)
        self.token = response.get("jwt_token")
        if not self.token:
            raise RuntimeError("Failed to obtain authentication token")
Confidence
80% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Missing User Warnings

Low
Confidence
87% confidence
Finding
This code logs in anonymously and sends user-supplied venue queries, dates, times, party sizes, and locale to the remote Ontopo API, but the script contains no explicit warning or disclosure that those inputs are transmitted to a third-party service. While network access is core to the tool's purpose, the absence of any visible notice about external data transmission is still a user-awareness gap for a CLI handling booking-related queries.

Static analysis

No suspicious patterns detected.