Browse Source

Strip null values from optional Login cipher fields

Some Login ciphers stored in Vaultwarden have explicit `null` values for optional fields (e.g. `totp`, `passwordRevisionDate`, `username`, `uris`) rather than the field being absent. Upstream Bitwarden's server serializes these with `skip_serializing_if = "Option::is_none"` so the fields are always absent when unset, never `null`.

The 2026.5+ Bitwarden clients (using the new sdk-internal WASM SDK) route JS `null` values into `EncString::deserialize` instead of short-circuiting `Option<T>` to `None`, and panic with `invalid type: unit value, expected a valid string`. Serde aborts on the first failure, so one bad cipher causes the entire vault to fail to load.

Match upstream's shape by stripping explicit `null` values from the affected keys before emit. The legacy `uri` field (set unconditionally to `Value::Null` at line 261 for old mobile client compat) is deliberately not stripped.

Refs: #7361, bitwarden/clients#21135
pull/7467/head
0xjjjjjj 2 months ago
parent
commit
12c20f7484
  1. 17
      src/db/models/cipher.rs

17
src/db/models/cipher.rs

@ -280,6 +280,23 @@ impl Cipher {
if let Some(pw_revision) = type_data_json["passwordRevisionDate"].as_str() { if let Some(pw_revision) = type_data_json["passwordRevisionDate"].as_str() {
type_data_json["passwordRevisionDate"] = json!(validate_and_format_date(pw_revision)); type_data_json["passwordRevisionDate"] = json!(validate_and_format_date(pw_revision));
} }
// Strip `null`s from optional Login fields — newer WASM clients panic (see #7361).
if let Value::Object(ref mut map) = type_data_json {
for key in [
"password",
"username",
"totp",
"autofillOnPageLoad",
"fido2Credentials",
"passwordRevisionDate",
"uris",
] {
if map.get(key).is_some_and(Value::is_null) {
map.remove(key);
}
}
}
} }
// Fix secure note issues when data is invalid // Fix secure note issues when data is invalid

Loading…
Cancel
Save