What changed, and why it matters
This commit fixes two reliability problems in a cryptocurrency wallet app. First, it adds a 20-second timeout when fetching fiat exchange rates, so the app no longer waits forever if the network stalls. Second, it adds a 5-second timeout when closing the Tor/ SOCKS network socket, preventing a slow shutdown from hanging the app. It also removes a line that set wallet key-derivation rounds to 1, which is a very low, insecure value. The commit message only mentions the fiat-rate loading issue, not the security change.
Review the default KDF rounds used by the underlying Monero wallet library after removing the override, verify that the new timeouts cover worst-case Tor latency without being too short, and confirm whether the KDF change was intentional and should be disclosed as a security hardening fix.
Security signals we found
Removal of hardcoded kdfRounds: 1, which weakens key-derivation cost for wallet encryption
Addition of network request timeout to prevent indefinite resource waits
Addition of socket-close timeout to prevent finally-block hangs
Evidence from the diff
The patch modifies three Dart files. fiat_rate_model.dart wraps the SOCKS HTTP request in a 20-second timeout to prevent indefinite awaits. socks_http.dart wraps socket.close() in a 5-second timeout with a log-only catch, preventing a stalled close from blocking the finally block. wallet_model.dart removes kdfRounds: 1 from a Monero wallet creation call, which previously forced an extremely weak key-derivation cost. No verified references are supplied, so the intent behind the KDF change cannot be independently confirmed.
Changed components
lib/models/fiat_rate_model.dartlib/models/wallet_model.dartlib/util/socks_http.dartInspect captured patch +7 / −7
diff --git a/lib/models/fiat_rate_model.dart b/lib/models/fiat_rate_model.dart
index fcc963a..8486a41 100644
--- a/lib/models/fiat_rate_model.dart
+++ b/lib/models/fiat_rate_model.dart
@@ -107,7 +107,11 @@ class FiatRateModel with ChangeNotifier {
}
try {
- final response = await makeSocksHttpRequest('GET', url, proxyInfo);
+ final response = await makeSocksHttpRequest(
+ 'GET',
+ url,
+ proxyInfo,
+ ).timeout(const Duration(seconds: 20));
if (response.statusCode == 200) {
final rate = response.jsonBody?['result']?[pair]?['o'];
if (rate is! String) {
diff --git a/lib/models/wallet_model.dart b/lib/models/wallet_model.dart
index 9523f0f..918d8c5 100644
--- a/lib/models/wallet_model.dart
+++ b/lib/models/wallet_model.dart
@@ -1203,7 +1203,6 @@ class WalletModel with ChangeNotifier {
restoreHeight: restoreHeight,
password: password,
path: isDummy ? '' : walletPath,
- kdfRounds: 1,
).address;
});
diff --git a/lib/util/socks_http.dart b/lib/util/socks_http.dart
index 708a803..9a82807 100644
--- a/lib/util/socks_http.dart
+++ b/lib/util/socks_http.dart
@@ -138,12 +138,9 @@ Future<ParsedHttpResponse> makeSocksHttpRequest(
return parseHttpResponse(rawResponse);
} finally {
- // Each request opens its own SOCKS connection, and with it a Tor circuit.
- // Left open they accumulate for the life of the process — the fiat poller
- // alone starts one every ten minutes. Closing must not mask a request
- // error, so its own failure is only logged.
+ // Free the Tor circuit; bounded so a stalled close can't hang the request.
try {
- await socket.close();
+ await socket.close().timeout(const Duration(seconds: 5));
} catch (e) {
log(LogLevel.warn, 'Failed to close SOCKS socket: $e');
}
Why this scored 46/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.