Dan Pastusek's Blog | Home


How to export a vault from Bitwarden without knowing the master password

Published 2023-01-24 Updated: 2024-01-24

I recently changed my Bitwarden master password and promptly forgot it. Bitwarden (in an attempt to be secure, I suppose) sends a push event to all other online devices to log you out. That would be fine, but when you change your password is when you are most likely to forget it, and you have absolutely zero recourse if you do. Unlike other password managers, there is no recovery document or keys they make you print when setting it up.

That's fine, you say, since you can always export. But in another attempt to be "secure", they make you type your master password when exporting your vault. I put secure in quotes because of how stupid this policy actually is. If I am still logged in on some device, I can see every site login stored in Bitwarden. So if I were a patient person, I could open each login, and copy / paste them to a new document. But I have ~670 logins stored in Bitwarden, now I know they are all in memory somewhere in plaintext, and I am far too impatient to copy & paste that many items.

So if you find yourself in that predicament, here's how to export your vault from a Bitwarden browser extension that you are still logged into.

First, open a Bitwarden extension window, right click -> inspect, and get the data:

let store = window.bitwardenContainerService.getCryptoService().stateService.memoryStorageService.store

Remove circular references and stringify

const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return;
      }
      seen.add(value);
    }
    return value;
  };
};

const stringified = JSON.stringify(store, getCircularReplacer());

Per this stack overflow, https://stackoverflow.com/a/19818659, export and download the data.

(function(console){

console.save = function(data, filename){
    if(!data) {
        console.error('Console.save: No data')
        return;
    }

    if(!filename) filename = 'console.json'

    if(typeof data === "object"){
        data = JSON.stringify(data, undefined, 4)
    }

    var blob = new Blob([data], {type: 'text/json'}),
        e    = document.createEvent('MouseEvents'),
        a    = document.createElement('a')

    a.download = filename
    a.href = window.URL.createObjectURL(blob)
    a.dataset.downloadurl =  ['text/json', a.download, a.href].join(':')
    e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
    a.dispatchEvent(e)
 }
})(console)

console.save(store)

Now you have an export in the same JSON format as a normal Bitwarden export. You can easily import it into a new vault. You'll notice that some things are missing, such as site URIs. I haven't found a workaround for that, yet.

I hope Bitwarden changes or removes one of both of these policies. For people with programming skills, the vault export is trivial to bypass, and for regular users these policies are an annoyance at best, and result in complete vault loss at worst. Needless to say I was a paying multi-org customer before this, and now am so frustrated at these policies that I am self-hosting all my vaults and will not be returning until a proper recovery solution is implemented.

P.S. Bitwarden team, can we please get passkey support on mobile already? It's 2024.