Mitigation Strategy: Explicit Encryption of Persisted State (MvRx-Specific)
Description:
- Identify MvRx State: Analyze all classes extending
MvRxState
and identify fields containing sensitive data. - Encryption Key Management: Use the Android Keystore System for secure key generation and storage (symmetric encryption, e.g., AES). Do not hardcode keys.
- Override
persistState
Handling: The core MvRx-specific step. Instead of directly using the defaultpersistState
behavior (which likely usesSharedPreferences
or similar), you must intercept the persistence process. This is best done by:- Creating a custom base
MvRxViewModel
class that all your ViewModels inherit from. - Overriding the mechanism MvRx uses to persist state. This might involve providing a custom implementation of the persistence logic, or wrapping the existing mechanism. The goal is to inject encryption before the data reaches the underlying storage.
- Within this overridden mechanism, encrypt sensitive fields before they are passed to the underlying persistence layer (e.g.,
SharedPreferences
). - Similarly, decrypt the fields after they are retrieved from the underlying persistence layer, but before they are used to populate the
MvRxState
.
- Creating a custom base
- Key Rotation: Implement a mechanism for key rotation.
- Transparent Handling: The encryption/decryption should be transparent to the individual
MvRxViewModel
implementations. They should interact with the state as usual, without needing to be aware of the encryption.
-
Threats Mitigated:
- Improper State Persistence and Exposure (Severity: High): Directly addresses the risk of sensitive data in MvRx's
persistState
being exposed. - Unintentional State Exposure via Logging (Severity: Medium): Indirectly mitigates this, as the persisted (and potentially logged) data is encrypted.
- Improper State Persistence and Exposure (Severity: High): Directly addresses the risk of sensitive data in MvRx's
-
Impact:
- Improper State Persistence and Exposure: Reduces risk from High to Low.
- Unintentional State Exposure via Logging: Reduces risk from Medium to Low.
-
Currently Implemented:
- Example: A custom base
MvRxViewModel
(SecureMvRxViewModel
) overrides the persistence logic to encrypt/decrypt specific fields annotated with@Sensitive
.
- Example: A custom base
-
Missing Implementation:
- Example: Not all ViewModels inherit from
SecureMvRxViewModel
. - Example: Key rotation is not yet implemented.
- Example: Not all ViewModels inherit from
Mitigation Strategy: State Sanitization for Logging (MvRx-Specific)
Description:
- Identify
MvRxState
Classes: Focus on classes extendingMvRxState
. - Create
toSafeString()
in Base Class: Add atoSafeString()
method to a custom baseMvRxState
class (or interface) that all your state classes inherit from. This method should:- Return a string representation of the state.
- Redact or omit sensitive fields.
- Provide a default implementation that can be overridden by subclasses.
- Override
toSafeString()
: In each specificMvRxState
subclass, overridetoSafeString()
to provide a tailored, safe representation of that state. - Integrate with MvRx Logging: The crucial MvRx-specific part. You need to ensure that MvRx's internal logging (when
debugMode
is enabled) uses yourtoSafeString()
method. This likely requires:- Examining the MvRx source code to understand how it logs state.
- Potentially creating a custom
MvRxViewModel
base class that overrides the logging behavior. - Within the overridden logging, call
toSafeString()
on the state object before it's passed to the logging framework.
- Disable
debugMode
in Production: EnsureMvRxViewModel.debugMode
is always false in production builds.
-
Threats Mitigated:
- Unintentional State Exposure via Logging (Severity: Medium): Specifically targets MvRx's state logging.
-
Impact:
- Unintentional State Exposure via Logging: Reduces risk from Medium to Low.
-
Currently Implemented:
- Example: A base
SafeMvRxState
interface definestoSafeString()
. - Example:
debugMode
is disabled in production builds.
- Example: A base
-
Missing Implementation:
- Example: Not all
MvRxState
classes implementtoSafeString()
correctly. - Example: The custom
MvRxViewModel
to integratetoSafeString()
with MvRx's logging is not yet implemented.
- Example: Not all
Mitigation Strategy: Correct Usage of withState
and setState
(MvRx-Specific)
Description:
- Code Review (MvRx Focus): Review all classes extending
MvRxViewModel
, paying specific attention to how the MvRx state is accessed and modified. - Enforce
withState
: Every read and modification of the state within RxJava streams must use thewithState
operator. This is a fundamental rule of MvRx. - Enforce
setState
: Every state update, regardless of whether it's inside an RxJava stream or not, must use thesetState
method provided byMvRxViewModel
. Direct modification of the state object is prohibited. - Training (MvRx Focus): Train developers specifically on the correct usage of
withState
andsetState
within the context of MvRx. Emphasize the importance of these methods for thread safety and state consistency. - Static Analysis (Optional): Explore the possibility of using static analysis tools (e.g., custom lint rules) to automatically detect violations of the
withState
andsetState
rules.
-
Threats Mitigated:
- Race Conditions in Async Operations (Severity: Medium): Directly addresses race conditions caused by improper state access within MvRx.
-
Impact:
- Race Conditions in Async Operations: Reduces risk from Medium to Low.
-
Currently Implemented:
- Example: Most ViewModels follow the
withState
andsetState
rules.
- Example: Most ViewModels follow the
-
Missing Implementation:
- Example: A recent code review specifically focused on
withState
andsetState
has not been conducted. - Example: Static analysis rules to enforce these rules are not in place.
- Example: A recent code review specifically focused on
Mitigation Strategy: Comprehensive Error Handling in RxJava Streams (MvRx-Specific)
Description:
- Identify MvRx ViewModels: Focus on classes extending
MvRxViewModel
. - RxJava Streams within ViewModels: Identify all RxJava streams within these ViewModels. These are the streams that interact with the MvRx state.
onError
Handlers (MvRx Context): ImplementonError
handlers for all RxJava subscriptions within the ViewModels. These handlers must:- Log the error (using the sanitized logging approach from the previous strategy).
- Use
setState
to update the MvRx state to a safe and consistent state. This is the crucial MvRx-specific part. The error handler must interact with the MvRx state management system. - Consider retrying (using
retry
orretryWhen
) if appropriate for the specific operation and state.
onErrorReturn
/onErrorResumeNext
(MvRx Context): Use these operators to provide default values or fallback streams, and then usesetState
to update the MvRx state accordingly.- Fail-Safe State Updates: Ensure that even if an error occurs, the MvRx state is transitioned to a well-defined, safe state. Avoid leaving the state in an inconsistent or undefined condition.
- Test MvRx Error Scenarios: Write unit tests that specifically target the MvRx ViewModels and simulate error conditions to verify that the error handling logic correctly updates the MvRx state.
-
Threats Mitigated:
- Unhandled Exceptions in Async Operations (Severity: Medium): Focuses on how unhandled exceptions affect the MvRx state.
-
Impact:
- Unhandled Exceptions in Async Operations: Reduces risk from Medium to Low.
-
Currently Implemented:
- Example: Some ViewModels have basic
onError
handlers that update the state.
- Example: Some ViewModels have basic
-
Missing Implementation:
- Example: Not all RxJava streams within ViewModels have comprehensive error handling that interacts correctly with
setState
. - Example: Thorough testing of error scenarios specifically within the MvRx context is lacking.
- Example: Not all RxJava streams within ViewModels have comprehensive error handling that interacts correctly with