Back to skill

Security audit

Vault Client

Security checks for vulnerabilities and agentic risk

Overview

This Vault client has a coherent purpose, but it persists Vault credentials and cached secrets locally and modifies future agent instructions in ways users should review before installing.

Review this before installing. Use only a least-privilege, short-lived Vault token; require HTTPS with a valid certificate; avoid tls.verify:false and http:// addresses; treat ~/.openclaw/vault.json and ~/.openclaw/vault-cache.json as sensitive files; clear the cache when done; and inspect any AGENTS.md changes before allowing them to affect future sessions.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/vault.js:34
Finding

Vault credentials and cached secrets are stored without restrictive file permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/vault.js:34-36 and scripts/vault.js:87-89
Vulnerability Type: Insecure storage of sensitive information
Risk Level: High

Vulnerable Code

Configuration writing at scripts/vault.js:34-36:

js
function saveConfig(cfg) {
  fs.mkdirSync(path.dirname(CONFIG_PATH), { recursive: true });
  fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
}

Cache writing at scripts/vault.js:87-89:

js
function saveCache(cache) {
  fs.writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));
}

Technical Analysis

The configuration file contains the Vault authentication token, and the cache file contains complete plaintext secret values retrieved from Vault. Both files are written without an explicit restrictive mode such as 0600.

Node.js therefore creates these files using permissions derived from the process umask. In environments with a permissive or incorrectly configured umask, other local users or processes may be able to read the files. The code also does not inspect or repair the permissions of existing files.

The cache increases the exposure scope because retrieved API keys, database credentials, and other secrets remain on disk until manually removed, even after their configured cache expiration time. Cache expiration only prevents the application from using stale entries; it does not erase expired values from the file.

Attack Path

  1. A user runs vault.js setup, causing the Vault token to be written to ~/.openclaw/vault.json.
  2. The user runs vault.js get, causing retrieved secret values to be written to ~/.openclaw/vault-cache.json.
  3. The files are created under the permissions allowed by the ambient process umask.
  4. Another local account or compromised process reads one or both files if their resulting permissions permit access.
  5. The attacker directly uses cached credentials or submits the stolen V ...[truncated 746 chars]
Remediation
View remediation

Remediation Suggestions

  • Create both sensitive files with owner-only permissions:

    js
    fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2), {
      mode: 0o600
    });
    
    fs.writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2), {
      mode: 0o600
    });
    
  • Apply fs.chmodSync(file, 0o600) after writing so existing files with unsafe permissions are repaired.

  • Ensure ~/.openclaw is accessible only to its owner, preferably with mode 0700.

  • Use atomic writes through a securely created temporary file in the same protected directory, followed by a rename.

  • Refuse or safely handle symbolic links to reduce the risk of writing sensitive data to an unintended target.

  • Consider disabling persistent secret caching by default. If caching is required, remove expired entries from disk and provide a command that securely clears the cache.

  • Where feasible, store the Vault token through an operating-system credential store or secret service rather than a plaintext JSON file.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/vault.js:41
Finding

Vault tokens and secrets can be transmitted over unauthenticated or unencrypted connections

Content
View full analysis

Vulnerability Details

File Location: scripts/vault.js:41-66; insecure configuration is documented at SKILL.md:55
Vulnerability Type: Improper transport security for credentials and secret data
Risk Level: High

Vulnerable Code

js
function vaultRequest(cfg, method, urlPath, body = null) {
  return new Promise((resolve, reject) => {
    const url    = new URL(urlPath, cfg.address);
    const isHttps = url.protocol === 'https:';
    const lib    = isHttps ? https : http;
    const token  = cfg.auth?.token || '';

    const options = {
      hostname: url.hostname,
      port:     url.port || (isHttps ? 443 : 80),
      path:     url.pathname + url.search,
      method,
      headers: {
        'X-Vault-Token': token,
        'Content-Type':  'application/json',
      },
      timeout: 8000,
      // allow self-signed certs on internal Vault
      rejectUnauthorized: cfg.tls?.verify !== false,
    };

The accompanying documentation states:

md
Set `tls.verify: false` for internal Vault with self-signed certs.

Technical Analysis

The client accepts an http:// Vault address and automatically uses Node.js's plaintext HTTP implementation. The X-Vault-Token header and all request and response bodies are consequently transmitted without encryption.

For HTTPS connections, setting tls.verify to false disables certificate validation through rejectUnauthorized: false. Encryption without peer authentication does not protect against an active man-in-the-middle attacker because the attacker can present an arbitrary certificate and impersonate the Vault server.

Every request includes the Vault token, including secret reads, writes, listing operations, and token-management calls. Secret values returned by reads and submitted by writes are therefore exposed when transport security is disabled.

Attack Path

  1. A user configures an http:// Vault address ...[truncated 1208 chars]
Remediation
View remediation

Remediation Suggestions

  • Reject all non-HTTPS Vault addresses by default.
  • If plaintext HTTP is needed for development, restrict it to explicit loopback addresses and require a deliberate insecure-development override.
  • Remove the recommendation to set tls.verify to false.
  • Add support for a private certificate authority file, for example through an explicit tls.ca_file setting passed to the HTTPS request as trusted CA material.
  • Keep rejectUnauthorized enabled in normal operation and fail closed when certificate validation fails.
  • Validate the configured protocol and transport settings during setup and before every request.
  • Display a prominent warning and require explicit confirmation if any insecure override is retained.
  • Document secure deployment requirements, including valid server certificates, hostname verification, and protection against untrusted network paths.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/vault.js:263
Finding

Interactive setup echoes the Vault authentication token in plaintext

Content
View full analysis

Vulnerability Details

File Location: scripts/vault.js:263
Vulnerability Type: Sensitive credential exposure through terminal input
Risk Level: Medium

Vulnerable Code

js
const token    = await ask(`Vault token   [${existing.auth?.token ? '(existing)' : 'hvs.xxx'}]: `);

The prompt is implemented using the ordinary readline interface:

js
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const ask = (q) => new Promise(resolve => rl.question(q, resolve));

Technical Analysis

readline.question does not conceal user input. A Vault token entered during setup is visibly echoed to the terminal.

Although the token is not intentionally printed after submission, terminal echo can expose it through shoulder surfing, screen sharing, terminal session recording, remote administration logs, or captured demonstrations. Vault tokens are bearer credentials and can generally be replayed without knowledge of another password.

Attack Path

  1. A user runs vault.js setup.
  2. The setup wizard asks the user to enter a Vault token.
  3. The token appears visibly while it is typed.
  4. A nearby observer, screen-sharing participant, or terminal-recording system captures the token.
  5. The observer submits the captured token to the Vault API.
  6. The observer performs operations allowed by the token until it expires or is revoked.

Impact Assessment

The attacker obtains the same Vault authorization granted to the exposed bearer token. Depending on its policies, this may permit reading secrets, listing paths, updating values, or renewing the token.

The direct scope is Vault access rather than local operating-system privilege. However, secrets obtained from Vault may enable access to databases, APIs, cloud infrastructure, and other systems.

Remediation
View remediation

Remediation Suggestions

  • Replace the ordinary readline token prompt with a hidden-input implementation that suppresses terminal echo.
  • Restore terminal state reliably on success, interruption, and exceptions.
  • Permit reading the token from a protected file descriptor or operating-system credential store for automated setup.
  • Do not accept the token as a command-line argument because arguments may be exposed through shell history and process listings.
  • Warn users not to enter tokens while screen sharing or in recorded terminal sessions.
  • After suspected exposure, revoke the affected token and issue a replacement with the minimum required Vault policies and a limited lifetime.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation advises setting tls.verify: false for self-signed certificates without a strong warning about the security consequences. Disabling certificate verification removes server identity validation and exposes Vault traffic and tokens to man-in-the-middle attacks, which is severe given this skill handles secrets.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Retrieved secrets are cached to disk in ~/.openclaw/vault-cache.json, creating local plaintext persistence of sensitive material outside Vault's access controls and audit boundaries. Anyone with filesystem access, backup access, or malware on the host may recover API keys, credentials, or other secrets even after the Vault session ends.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill invokes shell commands (node .../vault.js) but does not declare an explicit tool scope such as permissions or allowed-tools. That creates an authorization gap where an agent may be able to execute shell-capable behavior without clear policy boundaries, which is especially sensitive for a secret-management skill.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 3)May include surrounding context.

md
---
name: vault-client
description: Hashicorp Vault client for OpenClaw agents. Read and write secrets from a Vault server without raw curl commands or hardcoded tokens. Use when reading API keys, DB credentials, or any secret stored in Hashicorp Vault; checking token expiry; rotating secrets; or configuring Vault access for the first time. NOT for the zuiho-kai local Vault skill (that is a different, local-only tool).
---

# vault-client

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The setup flow stores Vault address, token, and mount in ~/.openclaw/vault.json and modifies AGENTS.md, but the documentation does not clearly warn that credentials and configuration will persist on disk across sessions. Persisted secrets increase the chance of local credential exposure through filesystem compromise, backups, logs, or accidental sharing.

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 · references/auth-methods.md (reported line 20)May include surrounding context.

Get a token via AppRole:

bash
curl -s -X POST https://vault.example.com:8200/v1/auth/approle/login \
  -d '{"role_id":"<role_id>","secret_id":"<secret_id>"}' | \
  node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(d.auth.client_token)"

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 · references/auth-methods.md (reported line 38)May include surrounding context.

bash
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -s -X POST https://vault.example.com:8200/v1/auth/kubernetes/login \
  -d "{\"role\":\"my-role\",\"jwt\":\"$TOKEN\"}" | \
  node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(d.auth.client_token)"

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 · scripts/vault.js (reported line 8)May include surrounding context.

js
* Usage:
 *   vault.js check                        # connectivity + token expiry
 *   vault.js get <path> [key]             # read secret (or single key)
 *   vault.js put <path> key=value ...     # write secret
 *   vault.js list <path>                  # list keys at path
 *   vault.js token-info                   # show token details + expiry
 *   vault.js token-renew                  # renew token

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The setup wizard collects a Vault token and stores it in plaintext in ~/.openclaw/vault.json without warning, permission hardening, or safer credential storage. A local compromise, shared account, backup leak, or permissive file mode could expose the token and allow unauthorized Vault access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The setup routine performs behavior outside the stated scope of a Vault client by appending instructions into a local AGENTS.md file. This creates an undocumented workspace-modification side effect that can influence future agent behavior and expands trust from secret access into persistent instruction injection.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Appending to AGENTS.md gives the skill persistence over future workspace instructions, which is not necessary for reading or writing Vault secrets. In an agent ecosystem, modifying an instruction file is security-sensitive because it can steer later agent actions, normalize fallback behaviors, or broaden the tool's influence beyond its declared purpose.

Content

No source excerpt is available for this finding.