Back to skill

Security audit

Twhidden Bitwarden

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Bitwarden/Vaultwarden helper, but it handles full vault secrets in ways that create material review risks before installation.

Install only if you are comfortable giving this skill and your OpenClaw agent access equivalent to an unlocked Bitwarden vault. Use a dedicated low-scope vault account if possible, require manual approval for retrieve/create/edit/delete/register commands, avoid plaintext master-password files where you can, ensure BW_SERVER is HTTPS, and lock/logout after use.

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
bw.sh:19
Finding

Predictable Shared Session File Enables Token Exposure, Substitution, and File-Clobbering Risks

Content
View full analysis
/dev/null) echo "$session" > "$SESSION_FILE" chmod 600 "$SESSION_FILE" echo "Logged in successfully." elif [[ "$status" == "locked" ]]; then local session session=$(bw unlock "$BW_MASTER_PASSWORD" --raw 2>/dev/null) echo "$session" > "$SESSION_FILE" chmod 600 "$SESSION_FILE" echo "Vault unlocked." ``` ### Technical Analysis The script stores a security-sensitive Bitwarden session token at the fixed, globally predictable path `/tmp/.bw_session`. This path is shared across users, workspaces, Bitwarden accounts, and configured servers. The token is written using shell redirection before `chmod 600` is applied. Its initial permissions therefore depend on the process umask. Under a permissive umask, another local user may have a short opportunity to read the token before the permissions are restricted. The script also does not verify that the existing path is a regular file owned by the current user, does not protect against symbolic links, and does not create the file atomically. On systems without adequate protected-symlink enforcement, an attacker who can create entries in `/tmp` could prepare `/tmp/.bw_session` as a symbolic link. The subsequent redirection may follow that link and overwrite a file writable by the victim. Because the path is not namespaced by account or server, concurrent invocations can overwrite each other's sessions. The script will also blindly import any content already present ...[truncated 1574 chars]
Remediation
View remediation
` redirection. 5. Refuse to use an existing object unless it is a regular file, is not a symbolic link, and is owned by the current effective user. 6. Namespace the session by a cryptographic hash of the server and account identity to prevent collisions between different configurations. 7. Prefer `BW_SESSION` in process memory where practical and avoid persistent session storage if automatic reuse is not essential. 8. Ensure cleanup occurs on logout, lock, normal exit, and relevant termination signals. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
bw.sh:83
Finding

Bitwarden Master Password Is Exposed Through Process Command-Line Arguments

Content
View full analysis
/dev/null 2>&1 || true local status # Parse status JSON without python - extract "status":"value" pattern local raw_status raw_status=$(bw status 2>/dev/null || echo '{}') status=$(echo "$raw_status" | grep -oP '"status"\s*:\s*"\K[^"]+' 2>/dev/null || echo "unauthenticated") if [[ "$status" == "unauthenticated" ]]; then local session session=$(bw login "$BW_EMAIL" "$BW_MASTER_PASSWORD" --raw 2>/dev/null) echo "$session" > "$SESSION_FILE" chmod 600 "$SESSION_FILE" echo "Logged in successfully." elif [[ "$status" == "locked" ]]; then local session session=$(bw unlock "$BW_MASTER_PASSWORD" --raw 2>/dev/null) echo "$session" > "$SESSION_FILE" chmod 600 "$SESSION_FILE" echo "Vault unlocked." ``` ```bash # Step 1: Master key = PBKDF2-SHA256(password, email_lower, 600000, 32 bytes) local master_key_hex master_key_hex=$(openssl kdf -keylen 32 -kdfopt digest:SHA256 \ -kdfopt "pass:$reg_pass" -kdfopt "hexsalt:$(echo -n "$email_lower" | xxd -p | tr -d '\n')" \ -kdfopt "iter:$kdf_iterations" -binary PBKDF2 | xxd -p | tr -d '\n') # Step 2: Master password hash = PBKDF2-SHA256(master_key, password, 1, 32) → base64 local master_password_hash master_password_hash=$(openssl kdf -keylen 32 -kdfopt digest:SHA256 \ -kdfopt "hexpass:$master_key_hex" \ -kdfopt "hexsalt:$(echo -n "$reg_pass" | xxd -p | tr -d '\n')" \ -kdfopt "iter:1" -binary PBKDF2 | base64 -w0) ``` ### Technical Analysis The login and unlock operations pass `BW_MASTER_PASSWORD` directly as an argument to the `bw` executable. Registration similarly places the plaintext password and a hexadecimal representation of it in OpenSSL command arguments through ` ...[truncated 2047 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
bw.sh:83
Finding

Unvalidated Server URL Allows Authentication and Registration Over Plaintext HTTP

Content
View full analysis
/dev/null 2>&1 || true ``` ```bash # Submit registration via curl local response http_code body response=$(curl -s -w "\n%{http_code}" -X POST \ "${BW_SERVER}/api/accounts/register" \ -H "Content-Type: application/json" \ -d "$(cat <
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

You can also override the credentials file path:

bash
export CREDS_FILE=/path/to/your/credentials.env

Server Configuration Examples

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The README instructs users to store the Bitwarden master password in a persistent plaintext file under the workspace. Even with chmod 600, plaintext at-rest storage of a master password materially increases risk from local compromise, backups, accidental inclusion in workspace syncs, or other tooling that can read the file; in a password-manager integration, this secret has especially high value.

Content

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

Configuration

Create a credentials file at secrets/bitwarden.env in your OpenClaw workspace:

bash
BW_SERVER=https://vault.bitwarden.com

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

Secure the file:

bash
chmod 600 ~/.openclaw/workspace/secrets/bitwarden.env

Alternatively, set these as environment variables directly.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The README documents commands such as get-password, get-username, get-notes, and get that print vault secrets directly to standard output, but it does not warn users that terminal output may be exposed through shell history capture, terminal scrollback, logging, CI output, or agent/tool transcripts. In the context of a password-manager skill, encouraging direct secret printing increases the chance of accidental credential disclosure even if the underlying behavior is intentional.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill explicitly documents shell-based capabilities and invocation of a local script (bash skills/bitwarden/bw.sh), but it does not declare any tool scope such as permissions or allowed-tools. In an autonomous agent setting, missing tool restrictions increases the risk that the skill can be invoked with broader shell access than intended, especially given it handles credentials and secret retrieval.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest and high-level description understate the capability of the skill: it does not only wrap the Bitwarden CLI, but can also register brand-new accounts and transmit registration material to a remote server. In an agent setting, incomplete disclosure is security-relevant because users or orchestrators may invoke the skill under false assumptions about what actions it can perform and what data it sends externally.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
local session
    session=$(bw login "$BW_EMAIL" "$BW_MASTER_PASSWORD" --raw 2>/dev/null)
    echo "$session" > "$SESSION_FILE"
    chmod 600 "$SESSION_FILE"
    echo "Logged in successfully."
  elif [[ "$status" == "locked" ]]; then
    local session

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 112)May include surrounding context.

md
local session
    session=$(bw login "$BW_EMAIL" "$BW_MASTER_PASSWORD" --raw 2>/dev/null)
    echo "$session" > "$SESSION_FILE"
    chmod 600 "$SESSION_FILE"
    echo "Logged in successfully."
  elif [[ "$status" == "locked" ]]; then
    local session

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 149)May include surrounding context.

md
local session
    session=$(bw login "$BW_EMAIL" "$BW_MASTER_PASSWORD" --raw 2>/dev/null)
    echo "$session" > "$SESSION_FILE"
    chmod 600 "$SESSION_FILE"
    echo "Logged in successfully."
  elif [[ "$status" == "locked" ]]; then
    local session

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · bw.sh (reported line 95)May include surrounding context.

sh
local session
    session=$(bw login "$BW_EMAIL" "$BW_MASTER_PASSWORD" --raw 2>/dev/null)
    echo "$session" > "$SESSION_FILE"
    chmod 600 "$SESSION_FILE"
    echo "Logged in successfully."
  elif [[ "$status" == "locked" ]]; then
    local session

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · bw.sh (reported line 101)May include surrounding context.

sh
local session
    session=$(bw login "$BW_EMAIL" "$BW_MASTER_PASSWORD" --raw 2>/dev/null)
    echo "$session" > "$SESSION_FILE"
    chmod 600 "$SESSION_FILE"
    echo "Logged in successfully."
  elif [[ "$status" == "locked" ]]; then
    local session

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code implements custom cryptographic registration logic and uses curl directly against the server API, which is materially different from a simple CLI wrapper. That mismatch increases risk because custom security-sensitive logic is harder to validate, easier to get subtly wrong, and may bypass expectations, controls, or audit assumptions built around the official CLI behavior.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · bw.sh (reported line 180)May include surrounding context.

sh
# Format: type 2 = AES-CBC-256 + HMAC-SHA256
  local encrypted_key="2.${iv_b64}|${ct_b64}|${mac_b64}"

  # Submit registration via curl
  local response http_code body
  response=$(curl -s -w "\n%{http_code}" -X POST \
    "${BW_SERVER}/api/accounts/register" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The delete command removes vault items immediately with no confirmation, dry-run, or secondary validation. In a password-manager context this is dangerous because mistaken or agent-triggered deletion can irreversibly destroy credentials, causing account lockout, operational disruption, or loss of recovery data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest claims the skill 'wraps the Bitwarden CLI (bw) with automatic session management.' The changelog shows part of the implementation uses openssl, curl, and custom JSON parsing for registration, meaning the skill does more than just wrap the CLI and implements protocol-level operations itself.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes a Bitwarden/Vaultwarden integration for storing, retrieving, generating, or managing passwords and credentials via the Bitwarden CLI. The changelog states the skill performs HTTP-based registration and earlier calls it a CLI wrapper with registration and CRUD operations, which extends beyond vault management into account creation on the service itself.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Registration transmits account data, including derived authentication material, to a user-configured remote server without an explicit warning in the command flow. In this skill’s context, where BW_SERVER is configurable and may point to self-hosted infrastructure, lack of an in-band warning raises the chance that credentials are sent to an unintended or untrusted endpoint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.