Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Insecure Object Serialization #456

Merged
merged 3 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Release Notes

## 10.3.1

* Fix insecure object serialization on fragments

## 10.3.0

* Changed initialize() to return a deferred result (allow partners to handle errors)
* Changed `initialize()` to return a deferred result (allow partners to handle errors)
* Update to Compose Fragment and remove ComposeView

## 10.2.7
Expand Down
2 changes: 2 additions & 0 deletions lib/src/main/java/com/smileidentity/SmileID.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.smileidentity.models.UploadRequest
import com.smileidentity.networking.BiometricKycJobResultAdapter
import com.smileidentity.networking.DocumentVerificationJobResultAdapter
import com.smileidentity.networking.EnhancedDocumentVerificationJobResultAdapter
import com.smileidentity.networking.FileAdapter
import com.smileidentity.networking.FileNameAdapter
import com.smileidentity.networking.GzipRequestInterceptor
import com.smileidentity.networking.JobResultAdapter
Expand Down Expand Up @@ -496,6 +497,7 @@ object SmileID {
.add(StringifiedBooleanAdapter)
.add(MetadataAdapter)
.add(FileNameAdapter)
.add(FileAdapter)
.add(SmartSelfieJobResultAdapter)
.add(DocumentVerificationJobResultAdapter)
.add(BiometricKycJobResultAdapter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import com.smileidentity.models.IdInfo
import com.smileidentity.results.BiometricKycResult
import com.smileidentity.results.SmileIDResult
import com.smileidentity.util.getParcelableCompat
import com.smileidentity.util.getSerializableCompat
import com.smileidentity.util.randomJobId
import com.smileidentity.util.randomUserId
import com.squareup.moshi.Types
import kotlinx.collections.immutable.toImmutableMap

/**
Expand Down Expand Up @@ -125,6 +125,8 @@ class BiometricKYCFragment : Fragment() {
}
}

private val moshi = SmileID.moshi

private const val KEY_ID_INFO = "idInfo"
private var Bundle.idInfo: IdInfo
get() = getParcelableCompat(KEY_ID_INFO)!!
Expand Down Expand Up @@ -161,9 +163,15 @@ private var Bundle.showInstructions: Boolean
set(value) = putBoolean(KEY_SHOW_INSTRUCTIONS, value)

private const val KEY_EXTRA_PARTNER_PARAMS = "extraPartnerParams"
private var Bundle.extraPartnerParams: HashMap<String, String>?
get() = getSerializableCompat(KEY_EXTRA_PARTNER_PARAMS)
set(value) = putSerializable(KEY_EXTRA_PARTNER_PARAMS, value)
private val type = Types.newParameterizedType(
Map::class.java,
String::class.java,
String::class.java,
)
private val adapter = moshi.adapter<Map<String, String>>(type)
private var Bundle.extraPartnerParams: Map<String, String>?
get() = getString(KEY_EXTRA_PARTNER_PARAMS)?.let { adapter.fromJson(it) }
set(value) = putString(KEY_EXTRA_PARTNER_PARAMS, value?.let { adapter.toJson(it) })

private var Bundle.smileIDResult: SmileIDResult<BiometricKycResult>
get() = getParcelableCompat(KEY_RESULT)!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import com.smileidentity.fragment.SmartSelfieEnrollmentFragment.Companion.result
import com.smileidentity.results.DocumentVerificationResult
import com.smileidentity.results.SmileIDResult
import com.smileidentity.util.getParcelableCompat
import com.smileidentity.util.getSerializableCompat
import com.smileidentity.util.randomJobId
import com.smileidentity.util.randomUserId
import com.squareup.moshi.Types
import java.io.File
import kotlinx.collections.immutable.toImmutableMap

Expand Down Expand Up @@ -138,6 +138,8 @@ class DocumentVerificationFragment : Fragment() {
}
}

private val moshi = SmileID.moshi

private const val KEY_USER_ID = "userId"
private var Bundle.userId: String
get() = getString(KEY_USER_ID)!!
Expand Down Expand Up @@ -197,14 +199,21 @@ private var Bundle.captureBothSides: Boolean
set(value) = putBoolean(KEY_CAPTURE_BOTH_SIDES, value)

private const val KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE = "bypassSelfieCaptureWithFile"
private val fileAdapter = moshi.adapter(File::class.java)
private var Bundle.bypassSelfieCaptureWithFile: File?
get() = getSerializableCompat(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE) as File?
set(value) = putSerializable(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE, value)
get() = getString(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE)?.let { fileAdapter.fromJson(it) }
set(value) = putString(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE, fileAdapter.toJson(value))

private const val KEY_EXTRA_PARTNER_PARAMS = "extraPartnerParams"
private var Bundle.extraPartnerParams: HashMap<String, String>?
get() = getSerializableCompat(KEY_EXTRA_PARTNER_PARAMS)
set(value) = putSerializable(KEY_EXTRA_PARTNER_PARAMS, value)
private val type = Types.newParameterizedType(
Map::class.java,
String::class.java,
String::class.java,
)
private val adapter = moshi.adapter<Map<String, String>>(type)
private var Bundle.extraPartnerParams: Map<String, String>?
get() = getString(KEY_EXTRA_PARTNER_PARAMS)?.let { adapter.fromJson(it) }
set(value) = putString(KEY_EXTRA_PARTNER_PARAMS, value?.let { adapter.toJson(it) })

private var Bundle.smileIDResult: SmileIDResult<DocumentVerificationResult>
get() = getParcelableCompat(KEY_RESULT)!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import com.smileidentity.fragment.SmartSelfieEnrollmentFragment.Companion.result
import com.smileidentity.results.EnhancedDocumentVerificationResult
import com.smileidentity.results.SmileIDResult
import com.smileidentity.util.getParcelableCompat
import com.smileidentity.util.getSerializableCompat
import com.smileidentity.util.randomJobId
import com.smileidentity.util.randomUserId
import com.squareup.moshi.Types
import java.io.File
import kotlinx.collections.immutable.toImmutableMap

Expand Down Expand Up @@ -136,6 +136,8 @@ class EnhancedDocumentVerificationFragment : Fragment() {
}
}

private val moshi = SmileID.moshi

private const val KEY_USER_ID = "userId"
private var Bundle.userId: String
get() = getString(KEY_USER_ID)!!
Expand Down Expand Up @@ -190,9 +192,10 @@ private var Bundle.idAspectRatio: Float
set(value) = putFloat(KEY_ID_ASPECT_RATIO, value)

private const val KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE = "bypassSelfieCaptureWithFile"
private val fileAdapter = moshi.adapter(File::class.java)
private var Bundle.bypassSelfieCaptureWithFile: File?
get() = getSerializableCompat(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE) as File?
set(value) = putSerializable(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE, value)
get() = getString(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE)?.let { fileAdapter.fromJson(it) }
set(value) = putString(KEY_BYPASS_SELFIE_CAPTURE_WITH_FILE, fileAdapter.toJson(value))

private const val KEY_CAPTURE_BOTH_SIDES = "captureBothSides"

Expand All @@ -201,9 +204,15 @@ private var Bundle.captureBothSides: Boolean
set(value) = putBoolean(KEY_CAPTURE_BOTH_SIDES, value)

private const val KEY_EXTRA_PARTNER_PARAMS = "extraPartnerParams"
private var Bundle.extraPartnerParams: HashMap<String, String>?
get() = getSerializableCompat(KEY_EXTRA_PARTNER_PARAMS)
set(value) = putSerializable(KEY_EXTRA_PARTNER_PARAMS, value)
private val type = Types.newParameterizedType(
Map::class.java,
String::class.java,
String::class.java,
)
private val adapter = moshi.adapter<Map<String, String>>(type)
private var Bundle.extraPartnerParams: Map<String, String>?
get() = getString(KEY_EXTRA_PARTNER_PARAMS)?.let { adapter.fromJson(it) }
set(value) = putString(KEY_EXTRA_PARTNER_PARAMS, value?.let { adapter.toJson(it) })

private var Bundle.smileIDResult: SmileIDResult<EnhancedDocumentVerificationResult>
get() = getParcelableCompat(DocumentVerificationFragment.KEY_RESULT)!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import com.smileidentity.fragment.SmartSelfieEnrollmentFragment.Companion.result
import com.smileidentity.results.SmartSelfieResult
import com.smileidentity.results.SmileIDResult
import com.smileidentity.util.getParcelableCompat
import com.smileidentity.util.getSerializableCompat
import com.smileidentity.util.randomJobId
import com.smileidentity.util.randomUserId
import com.squareup.moshi.Types
import kotlinx.collections.immutable.toImmutableMap

/**
Expand Down Expand Up @@ -131,6 +131,8 @@ class SmartSelfieAuthenticationFragment : Fragment() {
}
}

private val moshi = SmileID.moshi

private const val KEY_ALLOW_AGENT_MODE = "allowAgentMode"
private var Bundle.allowAgentMode: Boolean
get() = getBoolean(KEY_ALLOW_AGENT_MODE)
Expand Down Expand Up @@ -162,9 +164,15 @@ private var Bundle.showInstructions: Boolean
set(value) = putBoolean(KEY_SHOW_INSTRUCTIONS, value)

private const val KEY_EXTRA_PARTNER_PARAMS = "extraPartnerParams"
private var Bundle.extraPartnerParams: HashMap<String, String>?
get() = getSerializableCompat(KEY_EXTRA_PARTNER_PARAMS)
set(value) = putSerializable(KEY_EXTRA_PARTNER_PARAMS, value)
private val type = Types.newParameterizedType(
Map::class.java,
String::class.java,
String::class.java,
)
private val adapter = moshi.adapter<Map<String, String>>(type)
private var Bundle.extraPartnerParams: Map<String, String>?
get() = getString(KEY_EXTRA_PARTNER_PARAMS)?.let { adapter.fromJson(it) }
set(value) = putString(KEY_EXTRA_PARTNER_PARAMS, value?.let { adapter.toJson(it) })

private var Bundle.smileIdResult: SmileIDResult<SmartSelfieResult>
get() = getParcelableCompat(KEY_RESULT)!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import com.smileidentity.fragment.SmartSelfieEnrollmentFragment.Companion.result
import com.smileidentity.results.SmartSelfieResult
import com.smileidentity.results.SmileIDResult
import com.smileidentity.util.getParcelableCompat
import com.smileidentity.util.getSerializableCompat
import com.smileidentity.util.randomJobId
import com.smileidentity.util.randomUserId
import com.squareup.moshi.Types
import kotlinx.collections.immutable.toImmutableMap

/**
Expand Down Expand Up @@ -128,6 +128,8 @@ class SmartSelfieEnrollmentFragment : Fragment() {
}
}

private val moshi = SmileID.moshi

private const val KEY_ALLOW_AGENT_MODE = "allowAgentMode"
private var Bundle.allowAgentMode: Boolean
get() = getBoolean(KEY_ALLOW_AGENT_MODE)
Expand Down Expand Up @@ -159,9 +161,12 @@ private var Bundle.showInstructions: Boolean
set(value) = putBoolean(KEY_SHOW_INSTRUCTIONS, value)

private const val KEY_EXTRA_PARTNER_PARAMS = "extraPartnerParams"
private var Bundle.extraPartnerParams: HashMap<String, String>?
get() = getSerializableCompat(KEY_EXTRA_PARTNER_PARAMS)
set(value) = putSerializable(KEY_EXTRA_PARTNER_PARAMS, value)
private val type =
Types.newParameterizedType(Map::class.java, String::class.java, String::class.java)
private val adapter = moshi.adapter<Map<String, String>>(type)
private var Bundle.extraPartnerParams: Map<String, String>?
get() = getString(KEY_EXTRA_PARTNER_PARAMS)?.let { adapter.fromJson(it) }
set(value) = putString(KEY_EXTRA_PARTNER_PARAMS, value?.let { adapter.toJson(it) })

private var Bundle.smileIdResult: SmileIDResult<SmartSelfieResult>
get() = getParcelableCompat(KEY_RESULT)!!
Expand Down
9 changes: 9 additions & 0 deletions lib/src/main/java/com/smileidentity/networking/Retrofit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ object FileNameAdapter {
fun fromJson(fileName: String): File = File(fileName)
}

@Suppress("unused")
object FileAdapter {
@ToJson
fun toJson(file: File): String = file.absolutePath

@FromJson
fun fromJson(path: String): File = File(path)
}

@Suppress("unused")
object JobResultAdapter {
@FromJson
Expand Down