Back to skill

Security audit

QG Car

Security checks for vulnerabilities and agentic risk

Overview

The bus schedule and link-generation behavior is coherent, but the installer uses mutable remote code and global installation steps that should be reviewed before use.

Install only if you trust the publisher and are comfortable with a remote installer, global npm command installation, and replacement of Codex/OpenClaw skill directories. Safer installation would use an audited, pinned release with checksum verification and an explicit user-selected destination.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
install.sh:4
Finding

Documented installer executes a remote script and subsequently retrieves mutable source code

Content
View full analysis
/dev/null 2>&1; then git clone --depth 1 "$REPO_URL" "$repo_dir" else need_command curl need_command tar mkdir -p "$repo_dir" curl -fsSL "$TARBALL_URL" | tar -xz -C "$tmp_dir" ``` `install.sh:81-91`: ```bash if npm view "$PACKAGE_NAME" version --registry=https://registry.npmjs.org >/dev/null 2>&1; then if npm install -g "$PACKAGE_NAME"; then echo "Installed qg CLI from npm package: $PACKAGE_NAME" else echo "npm package install failed; falling back to source install." install_from_source fi else echo "npm package is not available yet; falling back to source install." install_from_source fi ``` ### Technical Analysis The documented one-line installation command pipes network content directly into Bash. Although the initial `raw.githubusercontent.com` URL is pinned to a commit, the downloaded installer does not continue using that pinned revision. It clones the repository’s mutable default branch or downloads `main.tar.gz`. No commit verification, checksum validation, or cryptographic signature verification occurs before the retrieved project is built and installed. Consequently, the effective code executed and installed can differ from the code represented by the pinned installer revision and from the code reviewed during this audit. The installer also supports `QG_SKILL_REPO_URL` and `QG_SKIL ...[truncated 1822 chars]
Remediation
View remediation
" ``` 5. Reject arbitrary source URL overrides by default. If mirrors are required, validate them against an allowlist and still require the expected content hash. 6. Download archives to a file first, verify the expected hash, inspect archive paths, and only then extract them. 7. Avoid global installation and automatic installation into both agent platforms. Let the user select a destination and use a project-local or user-scoped installation. 8. Clearly document all filesystem modifications, network destinations, lifecycle scripts, and code-execution steps before requesting user approval. ]]>

T08 · Insecure Dependencies

Error
Location
install.sh:81
Finding

Installer globally installs an unpinned npm package with lifecycle-script execution

Content
View full analysis
/dev/null 2>&1; then if npm install -g "$PACKAGE_NAME"; then echo "Installed qg CLI from npm package: $PACKAGE_NAME" ``` `README.md:42-43`: ```bash npm install -g qg-skill ``` ### Technical Analysis The installer installs the package by name without an exact version or integrity constraint. It therefore resolves whichever version is tagged as current at installation time rather than the audited `0.1.0` source. The project lockfile pins development dependencies used when building this repository, but it does not authenticate or pin the top-level package selected by `npm install -g "$PACKAGE_NAME"`. npm may also execute lifecycle scripts supplied by the resolved package during installation. The `QG_SKILL_PACKAGE` environment variable permits the package specification itself to be replaced. If the execution environment is influenced by an attacker, this can redirect installation to another registry package, local path, Git URL, or other npm-supported package specification. Global installation is broader than necessary for the declared functionality and places the resulting `qg` and `qg-list` commands in the user’s global npm binary location. ### Attack Path 1. A user runs the documented installer or the documented global npm command. 2. npm resolves the mutable current release of `qg-skill`, or an attacker-controlled specification supplied through `QG_SKILL_PACKAGE`. 3. A compromised maintainer account, malicious future release, registry compromise, or influenced environment causes npm to retrieve attacker-controlled package content. 4. npm executes applicable insta ...[truncated 863 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (21)

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The | bash construct is a classic dangerous command chain because it turns remote content retrieval into immediate shell execution. In a skill/CLI installation context, this is more dangerous because users may copy-paste it verbatim, leading to arbitrary code execution if the script, hosting account, or downstream installation sources are compromised.

Content

Scanner excerpt · README.md (reported line 35)May include surrounding context.

安装 CLI,并把 Skill 同时安装到 ~/.codex/skills/qgcar-skill 和 ~/.openclaw/skills/qgcar-skill:

bash
curl -fsSL https://raw.githubusercontent.com/qybaihe/qg-skill/26ed8e31342968836b672d0ea7ab2a275361779c/install.sh | bash

脚本会优先从 npm 安装 qg-skill;如果 npm 包还没发布,会自动 fallback 到 GitHub 源码构建安装。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Yes, this is a mismatch. The description promises a concrete helper for campus bus ticket workflows, but the provided code chunk is just an empty JavaScript module with no operational logic. It neither performs the declared actions nor any meaningful supporting behavior. This is a materially different primary purpose: the declared skill is a ticket-link preparation tool, while the actual code does nothing.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description is for a user-facing bus-ticket assistance skill centered on using the qg CLI to list schedules and prepare booking links. The supplied code chunk instead only installs the qg CLI and skill assets from external sources (GitHub/npm) onto the local machine. That is a materially different primary purpose from the declared runtime functionality. While installation may support the skill, this code chunk itself does not perform the described ticket-related tasks and introduces undeclared capabilities involving network retrieval, package installation, and filesystem modification in Codex/OpenClaw skill directories.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · install.sh (reported line 54)May include surrounding context.

sh
rsync -a --exclude ".git" --exclude "node_modules" "$repo_dir/" "$target_dir/"
  else
    cp -R "$repo_dir/." "$target_dir/"
    rm -rf "$target_dir/.git" "$target_dir/node_modules"
  fi
}

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
85% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · README.md (reported line 56)May include surrounding context.

只安装 Skill

bash
mkdir -p ~/.codex/skills
git clone https://github.com/qybaihe/qg-skill ~/.codex/skills/qgcar-skill

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 56)May include surrounding context.

只安装 Skill

bash
mkdir -p ~/.codex/skills
git clone https://github.com/qybaihe/qg-skill ~/.codex/skills/qgcar-skill

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 56)May include surrounding context.

只安装 Skill

bash
mkdir -p ~/.codex/skills
git clone https://github.com/qybaihe/qg-skill ~/.codex/skills/qgcar-skill

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill instructs use of a local shell CLI (qg) and generation of external WeChat links, but it declares no explicit permissions or allowed-tools scope. That creates an authorization gap where an agent may invoke shell and possibly network-capable tooling without a narrowly bounded policy, increasing the chance of unintended command execution or data exposure.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The activation text is broad enough that the skill could trigger on general transportation or booking-related requests, causing the agent to use shell-backed actions in situations where the user did not clearly ask for this specific bus workflow. Over-broad activation increases the risk of unintended tool use and accidental disclosure or manipulation of local state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The installer unconditionally runs rm -rf on the target skill directory before recreating it, with no confirmation or backup. Although the path is quoted, it is derived from environment variables, so a misconfigured or manipulated CODEX_HOME/OPENCLAW_HOME value could cause unintended data loss by deleting unrelated directories under those roots.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The installer retrieves code from remote sources (GitHub and npm) and performs a global CLI installation, which exceeds the narrow stated purpose of a ticket-link preparation skill. This expands the trust boundary substantially: anyone controlling the referenced package, repository, or the user's environment variables can cause arbitrary code to be installed and executed during setup.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script uses network access to query npm, clone or download a repository, and install a package globally even though the skill description says it should only help prepare booking links and must not autonomously act beyond that scope. That mismatch makes the installer more dangerous because it grants broad system modification capability unrelated to the minimal functionality users would expect from this skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest says the skill helps with Qiguan bus tickets using the local qg CLI, including copying links, but this file itself spawns platform clipboard utilities (pbcopy/clip/xclip) via child_process. Launching external programs is a materially broader capability than simple schedule lookup or link generation and is not obviously required for the stated purpose when printing the link would suffice.

Content

No source excerpt is available for this finding.

External Script Fetching

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The README instructs users to fetch and execute a remote shell script directly from the network. Even though the URL is commit-pinned, piping remote content into bash removes an inspection step and grants immediate code execution; the script also falls back to npm/GitHub build sources, expanding the supply-chain trust boundary.

Content

Scanner excerpt · README.md (reported line 35)May include surrounding context.

安装 CLI,并把 Skill 同时安装到 ~/.codex/skills/qgcar-skill 和 ~/.openclaw/skills/qgcar-skill:

bash
curl -fsSL https://raw.githubusercontent.com/qybaihe/qg-skill/26ed8e31342968836b672d0ea7ab2a275361779c/install.sh | bash

脚本会优先从 npm 安装 qg-skill;如果 npm 包还没发布,会自动 fallback 到 GitHub 源码构建安装。

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The user-intent section only documents example requests in Chinese and maps station names partly through Chinese phrases, with no statement that other languages are also supported. This can be read as a locale/language constraint without user opt-in.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.27.7 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The lockfile pins esbuild to 0.27.7, which is reported as affected by GHSA-g7r4-m6w7-qqqr. Although esbuild is only a development dependency here and the advisory is specific to running esbuild's development server on Windows, keeping a known vulnerable package in the dependency tree is still a real issue because it can expose developers or CI environments if that feature is used.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 54)May include surrounding context.

json
"qg": "tsx src/cli.ts"
  },
  "devDependencies": {
    "@types/node": "^22.14.0",
    "tsx": "^4.19.3",
    "typescript": "^5.8.3"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 55)May include surrounding context.

json
},
  "devDependencies": {
    "@types/node": "^22.14.0",
    "tsx": "^4.19.3",
    "typescript": "^5.8.3"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 56)May include surrounding context.

json
"devDependencies": {
    "@types/node": "^22.14.0",
    "tsx": "^4.19.3",
    "typescript": "^5.8.3"
  }
}

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code creates a hidden cache directory under the user's home directory and writes schedule-derived data to last-list.json. There is no confirmation prompt, log message, comment, or other user-visible disclosure here indicating that local data will be persisted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The code saves the last retrieved schedule list to local storage via saveLastList(cacheItems), which is a file-write-like operation. In this file there is no prompt, log message, or nearby comment/docstring disclosing that running the list command persists data locally, so users may not realize command results are being stored.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
dist/cli.js:237

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/cli.ts:298