[GH-ISSUE #5322] Bitwarden Android Beta (2024.12.0 (19597)) fails to sync with SSH keys #39363

Closed
opened 2026-07-17 14:03:52 -05:00 by GiteaMirror · 10 comments
Owner

Originally created by @segln on GitHub (Dec 23, 2024).
Original GitHub issue: https://github.com/dani-garcia/vaultwarden/issues/5322

Vaultwarden Support String

Your environment (Generated via diagnostics page)

EXPERIMENTAL_CLIENT_FEATURE_FLAGS=ssh-key-vault-item,ssh-agent

  • Vaultwarden version: v1.32.7
  • Web-vault version: v2024.6.2c
  • OS/Arch: linux/x86_64
  • Running within a container: true (Base: Debian)
  • Database type: PostgreSQL
  • Database version: PostgreSQL 16.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.2.1 20240805, 64-bit
  • Environment settings overridden!: true
  • Uses a reverse proxy: true
  • IP Header check: true (X-Real-IP)
  • Internet access: true
  • Internet access via a proxy: false
  • DNS Check: true
  • Browser/Server Time Check: true
  • Server/NTP Time Check: true
  • Domain Configuration Check: false
  • HTTPS Check: true
  • Websocket Check: true
  • HTTP Response Checks: true

Config & Details (Generated via diagnostics page)

Show Config & Details

Environment settings which are overridden: ADMIN_TOKEN

Config:

{
  "_duo_akey": null,
  "_enable_duo": false,
  "_enable_email_2fa": true,
  "_enable_smtp": true,
  "_enable_yubico": true,
  "_icon_service_csp": "",
  "_icon_service_url": "",
  "_ip_header_enabled": true,
  "_max_note_size": 10000,
  "_smtp_img_src": "***:",
  "admin_ratelimit_max_burst": 3,
  "admin_ratelimit_seconds": 300,
  "admin_session_lifetime": 20,
  "admin_token": "***",
  "allowed_connect_src": "",
  "allowed_iframe_ancestors": "",
  "attachments_folder": "data/attachments",
  "auth_request_purge_schedule": "30 * * * * *",
  "authenticator_disable_time_drift": false,
  "data_folder": "data",
  "database_conn_init": "",
  "database_max_conns": 10,
  "database_timeout": 30,
  "database_url": "**********://********************,*********************************",
  "db_connection_retries": 15,
  "disable_2fa_remember": false,
  "disable_admin_token": false,
  "disable_icon_download": false,
  "domain": "*****://***************************",
  "domain_origin": "*****://***************************",
  "domain_path": "",
  "domain_set": true,
  "duo_context_purge_schedule": "30 * * * * *",
  "duo_host": null,
  "duo_ikey": null,
  "duo_skey": null,
  "duo_use_iframe": false,
  "email_2fa_auto_fallback": false,
  "email_2fa_enforce_on_verified_invite": false,
  "email_attempts_limit": 3,
  "email_change_allowed": true,
  "email_expiration_time": 600,
  "email_token_size": 6,
  "emergency_access_allowed": true,
  "emergency_notification_reminder_schedule": "0 3 * * * *",
  "emergency_request_timeout_schedule": "0 7 * * * *",
  "enable_db_wal": true,
  "enable_websocket": true,
  "enforce_single_org_with_reset_pw_policy": false,
  "event_cleanup_schedule": "0 10 0 * * *",
  "events_days_retain": null,
  "experimental_client_feature_flags": "ssh-key-vault-item,ssh-agent",
  "extended_logging": true,
  "helo_name": null,
  "hibp_api_key": "***",
  "http_request_block_non_global_ips": true,
  "http_request_block_regex": null,
  "icon_blacklist_non_global_ips": true,
  "icon_blacklist_regex": null,
  "icon_cache_folder": "data/icon_cache",
  "icon_cache_negttl": 259200,
  "icon_cache_ttl": 2592000,
  "icon_download_timeout": 10,
  "icon_redirect_code": 302,
  "icon_service": "internal",
  "incomplete_2fa_schedule": "30 * * * * *",
  "incomplete_2fa_time_limit": 3,
  "increase_note_size_limit": false,
  "invitation_expiration_hours": 120,
  "invitation_org_name": "Vaultwarden",
  "invitations_allowed": false,
  "ip_header": "X-Real-IP",
  "job_poll_interval_ms": 30000,
  "log_file": null,
  "log_level": "warn",
  "log_timestamp_format": "%Y-%m-%d %H:%M:%S.%3f",
  "login_ratelimit_max_burst": 10,
  "login_ratelimit_seconds": 60,
  "org_attachment_limit": null,
  "org_creation_users": "",
  "org_events_enabled": false,
  "org_groups_enabled": false,
  "password_hints_allowed": false,
  "password_iterations": 600000,
  "push_enabled": false,
  "push_identity_uri": "https://identity.bitwarden.com",
  "push_installation_id": "***",
  "push_installation_key": "***",
  "push_relay_uri": "https://push.bitwarden.com",
  "reload_templates": false,
  "require_device_email": false,
  "rsa_key_filename": "data/rsa_key",
  "send_purge_schedule": "0 5 * * * *",
  "sendmail_command": null,
  "sends_allowed": true,
  "sends_folder": "data/sends",
  "show_password_hint": false,
  "signups_allowed": false,
  "signups_domains_whitelist": "",
  "signups_verify": false,
  "signups_verify_resend_limit": 6,
  "signups_verify_resend_time": 3600,
  "smtp_accept_invalid_certs": false,
  "smtp_accept_invalid_hostnames": false,
  "smtp_auth_mechanism": null,
  "smtp_debug": false,
  "smtp_embed_images": true,
  "smtp_explicit_tls": null,
  "smtp_from": "*****************",
  "smtp_from_name": "Vaultwarden",
  "smtp_host": "********************",
  "smtp_password": "***",
  "smtp_port": 587,
  "smtp_security": "starttls",
  "smtp_ssl": null,
  "smtp_timeout": 15,
  "smtp_username": "*******",
  "templates_folder": "data/templates",
  "tmp_folder": "data/tmp",
  "trash_auto_delete_days": null,
  "trash_purge_schedule": "0 5 0 * * *",
  "use_sendmail": false,
  "use_syslog": false,
  "user_attachment_limit": null,
  "user_send_limit": null,
  "web_vault_enabled": true,
  "web_vault_folder": "web-vault/",
  "yubico_client_id": null,
  "yubico_secret_key": null,
  "yubico_server": null
}

Vaultwarden Build Version

v1.32.7

Deployment method

Official Container Image

Custom deployment method

No response

Reverse Proxy

nginx/1.27.2

Host/Server Operating System

Linux

Operating System Version

6.12.4-arch1-1 x86_64 GNU/Linux

Clients

Android

Client Version

Android Beta 2024.12.0 (19597)

Steps To Reproduce

  1. Sync the vault

Expected Result

Sync success

Actual Result

Sync failed

Logs

Bitwarden Android Beta: adb logcat log

The log reports Network Error: https://api.bitwarden.com/sync but I'm connecting to Vaultwarden so that can be ignored.

12-23 18:54:56.815 32448 14626 W NetworkResultCall: Network Error: https://api.bitwarden.com/sync
12-23 18:54:56.816 32448 14626 W NetworkResultCall: kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 719619: Expected string literal but 'null' literal was found at path: $.ciphers[234].sshKey.keyFingerprint
12-23 18:54:56.816 32448 14626 W NetworkResultCall: Use 'coerceInputValues = true' in 'Json {}' builder to coerce nulls if property has a default value.
12-23 18:54:56.816 32448 14626 W NetworkResultCall: JSON input: .....ll,"sshKey":{"keyFingerprint":null,"privateKey":null,"public.....
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:580)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.AbstractJsonLexer.unexpectedToken(AbstractJsonLexer.kt:221)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StringJsonLexer.consumeNextToken(StringJsonLexer.kt:76)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:88)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:365)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:339)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$SshKey$$serializer.deserialize(SyncResponseJson.kt:736)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$SshKey$$serializer.deserialize(SyncResponseJson.kt:736)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$$serializer.deserialize(SyncResponseJson.kt:430)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$$serializer.deserialize(SyncResponseJson.kt:430)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(StreamingJsonDecoder.kt:168)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.CompositeDecoder$DefaultImpls.decodeSerializableElement$default(Decoding.kt:538)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.internal.CollectionLikeSerializer.readElement(CollectionSerializers.kt:80)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$$serializer.deserialize(SyncResponseJson.kt:26)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$$serializer.deserialize(SyncResponseJson.kt:26)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:165)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at retrofit2.converter.kotlinx.serialization.Serializer$FromString.fromResponseBody(Serializer.kt:26)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:11)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:7)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:246)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:156)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
12-23 18:54:56.816 32448 14626 W NetworkResultCall: 	at java.lang.Thread.run(Thread.java:1012)

Screenshots or Videos

No response

Additional Context

Details

Bitwarden Android Beta requires ciphers.sshKey.keyFingerprint, but Vaultwarden's /api/sync does not return this property.

This bug does not occur if the SSH key is not in the vault.

Vaultwarden's SSH key feature works well with the Desktop client.

Originally created by @segln on GitHub (Dec 23, 2024). Original GitHub issue: https://github.com/dani-garcia/vaultwarden/issues/5322 ### Vaultwarden Support String ### Your environment (Generated via diagnostics page) EXPERIMENTAL_CLIENT_FEATURE_FLAGS=ssh-key-vault-item,ssh-agent * Vaultwarden version: v1.32.7 * Web-vault version: v2024.6.2c * OS/Arch: linux/x86_64 * Running within a container: true (Base: Debian) * Database type: PostgreSQL * Database version: PostgreSQL 16.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.2.1 20240805, 64-bit * Environment settings overridden!: true * Uses a reverse proxy: true * IP Header check: true (X-Real-IP) * Internet access: true * Internet access via a proxy: false * DNS Check: true * Browser/Server Time Check: true * Server/NTP Time Check: true * Domain Configuration Check: false * HTTPS Check: true * Websocket Check: true * HTTP Response Checks: true ### Config & Details (Generated via diagnostics page) <details><summary>Show Config & Details</summary> **Environment settings which are overridden:** ADMIN_TOKEN **Config:** ```json { "_duo_akey": null, "_enable_duo": false, "_enable_email_2fa": true, "_enable_smtp": true, "_enable_yubico": true, "_icon_service_csp": "", "_icon_service_url": "", "_ip_header_enabled": true, "_max_note_size": 10000, "_smtp_img_src": "***:", "admin_ratelimit_max_burst": 3, "admin_ratelimit_seconds": 300, "admin_session_lifetime": 20, "admin_token": "***", "allowed_connect_src": "", "allowed_iframe_ancestors": "", "attachments_folder": "data/attachments", "auth_request_purge_schedule": "30 * * * * *", "authenticator_disable_time_drift": false, "data_folder": "data", "database_conn_init": "", "database_max_conns": 10, "database_timeout": 30, "database_url": "**********://********************,*********************************", "db_connection_retries": 15, "disable_2fa_remember": false, "disable_admin_token": false, "disable_icon_download": false, "domain": "*****://***************************", "domain_origin": "*****://***************************", "domain_path": "", "domain_set": true, "duo_context_purge_schedule": "30 * * * * *", "duo_host": null, "duo_ikey": null, "duo_skey": null, "duo_use_iframe": false, "email_2fa_auto_fallback": false, "email_2fa_enforce_on_verified_invite": false, "email_attempts_limit": 3, "email_change_allowed": true, "email_expiration_time": 600, "email_token_size": 6, "emergency_access_allowed": true, "emergency_notification_reminder_schedule": "0 3 * * * *", "emergency_request_timeout_schedule": "0 7 * * * *", "enable_db_wal": true, "enable_websocket": true, "enforce_single_org_with_reset_pw_policy": false, "event_cleanup_schedule": "0 10 0 * * *", "events_days_retain": null, "experimental_client_feature_flags": "ssh-key-vault-item,ssh-agent", "extended_logging": true, "helo_name": null, "hibp_api_key": "***", "http_request_block_non_global_ips": true, "http_request_block_regex": null, "icon_blacklist_non_global_ips": true, "icon_blacklist_regex": null, "icon_cache_folder": "data/icon_cache", "icon_cache_negttl": 259200, "icon_cache_ttl": 2592000, "icon_download_timeout": 10, "icon_redirect_code": 302, "icon_service": "internal", "incomplete_2fa_schedule": "30 * * * * *", "incomplete_2fa_time_limit": 3, "increase_note_size_limit": false, "invitation_expiration_hours": 120, "invitation_org_name": "Vaultwarden", "invitations_allowed": false, "ip_header": "X-Real-IP", "job_poll_interval_ms": 30000, "log_file": null, "log_level": "warn", "log_timestamp_format": "%Y-%m-%d %H:%M:%S.%3f", "login_ratelimit_max_burst": 10, "login_ratelimit_seconds": 60, "org_attachment_limit": null, "org_creation_users": "", "org_events_enabled": false, "org_groups_enabled": false, "password_hints_allowed": false, "password_iterations": 600000, "push_enabled": false, "push_identity_uri": "https://identity.bitwarden.com", "push_installation_id": "***", "push_installation_key": "***", "push_relay_uri": "https://push.bitwarden.com", "reload_templates": false, "require_device_email": false, "rsa_key_filename": "data/rsa_key", "send_purge_schedule": "0 5 * * * *", "sendmail_command": null, "sends_allowed": true, "sends_folder": "data/sends", "show_password_hint": false, "signups_allowed": false, "signups_domains_whitelist": "", "signups_verify": false, "signups_verify_resend_limit": 6, "signups_verify_resend_time": 3600, "smtp_accept_invalid_certs": false, "smtp_accept_invalid_hostnames": false, "smtp_auth_mechanism": null, "smtp_debug": false, "smtp_embed_images": true, "smtp_explicit_tls": null, "smtp_from": "*****************", "smtp_from_name": "Vaultwarden", "smtp_host": "********************", "smtp_password": "***", "smtp_port": 587, "smtp_security": "starttls", "smtp_ssl": null, "smtp_timeout": 15, "smtp_username": "*******", "templates_folder": "data/templates", "tmp_folder": "data/tmp", "trash_auto_delete_days": null, "trash_purge_schedule": "0 5 0 * * *", "use_sendmail": false, "use_syslog": false, "user_attachment_limit": null, "user_send_limit": null, "web_vault_enabled": true, "web_vault_folder": "web-vault/", "yubico_client_id": null, "yubico_secret_key": null, "yubico_server": null } ``` </details> ### Vaultwarden Build Version v1.32.7 ### Deployment method Official Container Image ### Custom deployment method _No response_ ### Reverse Proxy nginx/1.27.2 ### Host/Server Operating System Linux ### Operating System Version 6.12.4-arch1-1 x86_64 GNU/Linux ### Clients Android ### Client Version Android Beta 2024.12.0 (19597) ### Steps To Reproduce 1. Sync the vault ### Expected Result Sync success ### Actual Result Sync failed ### Logs #### Bitwarden Android Beta: `adb logcat` log The log reports `Network Error: https://api.bitwarden.com/sync` but I'm connecting to Vaultwarden so that can be ignored. <details> ``` 12-23 18:54:56.815 32448 14626 W NetworkResultCall: Network Error: https://api.bitwarden.com/sync 12-23 18:54:56.816 32448 14626 W NetworkResultCall: kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 719619: Expected string literal but 'null' literal was found at path: $.ciphers[234].sshKey.keyFingerprint 12-23 18:54:56.816 32448 14626 W NetworkResultCall: Use 'coerceInputValues = true' in 'Json {}' builder to coerce nulls if property has a default value. 12-23 18:54:56.816 32448 14626 W NetworkResultCall: JSON input: .....ll,"sshKey":{"keyFingerprint":null,"privateKey":null,"public..... 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:580) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.AbstractJsonLexer.unexpectedToken(AbstractJsonLexer.kt:221) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StringJsonLexer.consumeNextToken(StringJsonLexer.kt:76) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:88) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:365) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:339) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$SshKey$$serializer.deserialize(SyncResponseJson.kt:736) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$SshKey$$serializer.deserialize(SyncResponseJson.kt:736) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$$serializer.deserialize(SyncResponseJson.kt:430) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$Cipher$$serializer.deserialize(SyncResponseJson.kt:430) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(StreamingJsonDecoder.kt:168) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.CompositeDecoder$DefaultImpls.decodeSerializableElement$default(Decoding.kt:538) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.internal.CollectionLikeSerializer.readElement(CollectionSerializers.kt:80) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$$serializer.deserialize(SyncResponseJson.kt:26) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson$$serializer.deserialize(SyncResponseJson.kt:26) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at kotlinx.serialization.json.Json.decodeFromString(Json.kt:165) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at retrofit2.converter.kotlinx.serialization.Serializer$FromString.fromResponseBody(Serializer.kt:26) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:11) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:7) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:246) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:156) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) 12-23 18:54:56.816 32448 14626 W NetworkResultCall: at java.lang.Thread.run(Thread.java:1012) ``` </details> ### Screenshots or Videos _No response_ ### Additional Context ### Details Bitwarden Android Beta requires `ciphers.sshKey.keyFingerprint`, but Vaultwarden's `/api/sync` does not return this property. This bug does not occur if the SSH key is not in the vault. Vaultwarden's SSH key feature works well with the Desktop client.
GiteaMirror added the bug label 2026-07-17 14:03:52 -05:00
Author
Owner

@BlackDex commented on GitHub (Dec 23, 2024):

Vaultwarden doesn't have anything special for this except that it returns the json blob exactly as received. It probably means the stored data is not valid i think. But i haven't checked it.

Does the fingerprint show in the desktop client?

<!-- gh-comment-id:2559407347 --> @BlackDex commented on GitHub (Dec 23, 2024): Vaultwarden doesn't have anything special for this except that it returns the json blob exactly as received. It probably means the stored data is not valid i think. But i haven't checked it. Does the fingerprint show in the desktop client?
Author
Owner

@segln commented on GitHub (Dec 23, 2024):

Yes, on desktop client with Linux and Windows SSH key features (add, list, edit, etc...) works well.

<!-- gh-comment-id:2559409799 --> @segln commented on GitHub (Dec 23, 2024): Yes, on desktop client with Linux and Windows SSH key features (add, list, edit, etc...) works well.
Author
Owner

@BlackDex commented on GitHub (Dec 23, 2024):

Could you check the database for this specific key and what is in the data column?

<!-- gh-comment-id:2559410038 --> @BlackDex commented on GitHub (Dec 23, 2024): Could you check the database for this specific key and what is in the data column?
Author
Owner

@segln commented on GitHub (Dec 23, 2024):

Here is the data for the SSH key row.

INSERT INTO "ciphers" ("uuid", "created_at", "updated_at", "user_uuid", "organization_uuid", "atype", "name", "notes", "fields", "data", "password_history", "deleted_at", "reprompt", "key") VALUES
('065d4800-610f-48a9-958d-6ba584489ddf',	'2024-12-23 10:16:13.321893',	'2024-12-23 10:16:13.325395',	'ef669930-9712-4522-95b6-b7dc72c1ae8a',	NULL,	5,	'2.SmP/Qsnb3g+SYNH3tiJLRA==|2H/qXArvh7UuD7OyyVzqeA==|/BTVGv4O4xCbpleOhh1P3x9LYFa1YAGiGkibcaCAkx4=',	NULL,	NULL,	'{"keyFingerprint":"2.TTuJoqtXsm6ATGoog3LHrA==|58fTr0btpcL6qrwLHJQsXyHSRqsmOESGuuWm3QwTgMOXXh76+fw0Z+8uDVta7eSnXHdNOQVcM8lEJ75LPY4qlw==|kXXFZo56gVRc3yJW5J+QebNSRTncr6Wehc/rprDg57k=","privateKey":"2.L+x00lseczoU+vK395tESQ==|ZlsXRL3+6UBwxrHgzJCPp5YRQKlu4XI1oX8uhZO+/8V0sxgPtREyPpfTMujLcnzfhtGaF3I++S+NTGP9vlom4EXM7SQTJDfRTs1tpBEVSciruT334w7FBHfEq1AytHa+P/UlrhTo5lIY7jvag4HvnwdUPt+Yar9ERjEdkSdJZ/VaD3D+Bul0o5ESotehLX3gcn0Tz4sCTZtY8IJ4xe4oOezNxVibVYk+lHvOVxrtsICY2qDHpNXM9McQfWGzgBXfy56Yg+jxdNJLOHvLZZjZ2YdqZJZoCRb9DMs7wQW28Why6NbEtKnU/N9FJGTAVaC2vTZIXaHRnx5AQ7wTka2rn7jPndoRL2M3qPFUPC4Qs7UK7C7bu5mIM6nwCgPwAPSB/V48iIXcWEXYhRGiaAJMKQ5tolD1z/XqZnZgW1dJVwNcTseYYIlu6v3xn3za0yBmdJ5q8awYzokyf3hk7No1ukayo9f1WDODIVA6fx5BJYIy8NErH6nhISKvW8+6yVpJ2HZpyyxVdE4TcMhz40tOMA==|bzgdJAn0pPbWVEvK9k8jUuJKPrizaW/ILCjCbSGezgE=","publicKey":"2.Va0MLFITWE64r4m9Ao/YFA==|VMrFscfr/v+SLkSv4cbYbOR8UxODO6UkpL8t+7eiH2EMUvye6XchBFwMSsAwbiF+ZeWL1fpTiDZ4gIV5R86rY8vtkuDgl3tnZukO48EBhlhim/dxeGLh2CWZ7pR5YDbN|f9QsxBJI24jZIvs7cgiHM6MkBEq0UygY3JJMpBDZ+9k="}',	NULL,	NULL,	0,	NULL);
<!-- gh-comment-id:2559425621 --> @segln commented on GitHub (Dec 23, 2024): Here is the data for the SSH key row. ``` INSERT INTO "ciphers" ("uuid", "created_at", "updated_at", "user_uuid", "organization_uuid", "atype", "name", "notes", "fields", "data", "password_history", "deleted_at", "reprompt", "key") VALUES ('065d4800-610f-48a9-958d-6ba584489ddf', '2024-12-23 10:16:13.321893', '2024-12-23 10:16:13.325395', 'ef669930-9712-4522-95b6-b7dc72c1ae8a', NULL, 5, '2.SmP/Qsnb3g+SYNH3tiJLRA==|2H/qXArvh7UuD7OyyVzqeA==|/BTVGv4O4xCbpleOhh1P3x9LYFa1YAGiGkibcaCAkx4=', NULL, NULL, '{"keyFingerprint":"2.TTuJoqtXsm6ATGoog3LHrA==|58fTr0btpcL6qrwLHJQsXyHSRqsmOESGuuWm3QwTgMOXXh76+fw0Z+8uDVta7eSnXHdNOQVcM8lEJ75LPY4qlw==|kXXFZo56gVRc3yJW5J+QebNSRTncr6Wehc/rprDg57k=","privateKey":"2.L+x00lseczoU+vK395tESQ==|ZlsXRL3+6UBwxrHgzJCPp5YRQKlu4XI1oX8uhZO+/8V0sxgPtREyPpfTMujLcnzfhtGaF3I++S+NTGP9vlom4EXM7SQTJDfRTs1tpBEVSciruT334w7FBHfEq1AytHa+P/UlrhTo5lIY7jvag4HvnwdUPt+Yar9ERjEdkSdJZ/VaD3D+Bul0o5ESotehLX3gcn0Tz4sCTZtY8IJ4xe4oOezNxVibVYk+lHvOVxrtsICY2qDHpNXM9McQfWGzgBXfy56Yg+jxdNJLOHvLZZjZ2YdqZJZoCRb9DMs7wQW28Why6NbEtKnU/N9FJGTAVaC2vTZIXaHRnx5AQ7wTka2rn7jPndoRL2M3qPFUPC4Qs7UK7C7bu5mIM6nwCgPwAPSB/V48iIXcWEXYhRGiaAJMKQ5tolD1z/XqZnZgW1dJVwNcTseYYIlu6v3xn3za0yBmdJ5q8awYzokyf3hk7No1ukayo9f1WDODIVA6fx5BJYIy8NErH6nhISKvW8+6yVpJ2HZpyyxVdE4TcMhz40tOMA==|bzgdJAn0pPbWVEvK9k8jUuJKPrizaW/ILCjCbSGezgE=","publicKey":"2.Va0MLFITWE64r4m9Ao/YFA==|VMrFscfr/v+SLkSv4cbYbOR8UxODO6UkpL8t+7eiH2EMUvye6XchBFwMSsAwbiF+ZeWL1fpTiDZ4gIV5R86rY8vtkuDgl3tnZukO48EBhlhim/dxeGLh2CWZ7pR5YDbN|f9QsxBJI24jZIvs7cgiHM6MkBEq0UygY3JJMpBDZ+9k="}', NULL, NULL, 0, NULL); ```
Author
Owner

@BlackDex commented on GitHub (Dec 23, 2024):

Not sure how your export was done because of the double "", but it sure looks like the data is there.

Ill have to check my self how this is returned to the client then.
But as you can see here it should return this as-is.
https://github.com/dani-garcia/vaultwarden/blob/ed4ad67e732c213beaec78970cdb68e48bee3dc1/src/db/models/cipher.rs#L346...L356

<!-- gh-comment-id:2559446645 --> @BlackDex commented on GitHub (Dec 23, 2024): Not sure how your export was done because of the double `""`, but it sure looks like the data is there. Ill have to check my self how this is returned to the client then. But as you can see here it should return this as-is. https://github.com/dani-garcia/vaultwarden/blob/ed4ad67e732c213beaec78970cdb68e48bee3dc1/src/db/models/cipher.rs#L346...L356
Author
Owner

@segln commented on GitHub (Dec 23, 2024):

I've corrected it by changing the export format.
And yes, the data exists. I've reinstalled the Android Bitwarden Beta app multiple times and tried on different devices, but it's still the same. I'm not sure what the problem is.

<!-- gh-comment-id:2559453582 --> @segln commented on GitHub (Dec 23, 2024): I've corrected it by changing the export format. And yes, the data exists. I've reinstalled the Android Bitwarden Beta app multiple times and tried on different devices, but it's still the same. I'm not sure what the problem is.
Author
Owner

@BlackDex commented on GitHub (Dec 23, 2024):

You could try to install the dev version of the Android client which should output the request and response data of the http call. Which in turn should show if the data is there or not.

<!-- gh-comment-id:2559460170 --> @BlackDex commented on GitHub (Dec 23, 2024): You could try to install the dev version of the Android client which should output the request and response data of the http call. Which in turn should show if the data is there or not.
Author
Owner

@segln commented on GitHub (Dec 23, 2024):

I completely wiped all SSH key rows from the database and reimported keys, and the symptoms disappeared.
I'm still not sure why the error occurred. For now, the problem has been resolved.

<!-- gh-comment-id:2559936181 --> @segln commented on GitHub (Dec 23, 2024): I completely wiped all SSH key rows from the database and reimported keys, and the symptoms disappeared. I'm still not sure why the error occurred. For now, the problem has been resolved.
Author
Owner

@Dubzer commented on GitHub (Jan 3, 2025):

hi there. I'm having the same problem and I've found the cause of it

here's a log from the app:

 W  kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 415049: Expected string literal but 'null' literal was found at path: $.ciphers[180].sshKey.keyFingerprint
 W  Use 'coerceInputValues = true' in 'Json {}' builder to coerce nulls if property has a default value.
 W  JSON input: .....ll,"sshKey":{"keyFingerprint":null,"privateKey":null,"public.....

turns out that keyFingerprint is null for an SSH key that I don't even have... or so I thought, until I looked in the Trash from the browser extension and there were some keys with no fields other than the name!
I'm not sure when these keys were created. maybe there was a bug in some client that was fixed. or in the SSH agent

either way, I don't think it makes sense for the backend to allow such keys, since clients will reject anything that appears to be an invalid key

@BlackDex

<!-- gh-comment-id:2569641695 --> @Dubzer commented on GitHub (Jan 3, 2025): hi there. I'm having the same problem and I've found the cause of it here's a log from the app: ``` W kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 415049: Expected string literal but 'null' literal was found at path: $.ciphers[180].sshKey.keyFingerprint W Use 'coerceInputValues = true' in 'Json {}' builder to coerce nulls if property has a default value. W JSON input: .....ll,"sshKey":{"keyFingerprint":null,"privateKey":null,"public..... ``` turns out that `keyFingerprint` is null for an SSH key that I don't even have... or so I thought, until I looked in the Trash from the browser extension and there were some keys with no fields other than the name! I'm not sure when these keys were created. maybe there was a bug in some client that was fixed. or in the SSH agent either way, I don't think it makes sense for the backend to allow such keys, since clients will reject anything that appears to be an invalid key @BlackDex
Author
Owner

@BlackDex commented on GitHub (Jan 3, 2025):

The problem is, that we actually do not care what the data object is and how this is formed.
It does manifest these kind of issue unfortunately though.

The main reason for us to not care on what the clients are sending as data blob, is that new features or additions which are done via that data blob will just work out-of-the-box, without us having to update it every time.

It has the downside of these kind of issue. What we currently do is fix the output of the sync.
But, we have not yet done this for invalid ssh-keys, so those could cause an issue it seems.

But, yes this is because of the clients not sending the correct data back to the server, and could be a faulty client indeed.

<!-- gh-comment-id:2569652831 --> @BlackDex commented on GitHub (Jan 3, 2025): The problem is, that we actually do not care what the data object is and how this is formed. It does manifest these kind of issue unfortunately though. The main reason for us to not care on what the clients are sending as data blob, is that new features or additions which are done via that data blob will just work out-of-the-box, without us having to update it every time. It has the downside of these kind of issue. What we currently do is fix the output of the sync. But, we have not yet done this for invalid ssh-keys, so those could cause an issue it seems. But, yes this is because of the clients not sending the correct data back to the server, and could be a faulty client indeed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/vaultwarden#39363