doy / rbw

unofficial bitwarden cli
https://git.tozt.net/rbw
Other
611 stars 84 forks source link

rbw sync fails due to a JSON parse error #50

Closed simias closed 3 years ago

simias commented 3 years ago

I was having issues accessing my passwords with rbw, I decided to rbw purge and resync, but I'm still having a problem synchronizing the database:

$ rbw sync
rbw sync: failed to sync database from server: failed to parse JSON: Ciphers[16].PasswordHistory[0].Password: invalid type: null, expected a string at line 1 column 40928: invalid type: null, expected a string at line 1 column 40928

Seems like a trivial enough fix, but I have no idea how to dump said JSON to figure out why it's not correctly formed.

Since it seems to be the PasswordHistory that's having issues I tried purging the history and even regenerating new entries but it still fails.

I'm running v1.1.2

simias commented 3 years ago

I should add that I'm running a self-hosted bitwarden-rs as the backend, no idea if it's mangling something.

simias commented 3 years ago

I managed a quick and dirty way to dump the json and found the culprit:

"PasswordHistory":[{"LastUsedDate":"2021-03-31T19:30:06.936Z","Password":null}]

I can find this empty entry in the bitwarden desktop app:

history

Note that I suspect that this was added by rbw itself when I used rbw edit on an entry without a password set, but I could be wrong since I can't reproduce it as long as my rbw is out of order.

So I managed to work around the issue using the following patch:

diff --git a/src/api.rs b/src/api.rs
index 99e12fd..ac35306 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -254,7 +254,7 @@ impl SyncResCipher {
                 .iter()
                 .map(|entry| crate::db::HistoryEntry {
                     last_used_date: entry.last_used_date.clone(),
-                    password: entry.password.clone(),
+                    password: entry.password.clone().unwrap_or_else(String::new),
                 })
                 .collect()
         } else {
@@ -459,7 +459,7 @@ struct SyncResPasswordHistory {
     #[serde(rename = "LastUsedDate")]
     last_used_date: String,
     #[serde(rename = "Password")]
-    password: String,
+    password: Option<String>,
 }

This way the sync command completes, but now I hit another problem:

rbw list: failed to decrypt: failed to parse encrypted secret: invalid cipherstring: couldn't find type
simias commented 3 years ago

Ah it's actually the same issue: since above I replace the NULL password with an empty string, it then fails when it attempts to decrypt it.

So instead I'm going to filter out entries with no password.