-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Context
This issue tracks code review feedback from the token pairing feature backport to 2.1.8:
- Original PR: Feature/for mobile based on 2.1.8 bring token pairingย bisq2#4321
- Review: Feature/for mobile based on 2.1.8 bring token pairingย bisq2#4321 (review)
The feedback below should be addressed in the mobile-compatible codebase.
๐ด Major Issues (9)
1. SecureRandom Performance Issue
๐ common/src/main/java/bisq/common/util/ByteArrayUtils.java (lines 89-92)
Problem: Creating a new SecureRandom instance on every call causes initialization overhead.
Fix: Replace with a shared static final SecureRandom instance and add input validation:
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
public static byte[] getRandomBytes(int size) {
if (size < 0) {
throw new IllegalArgumentException("size must be >= 0");
}
byte[] bytes = new byte[size];
SECURE_RANDOM.nextBytes(bytes);
return bytes;
}2. ClientSecret Stored in Plaintext
๐ http-api/src/main/java/bisq/http_api/access/identity/ClientProfile.java (lines 26-35)
Problem: clientSecret is stored as plaintext and serialized via protobuf, creating exposure risk if persistence store is compromised.
Fix Options:
- Implement encryption/decryption for persistence layer
- Document and enforce strict file-level protections + rotation policies
- Ensure constant-time comparison is maintained for authentication
3. Permission Decoding Error Context
๐ http-api/src/main/java/bisq/http_api/access/pairing/PairingCodeDecoder.java (lines 52-55)
Problem: Permission.fromId() throws IllegalArgumentException for unknown IDs without contextual information.
Fix: Either document the fail-fast behavior or wrap exceptions with context:
for (int i = 0; i < numPermissions; i++) {
try {
permissions.add(Permission.fromId(BinaryDecodingUtils.readInt(in)));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
"Invalid permission at index " + i + " in pairing code", e);
}
}4. Race Condition in Pairing Code Consumption
๐ http-api/src/main/java/bisq/http_api/access/pairing/PairingService.java (lines 83-101)
Problem: Non-atomic get() + remove() allows two concurrent requests to use the same pairing code.
Fix: Use atomic remove():
PairingCode pairingCode = pairingCodeByIdMap.remove(pairingCodeId);
if (pairingCode == null) {
throw new InvalidPairingRequestException("Pairing code not found or already used");
}
if (isExpired(pairingCode)) {
throw new InvalidPairingRequestException("Pairing code is expired");
}
// Don't call remove again5. Memory Leak in SessionService
๐ http-api/src/main/java/bisq/http_api/access/session/SessionService.java (lines 27-43)
Problem: sessionTokenBySessionIdMap never evicts expired sessions, causing unbounded memory growth.
Fix Strategy:
- Add lazy cleanup in
find():
public Optional<SessionToken> find(String sessionId) {
SessionToken token = sessionTokenBySessionIdMap.get(sessionId);
if (token != null && token.isExpired()) {
sessionTokenBySessionIdMap.remove(sessionId);
return Optional.empty();
}
return Optional.ofNullable(token);
}- Add explicit
remove(sessionId)method for logout - Add background
ScheduledExecutorServiceto periodically clean expired entries
6. Memory Leak in Pairing Code Map
๐ http-api/src/main/java/bisq/http_api/HttpApiService.java (lines 251-262)
Problem: Periodic regeneration adds codes without removing old ones, causing pairingCodeByIdMap to grow unbounded.
Fix: Either:
- Purge expired entries before inserting new code
- Track and remove previous pairing ID when generating new one
- Add dedicated cleanup task via
Scheduler
7. Inconsistent Error Response Formats
๐ http-api/src/main/java/bisq/http_api/rest_api/endpoints/RestApiBase.java (lines 39-43)
Problem: buildNotFoundResponse returns plain string; buildErrorResponse returns JSON {"error": "..."}.
Fix: Unify to JSON structure:
protected Response buildNotFoundResponse(String message) {
return buildErrorResponse(Response.Status.NOT_FOUND, message);
}8. Null Headers in WebSocketRestApiRequest
๐ http-api/src/main/java/bisq/http_api/web_socket/rest_api_proxy/WebSocketRestApiRequest.java (lines 50-52)
Problem: headers field can be null when omitted from JSON, causing NPEs downstream.
Fix: Initialize to non-null:
private Map<String, String> headers = new HashMap<>();9. Sensitive Data in ToString
๐ http-api/src/main/java/bisq/http_api/web_socket/rest_api_proxy/WebSocketRestApiRequest.java (lines 33-52)
Problem: Lombok @ToString includes sensitive fields (headers, authToken, authTs, authNonce, body).
Fix: Exclude from toString:
@ToString(exclude = {"authToken", "authTs", "authNonce", "headers", "body"})๐ก Minor Issues & Nitpicks (17)
View minor issues and code quality suggestions
Configuration & Validation
- PairingConfig: Validate
sessionTtlInMinutes > 0infrom()method - http_api_app.conf: Consider defaulting
writePairingQrCodeToDisktofalsefor production security
Code Quality
- RestApiBase:
buildOkResponseshould delegate tobuildResponsefor DRY - HttpApiAuthFilter: Lower log level from
infotodebugfor unauthenticated endpoint checks - InvalidPairingRequestException: Add cause-chaining constructor
- InvalidSessionRequestException: Add cause-chaining constructor
- PairingQrCodeGenerator: Remove unused
@Slf4jannotation - ClientProfile: Consider excluding
clientSecretfrom@EqualsAndHashCodeto prevent timing attacks
Binary Encoding
- BinaryDecodingUtils: Default
maxLengthofInteger.MAX_VALUEmisleading (actual limit is 65535) - PairingCodeEncoder: Error message says "pairing QR" but encodes "pairing code"
- PairingCodeDecoder: Same error message inconsistency
Protobuf
- api.proto:
ApiAccessStoreskips field index 1; addreserved 1;if intentional
Permissions
- RestPermissionMapping:
String.replace()replaces all occurrences; usestartsWith()+substring()instead - ApiAccessStore: Deep-copy permission sets in
getClone()to prevent snapshot drift - ApiAccessStoreService: Copy permissions on write to avoid mutability leaks
Testing
- PairingServiceTest: Wrap
Files.readString()in utility for Android API compatibility - Various files: Consider adding more comprehensive unit tests
Priority Recommendation
High Priority (fix before mobile release):
- Issues README: getting started improvements based on first new dev joining the project experienceย #4, Add Bisq 2 library dependenciesย #5, Integrate full node POC code into Bisq-mobile projectย #6 (concurrency + memory leaks)
- Issue Initial App Designย #2 (security - plaintext secrets)
- Issue Define concept for native mobile notificationsย #8, Support to build-up reputation for sellersย #9 (security - sensitive data exposure)
Medium Priority:
- Issues Adapt a leaf Bisq2 module jar and integrate into the appย #1, Framework Setupย #3, Node Tor Supportย #7 (correctness & consistency)
Low Priority:
- All nitpick items (code quality improvements)
Related
- Backport PR: Feature/for mobile based on 2.1.8 bring token pairingย bisq2#4321
- Original feature: Api pairing session handling and tlsย bisq2#4263