Skip to content

bitwarden

Notes related to the bitwarden password manager.

bitwarden CLI

https://bitwarden.com/help/cli/

Essentials:

bw --help
bw <command> --help
bw login
bw sync
bw lock
bw logout

Programmatically work with attachments

Without a way to do this from any of the GUI based clients, this will help you work with large numbers of attachments.

WARNING: Do not do use bw if you have certain types of PowerShell logging enabled, for example transcript logging. Similar to enabling clipboard monitoring in Sysmon, you can potentially write your entire vault to disk in clear text.

Script tracing and script block logging records the content of scripts themselves for auditing purposes. If a malicious script runs or if a script breaks something, what was executed exactly at the time of running that script is written to a file on disk.

To avoid issues here, use variables for bw queries as demonstrated below. The most that can be retrieved in some cases is the name or title of an entry, or it's itemid which is acceptable. By doing this the variable runs the query each time the script is invoked rather than hardcoding the variable iteself. You'd need to have a valid login session to return any information.

Transcript logging logs all of the text that appears in a terminal session window. This is what can potentially be dangerous if you're searching your vault from PowerShell while this setting is enabled. It can be enabled manually via the Start-Transcript cmdlet. This cmdlet can also be enabled in a profile to run every time you open PowerShell. Similar to bash profiles, this means it will invoke Start-Transcript anytime you run PowerShell.

To check your PowerShell profile settings to see if this is enabled, review the locations mentioned here. Also check your registry to see if it's enabled there as well.

Retrieve an itemid

bw list items --search <query> --pretty | grep -P "^\s+\"id\":\s\".*\",$" | cut -d '"' -f 4 | head -n1

Get the itemid of your entry named 'GitHub'

If mutiple results are found, remove the regex to see what's returned and refine your query

bw list items --search GitHub --pretty | grep -P "^\s+\"id\":\s\".*\",$" | cut -d '"' -f 4 | head -n1

Put the query for the itemid into a variable

This should be only one line, so double quoting "$()" is fine

ITEM_ID="$(bw list items --search <query> --pretty | grep -P "^\s+\"id\":\s\".*\",$" | cut -d '"' -f 4 | head -n1)"

Upload files

You'll receive continuous responses to the console window for each attachment uploaded.

for file in ../path/*.test; do bw create attachment --file "$file" --itemid "$ITEM_ID"; done

Confirm the files are listed under "$ITEM_ID" attachments

bw get item "$ITEM_ID" --pretty

Enumerate attachments

We grep for any matches after -A the list of attachments, as other entries above the attachments line (which we don't want) could also match this regex

10000 is arbitrary, just a guess to an upper limit on how many lines of json the attachments cover - update this if you need to

DO NOT double quote the command substitution $(), this way each result is it's own line vs the list of results being a single string

ATTACHMENT_IDS=$(bw get item "$ITEM_ID" --pretty | grep -A 10000 -Px "^\s+\"attachments\": \[$" | grep -Px "^\s+\"id\": \"\w+\",$" | grep -Fv '-' | cut -d '"' -f 4)

Download attachments

DO double quote the variable of each "$file", or each line from the output above

for file in $ATTACHMENT_IDS; do bw get attachment "$file" --itemid "$ITEM_ID"; done

Delete attachments

Same as downloading, with delete instead of get

for file in $ATTACHMENT_IDS; do bw delete attachment "$file" --itemid "$ITEM_ID"; done