Skip to content

Security fix: remove hardcoded credentials and improve exception handling#1095

Open
SachinPremkumar wants to merge 1 commit into
mosip:release-1.1.xfrom
SachinPremkumar:security-fix-1.1.1
Open

Security fix: remove hardcoded credentials and improve exception handling#1095
SachinPremkumar wants to merge 1 commit into
mosip:release-1.1.xfrom
SachinPremkumar:security-fix-1.1.1

Conversation

@SachinPremkumar

@SachinPremkumar SachinPremkumar commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Documentation

    • Updated repository setup guide to reference the 1.1.x development branch
  • Chores

    • Updated app version to 1.1.1
  • Bug Fixes

    • Improved error logging across data synchronization operations
    • Enhanced error handling in authentication and certificate sync workflows
    • Fixed initialization of biometric data fields

Signed-off-by: Sachin S P <52343650+SachinPremkumar@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR bumps the Flutter package and README branch reference to 1.1.x, removes the per-app Sonar Gradle plugin and replaces hardcoded build credentials with placeholders, converts all printStackTrace calls to structured Log.e logging, refactors LoginService to constructor injection, initializes UserBiometric identity fields to empty strings, and fixes rollback/interrupt handling in PreRegistrationDataSyncServiceImpl.

Changes

Release 1.1.x preparation

Layer / File(s) Summary
Version and release branch bumps
README.md, pubspec.yaml
README active branch link updated from release-1.0.x to release-1.1.x; Flutter package version bumped from 1.0.1+1 to 1.1.1+1.
Build config cleanup and credential sanitization
android/app/build.gradle, android/build.gradle
org.sonarqube plugin and its sonar {} block removed from the app module; root build.gradle replaces hardcoded Sonar credentials with placeholders, switches sonar.login to sonar.token, converts Jacoco report paths to rootProject.rootDir-relative strings, and replaces hardcoded debugPassword.
Replace printStackTrace with structured Android logging
android/app/src/.../MasterDataSyncApi.java, android/clientmanager/src/.../UserOnboardService.java
All sync method catch blocks in MasterDataSyncApi replace e.printStackTrace() with Log.e(TAG, …, e) or remove it where Log.e already existed; UserOnboardService IDA auth and certificate failure callbacks do the same.
LoginService constructor injection and UserBiometric defaults
android/clientmanager/src/.../LoginService.java, android/clientmanager/src/.../UserBiometric.java, android/clientmanager/src/test/.../LoginServiceTest.java
LoginService fields converted from @Inject field injection to private final constructor-injected fields; LoginServiceTest removes now-redundant manual field assignments; UserBiometric no-arg constructor initializes usrId, bioTypeCode, and bioAttributeCode to empty strings.
PreRegistrationDataSyncServiceImpl rollback and interrupt handling
android/clientmanager/src/.../PreRegistrationDataSyncServiceImpl.java
getPreRegistration error path now clears documents and demographics on the active RegistrationDto as a rollback; fetchPreRegistration splits the multi-catch into a dedicated InterruptedException branch that restores thread interrupt status and rethrows as RuntimeException without rollback.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇 Hop, hop, the version's new,
1.0.x branch bids adieu!
Secrets masked and stacks now logged,
Constructors clean, no fields unclogged.
Rollback safe when packets fail—
Release 1.1 sets the trail! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: removing hardcoded credentials from build.gradle and improving exception handling by replacing printStackTrace() with proper logging throughout multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java`:
- Around line 230-233: The catch blocks in the exception paths at lines 230,
257, 282, 391, and 416 log errors and update job status via onSyncJobComplete
but fail to complete the Pigeon result object, causing the Flutter caller to
hang indefinitely. In each of these exception handlers, after calling
onSyncJobComplete, add a call to resolve the result object (typically
result.reply or similar Pigeon completion method) with an appropriate response
value to ensure the Flutter caller receives a response when an exception occurs.
Apply this pattern consistently to all five affected catch blocks.

In `@android/build.gradle`:
- Around line 26-30: The Sonar configuration properties in the
android/build.gradle file contain hardcoded placeholder credentials including
sonar.token, sonar.projectKey, and sonar.organization. Replace these hardcoded
values with references to environment variables or Gradle properties that can be
provided at build time. For each credential property (sonar.token,
sonar.projectKey, sonar.organization), use System.getenv() or
project.findProperty() to load the actual values from external sources, allowing
CI/CD pipelines to inject real credentials without modifying the Gradle file.
This keeps the build configuration credential-free and prevents hardcoded values
from overriding CI-provided authentication.
- Line 67: The debugPassword variable contains unnecessary escaped quotes that
create literal quote characters in the actual string value used for Room
database encryption. Locate the debugPassword assignment and remove the
backslash escape sequences around the password text, changing from a string with
escaped inner quotes to a plain string value. This ensures the Room database
password contains only the intended password text without the unintended literal
quote characters.

In
`@android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java`:
- Around line 223-231: The catch block in getPreRegistration() method catches
all Exception types and unconditionally clears the RegistrationDto documents and
demographics, which reintroduces unwanted rollback even for
InterruptedException. Modify the exception handler to check if the caught
exception is caused by or is an InterruptedException before performing the
rollback. If the exception is an InterruptedException, log it without clearing
the registration data, and rethrow or handle it appropriately. Apply this same
fix to all three occurrences mentioned at lines 223-231, 247-250, and 263-266
where this rollback pattern appears.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f09db03a-4d91-481f-8ced-35fa48243aae

📥 Commits

Reviewing files that changed from the base of the PR and between 37f3a80 and 3c9376a.

📒 Files selected for processing (12)
  • README.md
  • android/app/build.gradle
  • android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java
  • android/build.gradle
  • android/clientmanager/src/main/assets/biosdk/matchsdk-debug.aar
  • android/clientmanager/src/main/assets/biosdk/matchsdk-release.aar
  • android/clientmanager/src/main/java/io/mosip/registration/clientmanager/entity/UserBiometric.java
  • android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/LoginService.java
  • android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java
  • android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/UserOnboardService.java
  • android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/LoginServiceTest.java
  • pubspec.yaml
💤 Files with no reviewable changes (2)
  • android/clientmanager/src/test/java/io/mosip/registration/clientmanager/service/LoginServiceTest.java
  • android/app/build.gradle

Comment on lines 230 to 233
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Policy Key Sync Failed.", e);
onSyncJobComplete(jobId, false, isManualSync);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Complete the Pigeon result in exception paths.

At Line 230, Line 257, Line 282, Line 391, and Line 416 catch blocks, the method logs and updates job status but does not resolve result. This can leave the Flutter caller waiting indefinitely when an exception occurs.

Suggested fix pattern (apply to each affected method)
         } catch (Exception e) {
             Log.e(TAG, "Policy Key Sync Failed.", e);
             onSyncJobComplete(jobId, false, isManualSync);
+            result.error(e);
         }
         } catch (Exception e) {
             Log.e(TAG, "Global Params Sync Failed.", e);
             onSyncJobComplete(jobId, false, isManualSync);
+            result.error(e);
         }
         } catch (Exception e) {
             Log.e(TAG, "User Details Sync Failed.", e);
             onSyncJobComplete(jobId, false, isManualSync);
+            result.error(e);
         }
             } catch (Exception e) {
                 Log.e(TAG, "Pre-Reg IDs Sync Failed.", e);
                 onSyncJobComplete(jobId, false, false);
+                result.error(e);
             }
         } catch (Exception e) {
             Log.e(TAG, "Kernel Certs Sync Failed.", e);
             onSyncJobComplete(jobId, false, isManualSync);
+            result.error(e);
         }

Also applies to: 257-260, 282-285, 391-394, 416-419

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@android/app/src/main/java/io/mosip/registration_client/api_services/MasterDataSyncApi.java`
around lines 230 - 233, The catch blocks in the exception paths at lines 230,
257, 282, 391, and 416 log errors and update job status via onSyncJobComplete
but fail to complete the Pigeon result object, causing the Flutter caller to
hang indefinitely. In each of these exception handlers, after calling
onSyncJobComplete, add a call to resolve the result object (typically
result.reply or similar Pigeon completion method) with an appropriate response
value to ensure the Flutter caller receives a response when an exception occurs.
Apply this pattern consistently to all five affected catch blocks.

Comment thread android/build.gradle
Comment on lines +26 to 30
property "sonar.projectKey", "your-sonar-project-key"
property "sonar.organization", "your-sonar-organization"
property "sonar.host.url", "https://sonarcloud.io"
property "sonar.login", "13c9437b3fa54b66de5ec14c4fc2bd04fb55ae77"
property "sonar.token", "your-sonar-token"
property "sonar.androidLint.reportPaths", "**/reports/lint-results-debug.xml"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not hardcode placeholder Sonar credentials in executable Gradle config.

Line 29 sets a literal token value ("your-sonar-token"), which can override CI-provided auth and fail analysis. Load credentials from env/Gradle properties and keep this file credential-free.

Suggested fix
-        property "sonar.projectKey", "your-sonar-project-key"
-        property "sonar.organization", "your-sonar-organization"
+        property "sonar.projectKey", System.getenv("SONAR_PROJECT_KEY") ?: ""
+        property "sonar.organization", System.getenv("SONAR_ORGANIZATION") ?: ""
         property "sonar.host.url", "https://sonarcloud.io"
-        property "sonar.token", "your-sonar-token"
+        property "sonar.token", System.getenv("SONAR_TOKEN") ?: ""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
property "sonar.projectKey", "your-sonar-project-key"
property "sonar.organization", "your-sonar-organization"
property "sonar.host.url", "https://sonarcloud.io"
property "sonar.login", "13c9437b3fa54b66de5ec14c4fc2bd04fb55ae77"
property "sonar.token", "your-sonar-token"
property "sonar.androidLint.reportPaths", "**/reports/lint-results-debug.xml"
property "sonar.projectKey", System.getenv("SONAR_PROJECT_KEY") ?: ""
property "sonar.organization", System.getenv("SONAR_ORGANIZATION") ?: ""
property "sonar.host.url", "https://sonarcloud.io"
property "sonar.token", System.getenv("SONAR_TOKEN") ?: ""
property "sonar.androidLint.reportPaths", "**/reports/lint-results-debug.xml"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@android/build.gradle` around lines 26 - 30, The Sonar configuration
properties in the android/build.gradle file contain hardcoded placeholder
credentials including sonar.token, sonar.projectKey, and sonar.organization.
Replace these hardcoded values with references to environment variables or
Gradle properties that can be provided at build time. For each credential
property (sonar.token, sonar.projectKey, sonar.organization), use
System.getenv() or project.findProperty() to load the actual values from
external sources, allowing CI/CD pipelines to inject real credentials without
modifying the Gradle file. This keeps the build configuration credential-free
and prevents hardcoded values from overriding CI-provided authentication.

Comment thread android/build.gradle
serverHealthCheckPath = "\"/v1/syncdata/actuator/health\""
serverActuatorInfoPath = "\"/v1/syncdata/actuator/info\""
debugPassword = "\"APTyKejHxACQyKBSRciR\""
debugPassword = "\"your-debug-password\""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where debugPassword is declared and consumed
rg -n -C3 '\bdebugPassword\b'

# Show signing-related usage context in Gradle files
fd -i 'build.gradle' -t f | xargs -I{} sh -c 'echo "---- {} ----"; rg -n -C2 "storePassword|keyPassword|debugPassword" "{}"'

Repository: mosip/android-registration-client

Length of output: 2583


🏁 Script executed:

#!/bin/bash
# Search for BuildConfig.DEBUG_PASSWORD usage
rg -n 'DEBUG_PASSWORD|debugPassword' --type java --type kotlin

# Also search in all text files to understand context
rg -n 'DEBUG_PASSWORD' -A3 -B3

Repository: mosip/android-registration-client

Length of output: 4408


🏁 Script executed:

#!/bin/bash
# Check if debugPassword is involved in any keystore or signing operations
rg -n -i 'keystore|signing|keystorefil' --type gradle | head -30

Repository: mosip/android-registration-client

Length of output: 729


🏁 Script executed:

#!/bin/bash
# Check RoomModule.java to see how dbPwd is used with the database
cat -n android/clientmanager/src/main/java/io/mosip/registration/clientmanager/config/RoomModule.java | head -120 | tail -30

Repository: mosip/android-registration-client

Length of output: 1949


🏁 Script executed:

#!/bin/bash
# Look for any documentation or comments about password format in the codebase
rg -n 'password.*quote|quote.*password|debug.*password' -i

Repository: mosip/android-registration-client

Length of output: 1266


Remove the unnecessary escaped quotes from debugPassword.

The escaped quotes in "\"your-debug-password\"" create a string containing literal quote characters. This value is used as the Room database password in debug mode (RoomModule.java:104), so the effective password becomes "your-debug-password" including the quotes. Change this to debugPassword = "your-debug-password" to remove the unintended quotes.

Note: This affects only debug database encryption, not signing credentials (which use storePassword/keyPassword from key.properties).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@android/build.gradle` at line 67, The debugPassword variable contains
unnecessary escaped quotes that create literal quote characters in the actual
string value used for Room database encryption. Locate the debugPassword
assignment and remove the backslash escape sequences around the password text,
changing from a string with escaped inner quotes to a plain string value. This
ensures the Room database password contains only the intended password text
without the unintended literal quote characters.

Comment on lines 223 to +231
} catch (Exception e) {
Log.e(TAG,ERROR_FETCH_PRE_REG_PACKET, e);
try {
RegistrationDto registrationDto = this.registrationService.getRegistrationDto();
registrationDto.getDocuments().clear();
registrationDto.getDemographics().clear();
} catch (Exception inner) {
Log.e(TAG, "No active registration to roll back", inner);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Interrupted fetch still triggers rollback in caller.

fetchPreRegistration(...) now avoids rollback for InterruptedException, but getPreRegistration(...) catches that wrapped runtime error in catch (Exception e) and still clears active RegistrationDto. This reintroduces unintended rollback and can wipe in-progress data during cancellation/interruption.

Proposed fix
-        } catch (Exception e) {
-            Log.e(TAG,ERROR_FETCH_PRE_REG_PACKET, e);
-            try {
+        } catch (Exception e) {
+            Log.e(TAG, ERROR_FETCH_PRE_REG_PACKET, e);
+            if (Thread.currentThread().isInterrupted() ||
+                    (e instanceof RuntimeException && e.getCause() instanceof InterruptedException)) {
+                Thread.currentThread().interrupt();
+                return attributeData;
+            }
+            try {
                 RegistrationDto registrationDto = this.registrationService.getRegistrationDto();
                 registrationDto.getDocuments().clear();
                 registrationDto.getDemographics().clear();
             } catch (Exception inner) {
                 Log.e(TAG, "No active registration to roll back", inner);
             }
         }

Also applies to: 247-250, 263-266

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@android/clientmanager/src/main/java/io/mosip/registration/clientmanager/service/PreRegistrationDataSyncServiceImpl.java`
around lines 223 - 231, The catch block in getPreRegistration() method catches
all Exception types and unconditionally clears the RegistrationDto documents and
demographics, which reintroduces unwanted rollback even for
InterruptedException. Modify the exception handler to check if the caught
exception is caused by or is an InterruptedException before performing the
rollback. If the exception is an InterruptedException, log it without clearing
the registration data, and rethrow or handle it appropriately. Apply this same
fix to all three occurrences mentioned at lines 223-231, 247-250, and 263-266
where this rollback pattern appears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant