From 49c5dec9b6c1899f8fc5ad3cff0ddc09cecf71c5 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sun, 13 Oct 2024 20:25:09 +0200 Subject: [PATCH] Fix iOS sync by converting field types to int (#5081) It seems the iOS clients are not able to handle the `type` key within the `fields` array when they are of the type string. All other clients seem to handle this just fine though. This PR fixes this by validating it is a number, if this is not the case, try to convert the string to a number, or return the default of `1`. `1` is used as this is the type `hidden` and should prevent accidental data disclosure. Fixes #5069 Possibly Fixes #5016 Possibly Fixes #5002 Signed-off-by: BlackDex --- src/db/models/cipher.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index a445e5c5..9dc9cba5 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -176,7 +176,27 @@ impl Cipher { .inspect_err(|e| warn!("Error parsing fields {e:?} for {}", self.uuid)) .ok() }) - .map(|d| d.into_iter().map(|d| d.data).collect()) + .map(|d| { + d.into_iter() + .map(|mut f| { + // Check if the `type` key is a number, strings break some clients + // The fallback type is the hidden type `1`. this should prevent accidental data disclosure + // If not try to convert the string value to a number and fallback to `1` + // If it is both not a number and not a string, fallback to `1` + match f.data.get("type") { + Some(t) if t.is_number() => {} + Some(t) if t.is_string() => { + let type_num = &t.as_str().unwrap_or("0").parse::().unwrap_or(1); + f.data["type"] = json!(type_num); + } + _ => { + f.data["type"] = json!(1); + } + } + f.data + }) + .collect() + }) .unwrap_or_default(); let password_history_json: Vec<_> = self @@ -244,7 +264,7 @@ impl Cipher { // NOTE: This was marked as *Backwards Compatibility Code*, but as of January 2021 this is still being used by upstream // data_json should always contain the following keys with every atype - data_json["fields"] = Value::Array(fields_json.clone()); + data_json["fields"] = json!([fields_json]); data_json["name"] = json!(self.name); data_json["notes"] = json!(self.notes); data_json["passwordHistory"] = Value::Array(password_history_json.clone());