T09 · Insecure Skill Coding Practices
Error
- Location
- bw.sh:19
- Finding
- Predictable Shared Session File Enables Token Exposure, Substitution, and File-Clobbering Risks<![CDATA[ ## Vulnerability Details **File Location**: `bw.sh:19`, `bw.sh:58-64`, `bw.sh:93-101` **Vulnerability Type**: Predictable and non-atomic sensitive temporary file **Risk Level**: High ### Vulnerable Code ```bash SESSION_FILE="/tmp/.bw_session" ``` ```bash get_session() { if [[ -f "$SESSION_FILE" ]]; then cat "$SESSION_FILE" elif [[ -n "${BW_SESSION:-}" ]]; then echo "$BW_SESSION" fi } ``` ```bash 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." ``` ### 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
- <![CDATA[ ## Remediation Suggestions 1. Store the session under a private, per-user runtime directory such as `$XDG_RUNTIME_DIR`, rather than directly under `/tmp`. 2. If no private runtime directory is available, create one safely with `mktemp -d`, set it to mode `700`, and remove it with a shell `trap`. 3. Set `umask 077` before creating any file containing authentication material. 4. Create the session file atomically and exclusively rather than using ordinary `>` 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. ]]>
