Back to skill

Security audit

Mvg

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Munich transit CLI, but its install and live-tracking paths can run mutable or locally hijackable code, so it needs user review before installation.

Install only from a reviewed, pinned commit or trusted versioned package, avoid the sudo install option, and treat the live command as higher risk because it executes Node.js and trusts local ws module resolution. The normal MVG lookup commands are read-only network queries, but the live-tracking implementation and exposed geOps key should be fixed before broad use.

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

T03 · Remote Payload Retrieval and Execution

Error
Location
README.md:17
Finding

Unpinned Remote Repository Retrieval and Execution

Content
View full analysis

Vulnerability Details

File Location: README.md, lines 17-20
Vulnerability Type: Mutable remote payload execution
Risk Level: High

bash
# With uvx (recommended) — runs instantly without installation
uvx --from git+https://github.com/Lars147/mvg-cli mvg search "Marienplatz"
uvx --from git+https://github.com/Lars147/mvg-cli mvg departures "Marienplatz"
uvx --from git+https://github.com/Lars147/mvg-cli mvg route "Marienplatz" "Garching"

Technical Analysis

The recommended quick-start commands instruct users to retrieve and execute the current contents of a remote Git repository. The repository reference is not pinned to a reviewed commit hash, immutable tag, or hash-verified package artifact. Consequently, the code executed by future users can differ from the code covered by this audit.

Although remote installation is relevant to distributing a CLI, directly executing a mutable repository exceeds the minimum trust necessary. A compromised maintainer account, repository, dependency declaration, or upstream branch could replace the effective payload without changing this audited artifact.

Attack Path

  1. An attacker compromises the referenced GitHub repository or a maintainer account.
  2. The attacker modifies the default branch, package metadata, build backend behavior, or CLI entry point.
  3. A user follows the recommended uvx --from git+https://... command.
  4. uvx retrieves the changed repository and runs its build or application code.
  5. The malicious code executes with the operating-system privileges of the invoking user.

Impact Assessment

Successful exploitation permits arbitrary code execution in the user's context. The resulting payload could access files readable by that user, modify user-owned configuration, use available network credentials, or install user-level persistence. Administrative privileges are not inherently obtained, but the impact expands if the command is run ...[truncated 41 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin the Git source to a reviewed full commit hash rather than the mutable default branch.
  • Prefer a signed, versioned release distributed through a trusted package registry.
  • Publish and verify cryptographic hashes for release artifacts.
  • Use a lockfile for build and runtime dependencies.
  • Avoid presenting execution from an unpinned Git source as the recommended installation method.
  • Document how users can verify release signatures and source provenance before execution.

T08 · Insecure Dependencies

Error
Location
mvg_cli.py:439
Finding

Unsafe Node.js Module Resolution from a Shared Agent Workspace

Content
View full analysis

Vulnerability Details

File Location: mvg_cli.py, lines 439-448
Vulnerability Type: Untrusted dependency loading and local tool hijacking
Risk Level: High

javascript
// Try multiple locations for ws module
const paths = [
  process.env.HOME + '/.openclaw/workspace/node_modules/ws',
  '/app/node_modules/.pnpm/ws@8.19.0/node_modules/ws',
];
let WebSocket;
for (const p of paths) {
  try { WebSocket = require(p); break; } catch(e) {}
}
if (!WebSocket) { try { WebSocket = require('ws'); } catch(e) { process.stderr.write('ws module not found'); process.exit(1); } }

Technical Analysis

The live-tracking implementation preferentially loads the ws module from hardcoded shared locations, including ~/.openclaw/workspace/node_modules/ws. It does not verify the module version, package integrity, ownership, permissions, or cryptographic hash before calling require().

Loading a Node.js package executes its initialization code. If another workspace component or local process can create or replace the module at the preferred path, invoking mvg live executes attacker-controlled JavaScript. The generic require('ws') fallback also relies on ambient Node.js resolution rather than an isolated, locked project dependency.

The Skill only needs a WebSocket implementation. Trusting arbitrary code from a shared Agent workspace is not necessary for that functionality and crosses the expected least-trust boundary.

Attack Path

  1. An attacker gains write access to ~/.openclaw/workspace/node_modules/ws, or causes a malicious package to be installed there.
  2. The attacker places malicious initialization code in the forged ws module.
  3. The user invokes the live command.
  4. Python creates and starts the temporary Node.js script.
  5. The script prioritizes the shared workspace path and calls require() on the malicious module.
  6. The attacker's JavaScript executes with the privileges and enviro ...[truncated 466 chars]
Remediation
View remediation

Remediation Suggestions

  • Declare ws as an explicit, project-local dependency and pin an audited version in a lockfile.
  • Remove resolution from ~/.openclaw/workspace and other shared or hardcoded package directories.
  • Run Node.js with an isolated module path controlled by this project.
  • Verify package integrity using lockfile hashes and trusted registry metadata.
  • Reject dependency directories that are writable by unrelated users or workspace components.
  • Prefer a Python WebSocket implementation with a pinned dependency if this eliminates the cross-runtime module-resolution requirement.
  • Consider running live tracking in a restricted subprocess with a minimized environment and filesystem permissions.

T09 · Insecure Skill Coding Practices

Warning
Location
mvg_cli.py:43
Finding

Hardcoded External-Service API Key Exposed in Source and URL

Content
View full analysis

Vulnerability Details

File Location: mvg_cli.py, lines 43-45 and line 480
Vulnerability Type: Hardcoded credential and query-string secret exposure
Risk Level: Medium

python
GEOPS_WS_URL = "wss://api.geops.io/realtime-ws/v1/"
GEOPS_API_KEY = "5cc87b12d7c5370001c1d655112ec5c21e0f441792cfc2fafe3e7a1e"
GEOPS_ORIGIN = "https://s-bahn-muenchen-live.de"
python
url = f"{GEOPS_WS_URL}?key={GEOPS_API_KEY}"

Technical Analysis

A geOps API key is embedded directly in the source and appended to the WebSocket URL as a query parameter. Anyone with access to the repository or distributed artifact can extract and reuse it.

Query-string credentials may additionally be exposed through debugging output, process instrumentation, network middleware, proxy logs, or service-side request logs. The audit could not establish the key's server-side scope, so it should not be assumed to be harmless merely because it may be intended for a public-facing application.

Attack Path

  1. An attacker obtains the source repository or packaged Skill.
  2. The attacker extracts the GEOPS_API_KEY constant.
  3. The attacker submits direct requests to the geOps WebSocket endpoint using the exposed key.
  4. The attacker consumes associated quota or accesses any operations permitted by the key.
  5. Legitimate live tracking may be disrupted if the key is rate-limited, suspended, or revoked following abuse.

Impact Assessment

The direct impact is unauthorized reuse of the external-service credential. Depending on server-side restrictions, this may cause quota exhaustion, service degradation, unexpected charges, attribution of abusive traffic to the legitimate client, or unauthorized access to additional API capabilities. This finding does not expose local user credentials and does not independently provide local system privileges.

Remediation
View remediation

Remediation Suggestions

  • Revoke and rotate the exposed key.
  • Remove the key from source code and repository history.
  • Load the credential from a protected runtime secret or environment variable.
  • Avoid placing credentials in query strings when the service supports an authorization header or another protected authentication mechanism.
  • Restrict the key by origin, endpoint, scope, rate, and quota wherever supported.
  • Use a dedicated low-privilege key intended for this client.
  • Ensure exception messages, subprocess diagnostics, and network logs redact credentials.
  • If geOps explicitly treats this as a public client identifier, document that status and still apply strict server-side restrictions to prevent abuse.
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (11)

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The README instructs users to execute code directly from a Git repository via uvx --from git+https://github.com/Lars147/mvg-cli without pinning to a specific commit, tag, or release. This creates a supply-chain risk: if the upstream repository is later compromised or changed, users will transparently run attacker-controlled code.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

This command repeats the same unsafe pattern of running the tool directly from an unpinned GitHub repository. Because the command is presented as a quickstart path, it meaningfully increases the chance that users execute whatever code currently exists at the remote source.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

Like the other quickstart examples, this line encourages execution from mutable remote source code without version pinning. In a CLI skill context, users may treat README commands as trustworthy setup steps, making repository compromise or malicious force-pushes especially dangerous.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
91% confidence
Finding

The README suggests sudo cp mvg_cli.py /usr/local/bin/mvg, which normalizes using elevated privileges to install an unreviewed script from the repository into a globally trusted execution path. If the script is malicious or later replaced before copy, the user may grant system-wide execution trust to attacker-controlled code.

Content

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

alias mvg="python3 /pfad/zu/mvg_cli.py"

Option B: Ins PATH kopieren

sudo cp mvg_cli.py /usr/local/bin/mvg

text

**Voraussetzungen:** Python 3.9+ und `requests`

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises executable capabilities involving environment access, file writing, network access, and shell usage, but the manifest does not declare any explicit tool scope or permissions boundaries. This creates an authorization ambiguity where an agent may invoke a more powerful runtime than users expect, increasing the risk of unintended command execution, network egress, or local file modification if the implementation is compromised or behaves unexpectedly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger description is broad and includes generic public-transit terms, which can cause the skill to activate in conversations that are only loosely related to Munich transit. Over-broad activation expands the attack surface by increasing the chance the agent routes unrelated user input into a networked, code-capable skill, potentially causing unnecessary external requests or unexpected tool use.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Natural-language help text, command descriptions, and user-facing output are written exclusively in German, which imposes a language choice on all users. Under the policy, locale or language constraints should either be optional, user-selectable, or clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

A hard-coded third-party API key embedded in source code is a credential exposure issue. Anyone with access to the code can reuse the key, abuse the third-party service, exhaust quota, or cause attribution and billing problems for the maintainer.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The live-tracking feature writes and executes a temporary JavaScript file through a local Node.js runtime and probes multiple local module paths. That expands the skill from simple transit API querying into local code execution and environment inspection, increasing risk if the runtime or searched module paths are compromised or manipulated.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · mvg_cli.py (reported line 482)May include surrounding context.

python
try:
            url = f"{GEOPS_WS_URL}?key={GEOPS_API_KEY}"
            out_file = js_path + ".json"
            result = subprocess.run(
                ["node", js_path, url, GEOPS_ORIGIN, str((timeout - 2) * 1000), out_file],
                capture_output=True, text=True, timeout=timeout
            )

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill description, headings, examples, and usage instructions are entirely in German, which can constitute a language/locale policy issue when no user opt-in or alternative language is provided. Although the tool is Munich-specific, the README does not explicitly justify that the documentation itself is intentionally German-only or offer another language option.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.