Skip to content

Security: KeePassXC master password is taken from the APW_KEEPASSXC_PASSWORD environment variable #93

@jmcte

Description

@jmcte

Summary

load_keepassxc_credential() in rust/src/native_app.rs reads the KeePassXC database master password from the APW_KEEPASSXC_PASSWORD environment variable:

let master_password = env::var("APW_KEEPASSXC_PASSWORD").map_err(|_| { ... })?;

The value is then fed to keepassxc-cli over stdin (good — it is not placed on the child's argv). However, placing the master password in the process environment has its own exposure surface.

Why it matters

Process environment is more exposed than stdin:

  • It is inherited by every child process APW spawns, not just keepassxc-cli (e.g. the broker executable, defaults, curl, tar, security).
  • On many systems same-user processes can read another process's environment (ps eww, /proc/<pid>/environ on Linux); it is commonly captured by crash reporters and diagnostic tooling.
  • It tends to leak into shell history, CI logs, and .env files.

The code comments already acknowledge this is a "reduced-security path," but the master password unlocks the entire KeePassXC vault, so the exposure is higher-value than the rest of the --external-fallback surface.

Recommendation

  • Prefer reading the master password from a file path (referenced by config) or an inherited file descriptor, and scrub it from the spawned child's environment for all other subprocesses.
  • If the env var is retained for non-interactive use, env::remove_var("APW_KEEPASSXC_PASSWORD") immediately after reading it so it is not inherited by unrelated child processes, and document the exposure in docs/SECURITY_POSTURE_AND_TESTING.md.
  • Zeroize the password buffer after use (stdin_payload) rather than relying on drop.

References

Severity: Medium

Filed by an automated deep security review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions