What changed, and why it matters
This commit changes the Tor privacy service in Stack Wallet so only one copy of the service can run at a time (a 'singleton'). Before, each call could create a fresh instance, which could lead to multiple Tor connections or inconsistent state. The patch itself is a defensive code-quality fix; it does not show an active attack or known breach.
Review whether the duplicate-instance behavior could have caused observable privacy or reliability issues in prior releases. If so, consider a security advisory; otherwise treat as a hardening fix and include in release notes.
Security signals we found
singleton enforcement for privacy-critical network service
prevention of duplicate Tor service instances
potential resource/state duplication bug class addressed
Evidence from the diff
The diff converts _TorServiceImpl and _FusionTorServiceImpl from directly instantiable classes to singletons using a private constructor and static instance accessor. The factory functions _getInterface() and _getFusionInterface() now return the singleton instance instead of a new object. This prevents duplicate Tor service objects, which could otherwise cause duplicate Tor processes, conflicting state, or resource leaks. There is no direct exploit shown in the diff, but duplicate instances of a privacy-critical network service are a reliability and potentially security-relevant bug class.
Changed components
tool/wl_templates/TOR_tor_service_impl.template.dartTorService implementationFusionTorService implementationInspect captured patch +13 / −2
diff --git a/tool/wl_templates/TOR_tor_service_impl.template.dart b/tool/wl_templates/TOR_tor_service_impl.template.dart
index 3e26caf..63ee6ef 100644
--- a/tool/wl_templates/TOR_tor_service_impl.template.dart
+++ b/tool/wl_templates/TOR_tor_service_impl.template.dart
@@ -21,10 +21,15 @@ FusionTorService _getFusionInterface() => throw Exception("TOR not enabled!");
//END_OFF
//ON
-TorService _getInterface() => _TorServiceImpl();
-FusionTorService _getFusionInterface() => _FusionTorServiceImpl();
+TorService _getInterface() => _TorServiceImpl.instance;
+FusionTorService _getFusionInterface() => _FusionTorServiceImpl.instance;
class _TorServiceImpl extends TorService {
+ static _TorServiceImpl? _instance;
+ static _TorServiceImpl get instance => _instance ??= _TorServiceImpl._();
+
+ _TorServiceImpl._();
+
Tor? _tor;
String? _torDataDirPath;
TorConnectionStatus _status = TorConnectionStatus.disconnected;
@@ -131,6 +136,12 @@ class _TorServiceImpl extends TorService {
}
class _FusionTorServiceImpl extends FusionTorService {
+ static _FusionTorServiceImpl? _instance;
+ static _FusionTorServiceImpl get instance =>
+ _instance ??= _FusionTorServiceImpl._();
+
+ _FusionTorServiceImpl._();
+
Tor? _tor;
String? _torDataDirPath;
Why this scored 28/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.