Back to skill

Security audit

Bitwarden Lease

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed local Bitwarden session broker with real credential-access risk, but the reviewed artifacts match that purpose and do not show hidden exfiltration or destructive behavior.

Install only if you are comfortable with a user-level background broker holding a Bitwarden session in memory for up to 24 hours and allowing same-user local processes to request allowlisted Bitwarden operations during that window. Prefer installing from a pinned, reviewed revision instead of the unpinned npx command, and route secret output directly to the intended consumer rather than into chat, logs, shell history, or files.

Vulnerability Patterns
  • 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
  • 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 (1)

T08 · Insecure Dependencies

Warning
Location
README.md:58
Finding

Unpinned npm executable and mutable Skill source in installation instructions

Content
View full analysis

Vulnerability Details

File Location: README.md:58
Vulnerability Type: Supply-chain exposure through unpinned executable dependencies and remote source revisions
Risk Level: Medium

Vulnerable Code

bash
npx skills add AntreasAntoniou/bitwarden-lease

Technical Analysis

The documented installation command invokes the skills package through npx without specifying a reviewed package version or integrity value. If that package is not already available locally, npx may retrieve and execute its current published version.

The referenced Skill repository is also identified by repository name rather than an immutable commit hash or signed release. Consequently, the code and instructions installed by this command can change after the audited project revision has been reviewed.

This creates a supply-chain trust boundary involving both the npm-hosted executable and the mutable repository source. A compromised package, transferred package ownership, malicious future release, compromised repository, or force-updated reference could cause users to execute or install content that was not covered by this audit.

The audited local scripts themselves do not retrieve remote payloads, and exploitation requires a user to follow the documented installation command.

Attack Path

  1. An attacker compromises the npm package used by npx, publishes a malicious version under the expected package name, or compromises the referenced Skill repository.
  2. The attacker adds code or Skill instructions that execute commands, alter agent behavior, or install additional components.
  3. A user follows README.md:58 without independently pinning or verifying the retrieved artifacts.
  4. npx retrieves and executes the current package version, which then resolves the mutable repository source.
  5. The attacker-controlled content runs or is installed with the permissions of the invoking user.
  6. Depending on the malicio ...[truncated 863 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin the skills npm package to a specifically reviewed version rather than allowing npx to select the current release.
  2. Reference the Skill repository by an immutable commit hash or a cryptographically signed release tag.
  3. Use npm lockfile and integrity metadata where the installation mechanism supports them.
  4. Prefer a download-and-verify workflow that checks a published SHA-256 digest or signature before executing installation code.
  5. Document the exact expected repository commit and package version so users can verify what is being installed.
  6. Consider using an invocation that refuses implicit installation when the required package is absent, followed by a separate, explicitly verified installation step.
  7. Re-audit and update the pinned versions deliberately when upstream changes are required.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
Findings (40)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is about operating a macOS Bitwarden lease mechanism and related LaunchAgent diagnostics/consumption behavior. The supplied code does not install, operate, unlock, consume, diagnose, or repair any Bitwarden CLI lease. Instead, it validates the contents of a repository/package for publication hygiene and metadata correctness. While the script references Bitwarden lease filenames and metadata, that is only in the context of static package validation, not credential-store interaction or lease management. This is a materially different primary purpose, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Set the directory containing this `SKILL.md` before invoking bundled scripts:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/bitwarden_lease_broker.py (reported line 136)May include surrounding context.

python
socket_root = Path("/tmp") / f"bwls-{os.getpid()}"
    socket_root.mkdir(mode=0o700)
    socket_path = socket_root / "broker.sock"
    environment = os.environ.copy()
    environment.update(
        {
            "BROKER_TEST_EVENTS": str(events),

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/self_test.py (reported line 90)May include surrounding context.

python
socket_root = Path("/tmp") / f"bwls-{os.getpid()}"
    socket_root.mkdir(mode=0o700)
    socket_path = socket_root / "broker.sock"
    environment = os.environ.copy()
    environment.update(
        {
            "BROKER_TEST_EVENTS": str(events),

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/self_test.py (reported line 164)May include surrounding context.

python
socket_root = Path("/tmp") / f"bwls-{os.getpid()}"
    socket_root.mkdir(mode=0o700)
    socket_path = socket_root / "broker.sock"
    environment = os.environ.copy()
    environment.update(
        {
            "BROKER_TEST_EVENTS": str(events),

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/self_test.py (reported line 207)May include surrounding context.

python
home.mkdir()
    completed = subprocess.run(
        [sys.executable, str(INSTALLER), "install", "--python", "python3"],
        env={**os.environ, "HOME": str(home)},
        capture_output=True,
        text=True,
        check=False,

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 · scripts/validate_package.py (reported line 27)May include surrounding context.

python
"scripts/self_test.py",
    "scripts/validate_package.py",
}
FORBIDDEN_NAMES = {".env", "id_rsa", "id_ed25519", "secrets.json"}
FORBIDDEN_MARKERS = (
    "Olym" + "pus credential lease",
    "Application Support/" + "Axi" + "otic",

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/validate_package.py (reported line 27)May include surrounding context.

python
"scripts/self_test.py",
    "scripts/validate_package.py",
}
FORBIDDEN_NAMES = {".env", "id_rsa", "id_ed25519", "secrets.json"}
FORBIDDEN_MARKERS = (
    "Olym" + "pus credential lease",
    "Application Support/" + "Axi" + "otic",

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The README instructs users to run npx skills add AntreasAntoniou/bitwarden-lease without pinning a specific package version. That can cause execution of whatever version is current at install time, so a compromised upstream package, typo-squatted dependency, or malicious newly published version could run arbitrary code during installation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill performs privileged local actions such as shell execution, file reads/writes, and potentially network-capable Bitwarden CLI operations, but it does not declare an explicit tool/permission scope. That creates an authority gap where an agent may invoke broader capabilities than a reviewer expects, increasing the risk of overreach or accidental secret exposure during installation, diagnosis, or credential retrieval workflows.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

text

The native dialog is the only password-entry surface. It permits three
attempts. Do not ask the user to type into an agent terminal, do not accept the
password in chat, and do not pass it in argv, files, shell history, clipboard
automation, or environment variables.

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 · scripts/bitwarden_lease_broker.py (reported line 70)May include surrounding context.

python
if password is None:
                    return {"error": "unlock cancelled", "status": "locked"}
                try:
                    completed = subprocess.run(
                        [
                            "bw",
                            "unlock",

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 · scripts/bitwarden_lease_broker.py (reported line 111)May include surrounding context.

python
'return "__BW_BROKER_CANCELLED__"\n'
            "end try\n"
        )
        completed = subprocess.run(
            ["osascript", "-e", script],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
86% confidence
Finding

The broker executes bw subcommands on behalf of any process that can reach the Unix socket, using the in-memory BW_SESSION token. Although the code restricts commands and avoids shell injection by passing an argument list, this still creates a local privilege boundary concern: an unauthorized local client that can access the socket can query vault data through bw get or bw list during the 24-hour lease window.

Content

Scanner excerpt · scripts/bitwarden_lease_broker.py (reported line 139)May include surrounding context.

python
environment = os.environ.copy()
        environment["BW_SESSION"] = self._session or ""
        try:
            completed = subprocess.run(
                ["bw", *argv],
                env=environment,
                capture_output=True,

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 · scripts/bitwarden_lease_broker.py (reported line 165)May include surrounding context.

python
def _clear_if_cli_reports_locked(self, environment: dict[str, str]) -> None:
        try:
            completed = subprocess.run(
                ["bw", "status"],
                env=environment,
                capture_output=True,

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 8)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 26)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 28)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 29)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 73)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 88)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 93)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/install_bitwarden_lease_broker.py (reported line 95)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/self_test.py (reported line 9)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/self_test.py (reported line 184)May include surrounding context.

python
import argparse
import os
import plistlib
import shlex
import shutil
import subprocess

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/self_test.py:30