Back to skill

Security audit

PostHog Query

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent PostHog query purpose, but its shell command template can turn crafted query text into local command execution if used with untrusted input.

Review before installing. Use a pinned or locally managed posthog-cli where possible, authenticate with the minimum query:read scope, and do not run generated SQL through a shell with untrusted user-provided values. Prefer passing SQL as a literal argument through a shell-free process API, file, or stdin.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:4
Finding
Unpinned Global npm Dependency Installation## Vulnerability Details **File Location**: `SKILL.md`, line 4 **Vulnerability Type**: Unpinned third-party dependency installed globally **Risk Level**: Medium ### Vulnerable Code ```yaml metadata: {"openclaw": {"emoji": "🦔", "requires": {"bins": ["posthog-cli"]}, "install": "npm install -g posthog-cli"}} ``` ### Technical Analysis The Skill instructs users to install the latest available version of `posthog-cli` globally from npm. It does not specify a reviewed version, lockfile, integrity hash, or verified package source. Consequently, the package content executed by users may change after the Skill has been audited. npm installation can execute package lifecycle scripts with the privileges of the user performing the installation. Global installation also modifies the user's shared tool environment rather than isolating the dependency to this Skill. This creates a supply-chain exposure if the package, its maintainer account, or a transitive dependency is compromised. This finding does not establish that `posthog-cli` is malicious. The risk arises from installing mutable, unpinned third-party code without integrity controls. ### Attack Path 1. An attacker compromises the npm package, a maintainer account, or a transitive dependency. 2. The attacker publishes a malicious version under the expected package name. 3. A user installs the Skill dependency using `npm install -g posthog-cli`. 4. npm retrieves the compromised latest version and may execute its lifecycle scripts. 5. Malicious code runs with the installing user's privileges and can modify files or access data available to that user. ### Impact Assessment Successful exploitation could execute arbitrary code with the privileges of the user running npm. The attacker could access that user's files and environment, including credentials readable by the user, and could alter globally installed tooling. The instruction does not request elevated operating-system p ...[truncated 127 chars]
Remediation
## Remediation Suggestions - Pin `posthog-cli` to a specifically reviewed version, for example `posthog-cli@X.Y.Z`. - Verify and document the official npm package name, publisher, and expected registry. - Prefer a project-local, lockfile-controlled installation over global installation. - Use npm integrity and provenance verification where supported. - Review package lifecycle scripts and transitive dependencies before approving upgrades. - Establish an explicit dependency-update process so new versions are reviewed before use.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:19
Finding
Shell Command Injection Through Double-Quoted SQL Arguments## Vulnerability Details **File Location**: `SKILL.md`, lines 19–21; affected examples also appear at lines 40, 45, 50, and 55 **Vulnerability Type**: Shell command injection **Risk Level**: High ### Vulnerable Code ```bash posthog-cli exp query run "<SQL>" ``` The same construction is demonstrated in the supplied examples: ```bash posthog-cli exp query run "SELECT count() as pageviews FROM events WHERE event = '\$pageview'" ``` ```bash posthog-cli exp query run "SELECT count() as pageviews FROM events WHERE event = '\$pageview' AND properties['\$current_url'] LIKE 'https://example.com/%'" ``` ```bash posthog-cli exp query run "SELECT toDate(timestamp) as date, count() as pageviews FROM events WHERE event = '\$pageview' AND timestamp >= now() - INTERVAL 7 DAY GROUP BY date ORDER BY date" ``` ```bash posthog-cli exp query run "SELECT event, timestamp FROM events ORDER BY timestamp DESC LIMIT 10" ``` ### Technical Analysis The documented invocation embeds SQL directly inside a shell double-quoted argument. Double quotes prevent ordinary word splitting but do not disable command substitution. Shell expressions such as `$(command)` and backtick command substitutions are evaluated before `posthog-cli` is launched. If an agent incorporates attacker-controlled query text, URL filters, event names, property values, or other input into this template without shell-safe encoding, that input can terminate the intended data context or introduce command substitution. Escaping `$` only in the fixed `$pageview` examples does not provide general protection for dynamically generated SQL. For example, SQL text containing `$(id)` inside the double-quoted argument would cause the shell to execute `id` locally and replace the expression with its output before passing the resulting SQL to the PostHog CLI. More harmful commands could be substituted in the same way. ### Attack Path 1. An attacker supplies or influ ...[truncated 1179 chars]
Remediation
## Remediation Suggestions - Invoke `posthog-cli` through a process API that accepts an argument array and does not invoke a shell. - Pass the SQL as one literal argument, such as the conceptual argument vector `["posthog-cli", "exp", "query", "run", sql]`. - If the CLI supports query input through a file or standard input, use that interface instead of embedding SQL in a shell command. - Do not concatenate untrusted values into a shell command. - If shell execution is unavoidable, apply complete shell-safe quoting to the entire generated SQL argument rather than escaping selected characters such as `$`. - Validate dynamic identifiers and use strict allowlists where feasible. Treat validation as defense in depth rather than a replacement for shell-free execution. - Update the examples and guidance to warn explicitly that user-controlled SQL must not be interpolated into a shell command.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

Credential Access

High
Category
Privilege Escalation
Content
## One-Time Setup

```bash
posthog-cli login  # authenticate interactively; stores token in ~/.posthog/credentials.json
```

Requires API key scope: `query:read`.
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## One-Time Setup

```bash
posthog-cli login  # authenticate interactively; stores token in ~/.posthog/credentials.json
```

Requires API key scope: `query:read`.
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.