Mitigation Strategy: Enforce Consistent DisposeBag
Usage
-
Description:
- Training: Ensure all developers understand RxSwift subscriptions and
DisposeBag
. - Code Style Guide: Mandate
DisposeBag
use for all subscriptions in the style guide. - Initialization: Create a
private let disposeBag = DisposeBag()
in every class managing subscriptions. - Subscription Handling: Always use
.disposed(by: disposeBag)
when creating subscriptions:.subscribe(...).disposed(by: disposeBag)
. - Lifecycle Management: Tie the
disposeBag
to the owning object's lifecycle (automatic deallocation usually handles this). - Code Reviews: Check for
disposeBag
presence, correct usage, and no manual disposal (unless justified). - Static Analysis (Optional): Explore tools to detect potential subscription leaks.
- Training: Ensure all developers understand RxSwift subscriptions and
-
Threats Mitigated:
- Memory Leaks (Severity: High): Unreleased subscriptions prevent garbage collection.
- Resource Exhaustion (Severity: High): Leaked subscriptions can hold other resources.
- Unexpected Behavior (Severity: Medium): Leaked subscriptions can react to events after the object is logically gone.
-
Impact:
- Memory Leaks: Significantly reduced (near elimination with perfect implementation).
- Resource Exhaustion: Significantly reduced (near elimination with perfect implementation).
- Unexpected Behavior: Significantly reduced.
-
Currently Implemented: Partially.
DisposeBag
is used inViewControllerA
,ViewModelB
, andNetworkManager
. -
Missing Implementation:
DataProcessor
class, several utility classes in theHelpers
folder.
Mitigation Strategy: Comprehensive RxSwift Error Handling
-
Description:
- Identify Error Sources: Find all potential error sources within Observable sequences.
catchError
/catchErrorJustReturn
: Use these operators in every Observable chain:catchError
: Transform the error into a new Observable (e.g., retry, show an error).catchErrorJustReturn
: Provide a default value and continue.
- Error-Specific Handling: Within
catchError
, useif let
orswitch
to handle different error types:.catchError { error in if let networkError = error as? NetworkError { // Handle network errors } else if let parsingError = error as? ParsingError { // Handle parsing errors } else { // Handle generic errors } return .empty() // Or a new Observable }
retry
(with Caution): For transient errors, useretry
with a backoff strategy and retry limit.- Global Error Handling (Optional): Use a
PublishSubject
orBehaviorSubject
for unhandled errors (logging, reporting). - Logging: Log all errors (handled and unhandled) with context.
- Code Reviews: Verify error handling and type-specific handling.
-
Threats Mitigated:
- Application Crashes (Severity: High): Unhandled errors can terminate sequences and crash the app.
- Data Corruption (Severity: Medium-High): Unhandled errors during processing can corrupt data.
- UI Inconsistencies (Severity: Medium): Unhandled errors can leave the UI in an unexpected state.
- Denial of Service (DoS) (Severity: Medium): Exploitable repeated failures.
-
Impact:
- Application Crashes: Significantly reduced.
- Data Corruption: Significantly reduced.
- UI Inconsistencies: Significantly reduced.
- Denial of Service (DoS): Reduced (especially with careful retry logic).
-
Currently Implemented: Partially. Basic error handling in network requests, but not consistent. No global handling.
-
Missing Implementation: Data parsing, user input validation, internal processing. Retry logic inconsistent. No global error subject.
Mitigation Strategy: Controlled Threading with observeOn
and subscribeOn
-
Description:
- Identify Threading Needs: For each Observable sequence:
- Where should work be done (background for network, main for UI)?
- Where should results be delivered (main for UI)?
subscribeOn
: Use to specify the thread for subscription and upstream operations:.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.observeOn
: Use to specify the thread for downstream operations. For UI:.observeOn(MainScheduler.instance)
.- Serial Queues: If operations must be sequential, use:
SerialDispatchQueueScheduler(qos: .background)
. - Testing: Thoroughly test concurrent operations.
- Code Review: Ensure that all UI operations are happening on Main thread.
- Identify Threading Needs: For each Observable sequence:
-
Threats Mitigated:
- Race Conditions (Severity: High): Uncontrolled threading leads to unpredictable results.
- Deadlocks (Severity: High): Threads blocked indefinitely.
- UI Freezes/Crashes (Severity: High): UI updates from background threads.
-
Impact:
- Race Conditions: Significantly reduced.
- Deadlocks: Significantly reduced.
- UI Freezes/Crashes: Eliminated.
-
Currently Implemented: Partially.
observeOn(MainScheduler.instance)
used in some UI code,subscribeOn
inconsistent. -
Missing Implementation: Consistent
subscribeOn
for background tasks. Thorough concurrent testing.
Mitigation Strategy: Minimize and Encapsulate Subject
Usage
-
Description:
- Prefer Observable Creation: Use
Observable.create
,Observable.just
,Observable.from
, etc., instead ofSubject
s. - Use Appropriate Subject Type: If a
Subject
is required:PublishSubject
: Only new events.BehaviorSubject
: Latest value and subsequent events.ReplaySubject
: Replays past events and subsequent events.AsyncSubject
: Only the last value on completion.
- Encapsulation: Never expose
Subject
s directly. Use.asObservable()
:private let mySubject = PublishSubject<Int>() var myObservable: Observable<Int> { return mySubject.asObservable() }
- Code Reviews: Scrutinize
Subject
use; justify necessity and ensure encapsulation.
- Prefer Observable Creation: Use
-
Threats Mitigated:
- Tight Coupling (Severity: Medium): Overuse creates tight coupling.
- Unpredictable Data Flow (Severity: Medium): Harder to trace event sources.
- Code Injection (Severity: Low, but possible): Public
Subject
s could allow event injection.
-
Impact:
- Tight Coupling: Reduced.
- Unpredictable Data Flow: Improved.
- Code Injection: Risk significantly reduced.
-
Currently Implemented: Partially. Some encapsulation, but others exposed.
PublishSubject
overused. -
Missing Implementation: Consistent encapsulation. Review and refactor to reduce
Subject
usage.
Mitigation Strategy: Pure Operators and Isolated Side Effects using do
operator
-
Description:
- Pure Operators:
map
,flatMap
,filter
,scan
, etc., should be pure functions – only transform data, no side effects. do(onNext:)
for Side Effects: If unavoidable, usedo(onNext:)
,do(onError:)
, ordo(onCompleted:)
. This clearly marks side effects.- Isolate Side Effects: Complex or security-sensitive side effects should be in separate functions/classes.
- Consider Alternatives: Explore ways to eliminate side effects within operators.
- Code Review: Ensure that all side effects are happening inside
do
operator.
- Pure Operators:
-
Threats Mitigated:
- Unpredictable Behavior (Severity: Medium): Side effects make code harder to reason about.
- Race Conditions (Severity: Medium-High): Side effects modifying shared state.
- Security Vulnerabilities (Severity: Variable): Depends on the side effect.
-
Impact:
- Unpredictable Behavior: Significantly reduced.
- Race Conditions: Reduced.
- Security Vulnerabilities: Reduced.
-
Currently Implemented: Not consistently implemented. Side effects present in some operators.
-
Missing Implementation: Review and refactor to remove side effects or use
do(onNext:)
. Clear guidelines for side effects.