Skip to content

Conversation

@jaswanthkumartw
Copy link

@jaswanthkumartw jaswanthkumartw commented Dec 24, 2025

Summary by CodeRabbit

  • New Features

    • Added support for CWT (COSE Web Token) credential format validation and verification.
    • Added credential status checking capability with per-purpose result tracking and detailed error reporting.
  • Improvements

    • Enhanced credential verification with improved error codes and messages.
    • Updated library dependencies for better compatibility and security.
  • Documentation

    • Comprehensive updates with detailed validation flows, verification mechanisms, and error code references.
  • Chores

    • Version bumped to 1.7.0.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

Walkthrough

Introduces CWT (CBOR Web Token) credential support and refactors the credential verification system to replace legacy revocation checking with a comprehensive credential status checking mechanism that retrieves and validates status lists, returning detailed per-purpose status results.

Changes

Cohort / File(s) Summary
CWT Credential Support
vc-verifier/kotlin/example/.../MainActivity.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialFormat.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt
Added CWT_VC credential format enum entry, new CwtVerifiableCredential class delegating to CwtValidator and CwtVerifier, comprehensive CWT validation logic including COSE structure and protected header validation, and CWT signature verification with issuer metadata resolution and JWKS key retrieval.
Status Checking Refactor
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/VerifiableCredential.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/LdpVerifiableCredential.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/SdJwtVerifiableCredential.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/msomdoc/MsoMdocVerifiableCredential.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt
Replaced isRevoked method with checkStatus across all credential types, returning Map<String, CredentialStatusResult>; new LdpStatusChecker implements comprehensive status list retrieval, CBOR decoding, bitstring extraction, and per-purpose status computation with detailed error handling.
Removed Legacy Code
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/LdpRevokeChecker.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/MsoMdocRevokeChecker.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/RevocationCheckException.kt
Removed obsolete revocation-checking classes and exception type in favor of new status checking infrastructure.
Data Models & Exception Types
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/StatusCheckException.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/StatusCheckerConstants.kt
Added new data classes (CredentialStatusResult, CredentialVerificationSummary, VCResultWithCredentialStatus, PresentationResultWithCredentialStatus), StatusCheckException with error code enum, and status-checking constants (STATUS_LIST_CREDENTIAL, BITSTRING_STATUS_LIST, etc.); added verificationErrorCode field to VerificationResult.
API Updates
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/CredentialsVerifier.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/CredentialVerifierFactory.kt
Extended CredentialsVerifier with getCredentialStatus and verifyAndGetCredentialStatus methods; updated PresentationVerifier with verifyAndGetCredentialStatus and new helper for VP proof verification; factory now handles CWT_VC format.
Utilities
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/LocalDocumentLoader.kt
Added hexToBytes, validateNumericDate, httpGet utility functions; exposed RestTemplate instance; added context mapping for mock identity context.
Constants & Error Handling
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt, vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialVerifierConstants.kt
Added CWT-specific error constants (ERROR_MESSAGE_EMPTY_VC_CWT, ERROR_MESSAGE_INVALID_HEX_VC_CWT); removed legacy VC_REVOKED error constants.
Dependencies & Configuration
vc-verifier/kotlin/gradle/libs.versions.toml, vc-verifier/kotlin/vcverifier/build.gradle.kts, vc-verifier/kotlin/vcverifier/publish-artifact.gradle, vc-verifier/kotlin/example/build.gradle.kts
Updated Jackson dependencies from 2.14.0 to 2.17.2, added COSE library 2.0.0 dependency with BCrypto exclusions, bumped library version from 1.6.0 to 1.7.0, added OSGI manifest exclusion.
Test Infrastructure
vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt, vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt, vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
Added test utilities (readClasspathFile, mockHttpResponse) for fixture loading and HTTP mocking; added comprehensive CwtValidatorTest covering structure validation, temporal claims, and error paths; scaffolded CwtVerifierTest.
Test Coverage Updates
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt, vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt, vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt, vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/...Test.kt
Added setup/teardown and test utilities for status list verification scenarios; replaced legacy StatusListRevocationCheckerTest with comprehensive StatusListRevocationCheckerTest for LdpStatusChecker covering edge cases, temporal validation, and error codes.
Test Resources
vc-verifier/kotlin/vcverifier/src/test/resources/contexts/mock-identity-context.json, vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/{mockDid.json, mosipRevoked*.json, mosipUnrevoked*.json, public_key/*}, vc-verifier/kotlin/vcverifier/src/test/resources/vp/*
Added JSON-LD mock identity context, DID documents with multiple key types (RSA, EC, Ed25519), revoked/unrevoked VC fixtures with credential status references, status list credentials, and VP test fixtures with embedded credentials.
Documentation
README.md, vc-verifier/kotlin/README.md
Added statusChecker to project structure, updated VC format support table; comprehensive Kotlin README overhaul including validation/verification flows, status checking workflow, API overview, error codes, and example JSON/Kotlin structures.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant CV as CredentialsVerifier
    participant VC as VerifiableCredential
    participant SC as StatusChecker<br/>(LdpStatusChecker)
    participant HTTP as HTTP Get

    C->>CV: verifyAndGetCredentialStatus(vc, format, purposes)
    CV->>VC: verify(credential)
    VC->>VC: validate() & verify()
    alt Verification Success
        VC-->>CV: true
        CV->>SC: getStatuses(credential, purposes)
        SC->>SC: parse credentialStatus
        SC->>HTTP: fetch statusListCredential
        HTTP-->>SC: statusListVC
        SC->>SC: validate statusListVC signature
        SC->>SC: decode & decompress encodedList
        SC->>SC: extract bit at statusListIndex
        SC-->>CV: Map<purpose, CredentialStatusResult>
        CV-->>C: CredentialVerificationSummary<br/>(success, statusMap)
    else Verification Failed
        VC-->>CV: false
        CV-->>C: CredentialVerificationSummary<br/>(failure, empty)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • swatigoel
  • abhip2565
  • mayuradesh

🐰 A new status checker bounces with glee,
CWT credentials now dance free,
Old revoke paths fade away,
Credential status rules the day, 🎉
Verification flows now complete,
Making credentials oh-so-neat!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.60% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[INJIVER-1369] - Add verification and validation for cwt formet VC' contains a typo ('formet' instead of 'format') but clearly describes adding CWT VC support, which aligns with the PR's main objective of introducing CWT credential verification and validation.
✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Nitpick comments (6)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt (1)

55-56: Remove trailing blank line.

The constant definition is correct and follows the existing pattern. However, Line 56 contains an unnecessary blank line.

🔎 Proposed fix
-    const val ERROR_MESSAGE_EMPTY_VC_CWT="${VALIDATION_ERROR}Input VC CWT string is null or empty."
-
+    const val ERROR_MESSAGE_EMPTY_VC_CWT="${VALIDATION_ERROR}Input VC CWT string is null or empty."
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt (1)

14-16: Remove unnecessary semicolons for idiomatic Kotlin.

Kotlin does not require semicolons at the end of statements.

🔎 Proposed fix
     override fun verify(credential: String): Boolean {
-        return CwtVerifer().verify(credential);
+        return CwtVerifier().verify(credential)
     }

     override fun checkStatus(credential: String, statusPurposes: List<String>?): List<CredentialStatusResult>? {
-        return null;
+        return null
     }

Also applies to: 18-20

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)

162-176: Consider throwing a domain-specific exception for consistency.

The require on line 171 throws IllegalArgumentException, which will be caught by CwtValidator's generic Exception handler and mapped to ERROR_CODE_GENERIC. Consider throwing ValidationException directly for more precise error handling and consistent error codes.

🔎 Proposed alternative
     fun validateNumericDate(
         claims: CBORObject,
         key: CBORObject,
         name: String
     ): Long? {
         if (!claims.ContainsKey(key)) return null

         val value = claims[key]

-        require(value.type == CBORType.Integer) {
-            "$name must be a CBOR integer (NumericDate)"
+        if (value.type != CBORType.Integer) {
+            throw IllegalArgumentException("$name must be a CBOR integer (NumericDate)")
         }

         return value.AsInt64()
     }

Alternatively, make this function throw ValidationException directly if validation-specific error handling is needed.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)

119-119: Extract CBOR claim keys as companion object constants.

ALG, EXP, NBF, and IAT are created as local variables on each validation call. Extract these as class-level constants to avoid repeated object creation.

🔎 Proposed fix
class CwtValidator {

    companion object {
        private val ALG = CBORObject.FromObject(1)
        private val EXP = CBORObject.FromObject(4)
        private val NBF = CBORObject.FromObject(5)
        private val IAT = CBORObject.FromObject(6)
    }

    // ... rest of the class
}

Also applies to: 159-161

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)

26-28: Remove unused code.

  • cborMapper (lines 26-28) is never used
  • header1 and headerValue (lines 127-128) are extracted but never used
🔎 Proposed fix
-    private val cborMapper = ObjectMapper(CBORFactory())
-        .registerKotlinModule()
-
         val payloadBytes = coseObj[2].GetByteString()
-        val header1 = coseObj[0].GetByteString()
-        val headerValue = CBORObject.DecodeFromBytes(header1)
         val claims = CBORObject.DecodeFromBytes(payloadBytes)

Also applies to: 127-128


16-24: Consider dependency injection for RestTemplate.

Creating RestTemplate as an instance variable works but makes testing difficult. Consider injecting it as a constructor parameter or using a factory for better testability.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf09af6 and e6b6a8f.

📒 Files selected for processing (12)
  • vc-verifier/kotlin/example/src/main/java/io/mosip/vccred/example/MainActivity.kt
  • vc-verifier/kotlin/gradle/libs.versions.toml
  • vc-verifier/kotlin/vcverifier/build.gradle.kts
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialFormat.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/CredentialVerifierFactory.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
👮 Files not reviewed due to content moderation or server errors (1)
  • vc-verifier/kotlin/example/src/main/java/io/mosip/vccred/example/MainActivity.kt
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-03T12:07:06.442Z
Learnt from: abhip2565
Repo: mosip/vc-verifier PR: 202
File: vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/SdJwtVerifiableCredential.kt:18-21
Timestamp: 2025-11-03T12:07:06.442Z
Learning: For SD-JWT credentials in the vc-verifier project, the checkStatus method should return null to bypass status checks rather than throwing errors or implementing actual status verification.

Applied to files:

  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
🧬 Code graph analysis (1)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)
  • hexToBytes (153-160)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)
  • decodeCose (193-196)
🪛 detekt (1.23.8)
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt

[warning] 3-3: The class or object CwtValidatorTest is empty.

(detekt.empty-blocks.EmptyClassBlock)

🔇 Additional comments (5)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/CredentialVerifierFactory.kt (1)

4-4: LGTM!

The CWT credential format integration follows the existing factory pattern correctly and is consistent with other credential format handlers.

Also applies to: 16-16

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialFormat.kt (1)

4-4: LGTM!

The CWT_VC enum entry addition is correct and follows the existing naming convention.

vc-verifier/kotlin/gradle/libs.versions.toml (1)

23-24: Run tests for Jackson module compatibility, particularly Kotlin data class deserialization and CBOR format parsing.

The Jackson upgrade from 2.14.0 to 2.17.2 introduces several behavior changes across the 2.15–2.17 releases. While your codebase uses only straightforward Jackson features (basic ObjectMapper.readValue() with Map/TypeReference, Kotlin module, and CBOR format), verify these areas:

  • Kotlin module: Test data class deserialization and constructor handling (Kotlin module refinements in 2.17 may affect behavior)
  • CBOR parsing: Validate CBOR deserialization in CwtVerifer.kt (CBOR format enhancements in 2.15+ may alter parsing behavior)
  • ObjectMapper usage: Confirm readValue() calls in Utils.kt, DidWebPublicKeyResolver.kt, LdpRevokeChecker.kt, and SdJwtValidator.kt produce correct results

The upgrade is safe for this codebase since it does not use polymorphic types (@JsonTypeInfo), enum annotations, JsonNode tree mutations, or large value streaming where breaking changes are more likely.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)

153-160: LGTM!

The hexToBytes function correctly strips whitespace, validates even length, and converts hex pairs to bytes.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)

169-174: The current implementation is correct per RFC 8392 (CWT) and RFC 7519 (JWT) specifications. The "exp" claim processing rule states: the current date/time MUST be before the value of "exp"; the token MUST NOT be accepted on or after the exp time. The condition exp <= now correctly implements this requirement—rejecting tokens when the current time equals or exceeds the expiration time. The suggested alternative exp < now would violate the specification by incorrectly accepting tokens at the exact moment of expiration.

cbor = "0.9"
identity = "20231002"
authleteSdJwt = "1.5"
augustcellars = "1.1.0"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the gradle libs.versions.toml file to see the full context
find . -name "libs.versions.toml" -path "*/vc-verifier/kotlin/*" -exec cat -n {} +

Repository: mosip/vc-verifier

Length of output: 178


🌐 Web query:

augustcellars cose-java 1.1.0 Maven Central latest version

💡 Result:

The latest version of com.augustcellars.cose:cose-java on Maven Central is 1.1.0 (released Jan 27, 2020). [1][2]

Sources:
[1] Maven Central (repo1.maven.org) listing for com/augustcellars/cose/cose-java/1.1.0.
[2] MVNRepository entry for cose-java showing newest version 1.1.0.


🌐 Web query:

cose-java security vulnerabilities CVE

💡 Result:

Short answer — cose-java itself has no widely‑published CVE entries; reported CVEs are for its third‑party dependencies (notably Bouncy Castle). Examples reported for cose-java releases include CVE-2024-29857, CVE-2024-30171 and CVE-2025-8916 (these are Bouncy Castle issues flagged on Maven/metadata for com.augustcellars.cose:cose-java). [1][2][3][4]

Sources:

  • cose-java package page (lists dependency CVEs). [1]
  • NVD entry for CVE-2024-30171 (Bouncy Castle timing/leakage issue). [2]
  • CVE-2024-29857 (Bouncy Castle EC curve CPU exhaustion). [3]
  • CVE-2025-8916 (Bouncy Castle excessive-allocation / DoS). [4]

If you want, I can:

  • list every CVE shown for a specific cose-java version, or
  • check your project’s dependency tree and tell you which versions of bcprov/bcpkix are pulled in and whether they are vulnerable. Which would you prefer?

🌐 Web query:

augustcellars CBOR library versions security

💡 Result:

Short answer: AugustCellars itself does not publish a standalone "AugustCellars.CBOR" with known CVEs, but AugustCellars packages (notably Com.AugustCellars.COSE) use other CBOR libraries and have historically bumped the CBOR dependency for security reasons. Notable findings:

  • Com.AugustCellars.COSE release notes state they updated to a newer CBOR (CBOR version 4.0) "due to a security parsing problem" (release 1.6.0). (nuget.org)
  • Many .NET CBOR issues are in other libraries (e.g., PeterO.Cbor has documented denial‑of‑service vulnerabilities / GHSA advisories and CVEs). If you use AugustCellars packages that depend on PeterO.Cbor, check the PeterO.Cbor advisory/CVE for affected versions and upgrade accordingly. (cvedetails.com)

Recommendation: identify which AugustCellars NuGet packages you use (e.g., Com.AugustCellars.COSE, Com.AugustCellars.CoAP) and inspect their current package metadata to see which CBOR implementation and version they depend on; then verify that CBOR dependency against its advisories/CVEs and upgrade to the fixed versions. Example NuGet pages show the CBOR-related dependency history for Com.AugustCellars.COSE. (nuget.org)

If you want, tell me which AugustCellars package and version you use and I’ll list the exact CBOR dependency and any known vulnerabilities and fixed versions.

Citations:


Verify Bouncy Castle transitive dependencies for known vulnerabilities.

Version 1.1.0 is the latest available on Maven Central. However, cose-java has transitive dependencies on Bouncy Castle (versions pulled by 1.1.0) which contain known security vulnerabilities: CVE-2024-29857 (EC curve CPU exhaustion), CVE-2024-30171 (timing/leakage), and CVE-2025-8916 (DoS). Audit the Bouncy Castle versions in your dependency tree and consider upgrading cose-java or managing Bouncy Castle transitive versions to mitigate these vulnerabilities.

Comment on lines 68 to 69
implementation(libs.jackson.dataformat.cbor)
implementation(libs.cose.java)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd vc-verifier/kotlin/vcverifier && cat build.gradle.kts | head -100

Repository: mosip/vc-verifier

Length of output: 2626


🏁 Script executed:

find . -name "libs.versions.toml" -o -name "libs.versions.json" -o -name "gradle.properties" | head -20

Repository: mosip/vc-verifier

Length of output: 146


🏁 Script executed:

cat ./vc-verifier/kotlin/gradle/libs.versions.toml

Repository: mosip/vc-verifier

Length of output: 4441


🏁 Script executed:

#!/bin/bash

echo "=== Checking jackson-dataformat-cbor latest version ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.fasterxml.jackson.dataformat+AND+a:jackson-dataformat-cbor&rows=1" | jq -r '.response.docs[0] | "Latest Version: \(.latestVersion)"'

echo ""
echo "=== Checking cose-java latest version ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.augustcellars.cose+AND+a:cose-java&rows=1" | jq -r '.response.docs[0] | "Latest Version: \(.latestVersion)"'

echo ""
echo "=== Checking jackson-core for version mismatch ==="
curl -s "https://search.maven.org/solrsearch/select?q=g:com.fasterxml.jackson.core+AND+a:jackson-core&rows=1" | jq -r '.response.docs[0] | "Latest Version: \(.latestVersion)"'

Repository: mosip/vc-verifier

Length of output: 147


🌐 Web query:

jackson-dataformat-cbor latest version 2024 2025

💡 Result:

Latest released version (as of Dec 24, 2025): jackson-dataformat-cbor 2.20.1. [1][2]

References:

  • Maven Central listing (artifact directories). [1]
  • mvnrepository artifact page showing 2.20.1. [2]

🌐 Web query:

cose-java latest version security vulnerabilities

💡 Result:

Summary — cose-java (com.augustcellars.cose)

  • Latest released version: 1.1.0 (published Jan 27, 2020). [1][2]
  • There are no public CVEs reported against the cose-java codebase itself; however repository metadata and artifact pages show reported vulnerabilities in its dependencies (examples surfaced by Maven/SCA databases): CVE-2025-8916, CVE-2024-30171, CVE-2024-29857 (these are dependency/packaging-level findings surfaced on artifact pages). [2][3]
  • Common dependency issues referenced include older CBOR (upokecenter/com.upokecenter:cbor), BouncyCastle, and older cryptography helper libraries used by the project — these are the likely sources of the dependency CVE listings. [2][4]

Recommendations

  • If you use com.augustcellars.cose, audit your build-time/runtime dependencies (CBOR, BouncyCastle, EdDSA libs) and upgrade those transitive libs to patched versions. [2][4]
  • Consider using a maintained fork or alternate Java COSE implementations (e.g., se.digg.cose / cose‑lib) if you need more recent dependency updates and active maintenance. [5][6]
  • Run your own SCA (OSS vulnerability scanner) against the exact artifact/version you use to get a complete, current list of vulnerabilities affecting your environment.

Sources

  1. Maven Central / Javadoc showing cose-java 1.1.0 as current. [https://javadoc.io/doc/com.augustcellars.cose/cose-java] [2]
  2. Maven Repository artifact page for com.augustcellars.cose:cose-java (1.1.0) — lists dependency CVEs and dependency versions. [https://mvnrepository.com/artifact/com.augustcellars.cose/cose-java/1.1.0] [3]
  3. mvnrepository pages for older cose-java versions (dependency vulnerability details). [https://mvnrepository.com/artifact/com.augustcellars.cose/cose-java/1.0.0] [4]
  4. se.digg.cose / cose-lib (maintained fork/alternative) information. [https://mvnrepository.com/artifact/se.digg.cose/cose-lib] [5]

If you want, I can run a focused SCA for the specific version you use (give me the exact groupId:artifactId:version) and return the full list of matching CVEs and recommended fixed versions.


🌐 Web query:

jackson 2.17.2 2.14.0 version compatibility security CVE

💡 Result:

Short answer: 2.17.2 is newer and fixes multiple security issues present in older 2.14.x releases — use 2.17.2 (or later) for better CVE coverage.

Details (high‑level):

  • CVE-2023-35116 (DoS via crafted cyclic object) affects jackson-databind < 2.16.0, so 2.14.0 is affected and 2.17.2 is not. [1][2]
  • Jackson project patch/release notes show 2.17.2 is a security/bugfix patch on top of the 2.17 line (includes fixes not present in 2.14). Upgrading to the latest 2.17.x (or newer stable) is recommended. [3]
  • Many older deserialization/XXE/remote‑code‑execution CVEs historically impacted older jackson‑databind versions (examples documented by vendor/security advisories); staying on a maintained recent patch (2.17.2+ or later) reduces exposure. Verify your usage of features like DefaultTyping or polymorphic deserialization, which increase risk. [2][4]

Recommendations:

  • Upgrade 2.14.0 → 2.17.2 (or preferably the latest 2.17+ / 2.20+ available) and test. [3][4]
  • Audit uses of polymorphic typing/DefaultTyping, restrict class whitelist, and follow Jackson security guidance. (If you want, I can list exact CVEs that apply to 2.14.0 in your environment.)

Sources:
[1] MITRE/CVE-2023-35116 summary via CVE database.
[2] IBM/other security advisories referencing jackson-databind CVEs.
[3] Jackson Release 2.17.2 notes (FasterXML).
[4] CVEDetails / Snyk package vulnerability listings for Jackson versions.


Fix critical version mismatch and address unmaintained dependencies.

The versions require updates:

  • jackson-dataformat-cbor (2.17.2) is outdated; latest is 2.20.1. Upgrade recommended.
  • cose-java (1.1.0) is no longer actively maintained (released Jan 2020) and has reported dependency vulnerabilities (CVE-2025-8916, CVE-2024-30171, CVE-2024-29857). Consider migrating to a maintained COSE library such as se.digg.cose:cose-lib.
  • CRITICAL: The build.gradle.kts forces jackson-core:2.14.0, which is vulnerable to CVE-2023-35116 and incompatible with the other Jackson modules at 2.17.2. Remove the forced resolution and align all Jackson modules to 2.17.2 or upgrade to 2.20.1.
🤖 Prompt for AI Agents
In vc-verifier/kotlin/vcverifier/build.gradle.kts around lines 68-69, the
project includes outdated/unmaintained dependencies and forces a vulnerable
jackson-core version: update jackson-dataformat-cbor to the current release
(e.g., 2.20.1) and ensure all Jackson modules use the same 2.20.1 version
(remove any forced resolution to jackson-core:2.14.0), replace the unmaintained
cose-java dependency with a maintained COSE library such as
se.digg.cose:cose-lib (update coordinates and adapt code/usages accordingly),
and run a full build & tests to confirm no API mismatches and that the
CVE-vulnerable versions are removed.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Fix all issues with AI Agents 🤖
In @README.md:
- Line 61: The markdown list item `statusChecker` is indented with 4 spaces
instead of 2; update the README.md list so the `statusChecker` entry uses
2-space indentation to match the other list items, preserving the backticks and
list marker.

In @vc-verifier/kotlin/README.md:
- Around line 394-411: Update the example JSON to reflect an invalid VC: set
verificationResult.verificationStatus to false, populate
verificationResult.verificationErrorCode with a suitable code like
"ERR_VC_EXPIRED", and adjust verificationResult.verificationMessage to clearly
state the VC is expired (and revoked if you want to mention both); keep
credentialStatus.revocation.isValid as false to indicate revocation.
- Around line 42-43: Update the README table entry that references the SD-JWT VC
draft for `vc+sd-jwt`, `dc+sd-jwt` so the link points to the latest spec (change
the URL from draft-ietf-oauth-sd-jwt-vc/10 to draft-ietf-oauth-sd-jwt-vc-13);
locate the table row containing the symbols `vc+sd-jwt`, `dc+sd-jwt` and replace
the old draft link with the new draft-ietf-oauth-sd-jwt-vc-13 URL (published
November 2025).

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt:
- Around line 189-192: Remove the duplicate hexToBytes implementation from
CwtVerifer.kt and use the shared utility from Util.kt instead: delete the local
hexToBytes function in CwtVerifer.kt, add an import for the Util.hexToBytes (or
adjust package-import to access Util), and ensure callers such as
decodeCose(credential: String) call the imported Util.hexToBytes; rebuild to
confirm no unresolved references remain.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt:
- Around line 17-27: Remove the unused CBOR ObjectMapper field and the duplicate
hexToBytes function: delete the private val cborMapper =
ObjectMapper(CBORFactory()).registerKotlinModule() and remove the
hexToBytes(hex: String) method from CwtVerifer, and replace any calls (if
present) with the shared utility implementation in Util.kt (reuse the existing
hexToBytes there); also clean up any now-unused imports resulting from these
deletions.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt:
- Around line 47-48: The JSON extraction of verifiableCredentials in
PresentationVerifier.verify() (the
JSONObject(presentation).getJSONArray(Shared.KEY_VERIFIABLE_CREDENTIAL) call)
can throw JSONException and is not currently handled; wrap this access in a
try/catch for JSONException (or validate presence with has/optJSONArray) and on
failure throw the existing PresentationNotSupportedException (or return an empty
VC result list) so a malformed or missing verifiableCredential array doesn’t
propagate an unhandled exception after getPresentationVerificationStatus()
succeeds; apply the same pattern to the similar extraction site around
getVCVerificationResults() at the other occurrence (line ~179).

In
@vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt:
- Around line 267-295: The test `should return error when statusSize is zero or
negative` leaks the second MockWebServer because the second prepareVC call
destructures its server into `_`; capture it (e.g., val (replacedVCZero,
serverZero) = prepareVC(...)) and ensure you call serverZero.shutdown() (or wrap
both servers in a try/finally or use a resource block to shut down both servers)
so both MockWebServer instances started by prepareVC are properly closed.

In
@vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt:
- Around line 32-41: This test belongs to the wrong test class and unnecessarily
loads an SD-JWT file; move the test to a new MsoMdocVerifiableCredentialTest and
delete the SD-JWT file loading from the test in SdJwtVerifierTest: create a test
method in MsoMdocVerifiableCredentialTest that calls
MsoMdocVerifiableCredential().checkStatus(...) and asserts it throws
UnsupportedOperationException with the message "Credential status checking not
supported for this credential format" (no sdJwt.txt or SD-JWT content should be
used), and remove the entire misplaced test block from SdJwtVerifierTest.

In @vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mockDid.json:
- Around line 1-42: The file mockDid.json is missing a trailing newline; open
the test fixture "mockDid.json" (the DID document containing verificationMethod
entries like "RsaVerificationKey2018", "EcdsaSecp256k1VerificationKey2019", and
"Ed25519VerificationKey2020") and add a single newline character at the end of
the file so it ends with a newline per POSIX conventions.

In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedStatusList.json:
- Around line 1-25: The test fixture file mosipRevokedStatusList.json is missing
a trailing newline; open mosipRevokedStatusList.json and add a single newline
character at the end of the file so it ends with '\n' (ensure no other changes
to the JSON content).

In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedVC.json:
- Line 5: The test fixture contains a real email under the "email" key in
mosipUnrevokedVC.json; replace that PII with a clearly fake address (e.g.,
"test@example.com") to remove personal data; apply the same change to the other
fixture mentioned (VPWithRevokedVC.json) to ensure no real emails remain in test
resources.
- Line 51: The test fixture contains real PII in the "phone" property of
mosipUnrevokedVC.json; replace the real number "+919427357934" with an obviously
fake number (e.g., "+1-555-0100" or another reserved test number) so the "phone"
field in the fixture no longer contains real personal data.

In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEdPublicKey.json:
- Line 8: Replace the real email string "test@gmail.com" in the test resource
with a reserved test domain such as "test@example.com" (i.e., update the value
"test@gmail.com" in didEdPublicKey.json to "test@example.com") to avoid
referencing a real domain in test fixtures.

In @vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json:
- Line 60: The test fixture VPWithRevokedVC.json contains a realistic phone
number in the "phone" field; replace the current value "+919427357934" with an
obviously fake number (e.g., "+1-555-0100" or similar clearly test-only value)
so no real PII remains in the fixture.
- Line 14: Replace the real-looking email value in the VPWithRevokedVC.json test
fixture by using clearly fake/test data (e.g., change the "email" field value
from "siwer.km@gmail.com" to "test@example.com" or similar); update the "email"
property inside the JSON object in VPWithRevokedVC.json so no real PII remains,
and run tests to ensure the fixture is still valid.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

84-84: Update outdated API reference.

This line still references the old isRevoked(credential) method which was replaced by checkStatus() in this PR. The documentation should be updated to reflect the new status checking mechanism.

🔎 Proposed fix
-This class provides the primary interface for interacting with the library and encapsulates all the core functionalities 
-related to validating and verifying Verifiable Credentials (VCs). It also performs a revocation check by calling the method isRevoked(credential).
+This class provides the primary interface for interacting with the library and encapsulates all the core functionalities 
+related to validating and verifying Verifiable Credentials (VCs). It also performs credential status checks using the checkStatus() method.
🧹 Nitpick comments (15)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/VerifiableCredential.kt (1)

9-11: Clarify the semantics of the Map key in the return type.

The default implementation appropriately allows formats that don't support status checking to gracefully fail. However, the return type Map<String, CredentialStatusResult> lacks documentation about what the String key represents (e.g., status purpose name, credential ID, or status type).

Consider adding KDoc to clarify the key semantics, for example:

/**
 * Checks the status of a credential.
 * @param credential The credential to check
 * @param statusPurposes Optional list of status purposes to filter (e.g., "revocation", "suspension")
 * @return Map where keys are status purpose names and values are the corresponding status results
 */
fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
    throw UnsupportedOperationException("Credential status checking not supported for this credential format")
}
vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json (1)

112-112: Clarify the mock JWS payload.

The JWS contains "hello" as the payload, which is unconventional. If this is intentional mock data for testing, consider adding a comment in the test code that uses this fixture to clarify that this is a deliberately simplified test signature.

vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt (1)

13-17: Consider type-safe JSON parsing in test utilities.

The cast as Map<String, Any>? after readValue(responseJson, Map::class.java) suppresses type checking and could mask issues if test data doesn't match expected structure. While acceptable for test utilities, consider using a more specific type parameter or typed readValue overload for better compile-time safety.

🔎 Safer alternative
 fun mockHttpResponse(url: String, responseJson: String) {
     every { NetworkManagerClient.Companion.sendHTTPRequest(url, any()) } answers {
-        mapper.readValue(responseJson, Map::class.java) as Map<String, Any>?
+        mapper.readValue<Map<String, Any>>(responseJson)
     }
 }
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (1)

122-126: Remove unused variables.

header1 and headerValue are extracted but never used. This appears to be dead code.

🔎 Proposed fix
         val payloadBytes = coseObj[2].GetByteString()
-        val header1 = coseObj[0].GetByteString()
-        val headerValue = CBORObject.DecodeFromBytes(header1)
         val claims = CBORObject.DecodeFromBytes(payloadBytes)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)

177-183: Consider adding error logging for debugging.

The httpGet function silently swallows all exceptions, which may make debugging network issues difficult. Consider logging the error at DEBUG or TRACE level.

🔎 Proposed fix
+    private val logger = java.util.logging.Logger.getLogger(Util::class.java.name)
+
     fun httpGet(url: String): String? {
         return try {
             restTemplate.getForObject(url, String::class.java)
         } catch (e: Exception) {
+            logger.fine("HTTP GET failed for $url: ${e.message}")
             null
         }
     }
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt (1)

100-127: Good test coverage for credential status verification.

The new tests properly mock HTTP responses and verify the credential status flow.

Minor suggestion: On line 153, use assertTrue for consistency with line 126 which uses assertFalse:

🔎 Proposed fix
-        assertEquals(credentialStatusEntry.value.isValid, true)
+        assertTrue(credentialStatusEntry.value.isValid)

Also applies to: 129-154

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt (2)

31-32: Consider lazy initialization for test fixtures.

mockDidJson is initialized at class property level, which runs before @BeforeAll. While this works, consider using lateinit var with initialization in setup() for consistency and clearer test lifecycle.

🔎 Proposed fix
-    val didDocumentUrl = "https://mosip.github.io/inji-config/qa-inji1/mock/did.json"
-    val mockDidJson = readClasspathFile("ldp_vc/mockDid.json")
+    val didDocumentUrl = "https://mosip.github.io/inji-config/qa-inji1/mock/did.json"
+    lateinit var mockDidJson: String
 
     @BeforeAll
     fun setup() {
         mockkObject(NetworkManagerClient.Companion)
         Util.documentLoader = LocalDocumentLoader
+        mockDidJson = readClasspathFile("ldp_vc/mockDid.json")
     }

179-179: Remove redundant mock setup.

mockkObject(NetworkManagerClient.Companion) is already called in @BeforeAll (line 36). This duplicate call is unnecessary.

🔎 Proposed fix
-        mockkObject(NetworkManagerClient.Companion)
-
         mockHttpResponse(realUrl, mockStatusListJson)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (2)

163-168: Edge case: Credential expires exactly at current time.

The condition exp <= now treats a credential as expired when exp equals now. Typically, expiration checks use exp < now (strictly less than), meaning the credential is valid up to and including the expiration time. The current logic causes credentials to be considered expired one second earlier than expected.

🔎 Proposed fix
-        if (exp != null && exp <= now) {
+        if (exp != null && exp < now) {

204-207: Hex validation doesn't account for whitespace.

The isValidHex method rejects any whitespace, but hexToBytes in Util.kt (line 152) strips whitespace via cleanHex = hex.replace("\\s".toRegex(), ""). This inconsistency means a hex string with spaces would fail validation here but would be successfully decoded by hexToBytes.

🔎 Proposed fix
     private fun isValidHex(credential: String): Boolean {
-        val hexRegex = "^[0-9a-fA-F]+$".toRegex()
-        return credential.matches(hexRegex)
+        val cleanHex = credential.replace("\\s".toRegex(), "")
+        val hexRegex = "^[0-9a-fA-F]+$".toRegex()
+        return cleanHex.isNotEmpty() && cleanHex.matches(hexRegex)
     }
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt (1)

13-15: Remove empty setup() method.

The @BeforeEach method is empty and can be removed to reduce noise. As flagged by static analysis (detekt), empty blocks should be eliminated.

🔎 Proposed fix
-    @BeforeEach
-    fun setup() {
-    }
-
     private val validator = CwtValidator()
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt (3)

45-45: Remove empty default constructor.

As flagged by static analysis, an empty default constructor can be removed since the class has no constructor parameters.

🔎 Proposed fix
-class LdpStatusChecker() {
+class LdpStatusChecker {

145-150: Original exception cause is lost when re-throwing.

The catch block wraps the exception message but doesn't chain the original exception, losing the stack trace. This makes debugging network or parsing issues harder.

🔎 Proposed fix
         } catch (e: Exception) {
             throw StatusCheckException(
                 "Retrieval of the status list failed: ${e.message}",
-                STATUS_RETRIEVAL_ERROR
+                STATUS_RETRIEVAL_ERROR,
+                e
             )
         }

This requires StatusCheckException to accept a cause parameter. If it doesn't currently support this, consider adding it:

class StatusCheckException(
    val errorMessage: String,
    val errorCode: StatusCheckErrorCode,
    cause: Throwable? = null
) : Exception(errorMessage, cause)

265-265: Potential NPE when parsing statusListIndex.

If entry[STATUS_LIST_INDEX] is null (despite earlier validation), calling .toString().toInt() will throw. While validateCredentialStatusEntry checks for this, the validation uses toIntOrNull() which handles null/invalid values, but here the value is re-parsed without the same safety.

🔎 Proposed fix
-        val statusListIndex = entry[STATUS_LIST_INDEX].toString().toInt()
+        val statusListIndex = entry[STATUS_LIST_INDEX]?.toString()?.toIntOrNull()
+            ?: throw StatusCheckException(
+                "Invalid '$STATUS_LIST_INDEX'",
+                INVALID_INDEX
+            )
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt (1)

48-79: Consider extracting server shutdown to @AfterEach.

Multiple tests create MockWebServer instances and must remember to shut them down. Consider using a test-level field and shutting down in teardown() to prevent resource leaks if assertions fail before shutdown() is called.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6b6a8f and 392a035.

📒 Files selected for processing (51)
  • README.md
  • vc-verifier/kotlin/README.md
  • vc-verifier/kotlin/example/src/main/java/io/mosip/vccred/example/MainActivity.kt
  • vc-verifier/kotlin/vcverifier/publish-artifact.gradle
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/CredentialsVerifier.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialVerifierConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/StatusCheckerConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/VerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/LdpRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/MsoMdocRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/LdpVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/SdJwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/msomdoc/MsoMdocVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/RevocationCheckException.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/StatusCheckException.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/LocalDocumentLoader.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/StatusListRevocationCheckerTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/LdpVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/MsoMdocVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/utils/UtilsTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt
  • vc-verifier/kotlin/vcverifier/src/test/resources/contexts/mock-identity-context.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mockDid.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedStatusList.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedStatusList.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEcKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEdPublicKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didMosipKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey2.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/idaPublicKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithUnrevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didIdentityServiceKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didMockKey.json
💤 Files with no reviewable changes (8)
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialVerifierConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/msomdoc/MsoMdocVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/RevocationCheckException.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/utils/UtilsTest.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/SdJwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/LdpRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/StatusListRevocationCheckerTest.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/MsoMdocRevokeChecker.kt
✅ Files skipped from review due to trivial changes (9)
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/idaPublicKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didMosipKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/contexts/mock-identity-context.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didIdentityServiceKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEcKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedStatusList.json
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/LdpVerifierTest.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt
👮 Files not reviewed due to content moderation or server errors (1)
  • vc-verifier/kotlin/example/src/main/java/io/mosip/vccred/example/MainActivity.kt
🧰 Additional context used
🧬 Code graph analysis (4)
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt (1)
vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt (2)
  • readClasspathFile (8-9)
  • mockHttpResponse (13-17)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt (1)
  • isValid (57-60)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)
  • isValidUri (80-91)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (2)
  • hexToBytes (152-159)
  • httpGet (177-183)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)
  • decodeCose (189-192)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)
  • decodeCose (29-36)
  • hexToBytes (20-27)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (2)
  • validateNumericDate (161-175)
  • hexToBytes (152-159)
🪛 detekt (1.23.8)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt

[warning] 45-45: An empty default constructor can be removed.

(detekt.empty-blocks.EmptyDefaultConstructor)


[warning] 145-145: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt

[warning] 14-15: This empty block of code can be removed.

(detekt.empty-blocks.EmptyFunctionBlock)

🪛 Gitleaks (8.30.0)
vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json

[high] 114-114: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithUnrevokedVC.json

[high] 114-114: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 markdownlint-cli2 (0.18.1)
vc-verifier/kotlin/README.md

74-74: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


75-75: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


76-76: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


78-78: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


90-90: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


91-91: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


92-92: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


100-100: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


101-101: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


102-102: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


104-104: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


105-105: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


107-107: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


108-108: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


109-109: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


110-110: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


112-112: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


113-113: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


115-115: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


116-116: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


117-117: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


174-174: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


175-175: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


176-176: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


206-206: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


207-207: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


208-208: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


213-213: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


214-214: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


220-220: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


221-221: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


255-255: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


268-268: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


269-269: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


273-273: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


276-276: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


280-280: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


292-292: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


293-293: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


298-298: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


299-299: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


300-300: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


305-305: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


317-317: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


318-318: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


322-322: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


324-324: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


325-325: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


326-326: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


327-327: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


328-328: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


332-332: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


496-496: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


503-503: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


593-593: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


604-604: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


605-605: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


607-607: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


608-608: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


609-609: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


610-610: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


611-611: Unordered list indentation
Expected: 6; Actual: 12

(MD007, ul-indent)


627-627: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


741-741: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


784-784: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


793-793: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


833-833: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

README.md

61-61: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

🔇 Additional comments (36)
vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didMockKey.json (1)

1-42: LGTM! Well-structured DID Document for testing.

This test resource provides good coverage with three different verification key types (RSA, EC secp256k1, Ed25519), each using appropriate key representation formats. The structure follows DID Core specification conventions.

Minor: The file is missing a trailing newline, which is a common convention for text files and may be flagged by some linters.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/LocalDocumentLoader.kt (1)

45-46: LGTM! Clean addition following the established pattern.

The new context mapping follows the same pattern as all existing entries and correctly routes the mock-identity-context URL to the local test resource.

vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey2.json (1)

1-7: LGTM! Valid Ed25519 test fixture.

The JSON structure is well-formed and follows the W3C security vocabulary specification for Ed25519VerificationKey2018 keys. The PEM-encoded public key has the correct format and ASN.1 structure for Ed25519 keys, and the mock URLs are appropriate for a test resource.

vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEdPublicKey.json (1)

1-26: LGTM! DID document structure is valid.

The JSON structure correctly follows the W3C DID v1 specification for a did:web document with Ed25519VerificationKey2020. The verification method, authentication, and assertionMethod references are properly configured for test scenarios.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt (1)

3-7: LGTM: Explicit imports improve clarity.

Replacing wildcard imports with explicit imports is a good practice that enhances code readability.

vc-verifier/kotlin/vcverifier/publish-artifact.gradle (1)

99-99: LGTM! Version bump aligns with new features.

The version increment from 1.6.0-SNAPSHOT to 1.7.0-SNAPSHOT is appropriate for the new CWT verification and credential status checking features being introduced in this PR.

Also applies to: 113-113

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/MsoMdocVerifierTest.kt (5)

7-7: LGTM! Import supports the new test.

The import is required for the new credential status check test added at lines 105-112.


18-19: Good refactoring! Credential constant improves maintainability.

Extracting the credential string into a reusable constant follows the DRY principle and makes the test code cleaner.


21-25: LGTM! Proper test initialization.

Mocking BuildConfig.version in the setup ensures consistent test behavior across different SDK environments.


35-35: LGTM! Using the extracted constant.

This change leverages the validMdoc constant defined above, improving code maintainability.


105-112: LGTM! Validates unsupported operation behavior.

The test correctly verifies that checkStatus throws UnsupportedOperationException with the expected message for the MSO-MDOC credential format, which doesn't support credential status checking.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/VerifiableCredential.kt (1)

3-3: LGTM!

The import for CredentialStatusResult is correctly added to support the new status checking functionality.

README.md (2)

41-41: LGTM!

The updated terminology "Status Check" correctly reflects the broader capability beyond just revocation checking.


46-52: LGTM!

The table updates correctly reflect:

  • Addition of EcdsaSecp256k1Signature2019 support for ldp_vc format
  • Clarification that SD-JWT formats use algorithm headers rather than named signature suites
vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithUnrevokedVC.json (1)

1-116: LGTM - Gitleaks warning is a false positive.

The Gitleaks warning on line 114 is a false positive. The flagged value is a DID identifier (did:key:z6Mkp...), which is a public decentralized identifier, not an API key or secret. Similarly, the JWS signature on line 112 is public cryptographic proof data.

This test fixture correctly represents a Verifiable Presentation with an embedded credential that has status checking capabilities, supporting the new status verification flows.

vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json (1)

114-114: Static analysis false positive - safe to ignore.

The static analysis tool flagged this line as containing a generic API key, but this is a W3C DID (Decentralized Identifier) which is a public identifier, not a secret. This can be safely ignored.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt (1)

17-20: LGTM - Well-structured status checking data model.

The new data classes properly separate verification results from status checking results, use immutable fields (val), and handle error cases appropriately with nullable StatusCheckException. The design aligns well with the status-check subsystem introduced in this PR.

Also applies to: 27-31, 57-65

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/LdpVerifiableCredential.kt (1)

19-21: LGTM - Clean refactoring to status checking.

The replacement of isRevoked() with checkStatus() properly delegates to the new LdpStatusChecker and returns richer status information via Map<String, CredentialStatusResult>, supporting multiple status purposes. This aligns well with the new status-check subsystem introduced in this PR.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/StatusCheckException.kt (1)

1-16: LGTM!

The exception class and error code enum are well-structured. The error codes cover the expected failure scenarios for credential status checking.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)

29-36: LGTM on core verification logic.

The critical bugs from previous reviews have been addressed:

  • decodeCose now correctly returns the decoded CBORObject
  • fetchPublicKey now properly converts JWK to PublicKey
  • verify now returns the verifySignature result

The verification flow is well-structured with appropriate null-safety handling.

Also applies to: 118-135


15-15: Fix typo in class name: CwtVeriferCwtVerifier.

The class name is missing an 'i'. Also update the filename to match.

Likely an incorrect or invalid review comment.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (2)

36-37: LGTM on RestTemplate singleton.

RestTemplate is thread-safe for concurrent use. Using a single instance is appropriate for this utility object.


152-175: LGTM!

Both utility functions are well-implemented:

  • hexToBytes properly validates input and handles whitespace
  • validateNumericDate correctly validates CBOR integer types for numeric dates
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt (1)

30-39: LGTM!

Test setup and teardown are properly implemented. The mock configuration using mockkObject(NetworkManagerClient) is correct for mocking companion object methods.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/StatusCheckerConstants.kt (1)

1-13: LGTM!

Constants are well-organized and properly named for the BitstringStatusList credential format. Using const val ensures compile-time constants.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/CredentialsVerifier.kt (2)

18-18: Good refactor: Factory instance reuse.

Creating the CredentialVerifierFactory as a class field instead of instantiating it in each method is a good optimization that avoids redundant object creation.


76-104: LGTM on new public API methods.

The new getCredentialStatus and verifyAndGetCredentialStatus methods are well-designed:

  • Graceful handling of UnsupportedOperationException for formats without status support
  • Status is only fetched when verification succeeds, avoiding unnecessary work
  • Sensible default parameter for statusPurposeList
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt (1)

157-228: Good test coverage for credential status verification.

The three new tests comprehensively cover:

  1. Empty status when verification fails
  2. Valid (unrevoked) credential status
  3. Invalid (revoked) credential status

Each test properly mocks external dependencies and validates the expected behavior.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)

24-59: Well-structured validation flow with clear error handling.

The validation pipeline follows a logical sequence: empty check → hex validation → COSE structure → protected header → CWT claims → date validation. The try-catch structure correctly maps ValidationException to ValidationStatus while catching unexpected exceptions with a generic error.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt (1)

34-151: Good test coverage addressing prior review feedback.

The test class now provides comprehensive coverage for CwtValidator scenarios including empty input, invalid hex, COSE structure validation, ALG type checking, payload validation, missing headers, temporal claims (exp, nbf, iat), and a positive path test. This addresses the previous review comment about the empty test class.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt (2)

162-171: New status-aware VC verification follows established patterns.

The getVCVerificationResultsWithCredentialStatus method correctly delegates to credentialsVerifier.verifyAndGetCredentialStatus() and maps results to the new VCResultWithCredentialStatus type. The implementation is consistent with the existing getVCVerificationResults method.


173-183: Clean API extension for credential status retrieval.

The new verifyAndGetCredentialStatus method provides a natural extension to the existing verify API, with sensible defaults (statusPurposeList = emptyList()). The implementation reuses the extracted helper methods appropriately.

vc-verifier/kotlin/README.md (1)

1-848: Comprehensive documentation update.

The README now provides thorough coverage of supported formats, validation/verification flows, credential status checking, API references, and error codes. The addition of example JSON responses and feature matrices improves developer experience significantly.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt (2)

362-388: Well-implemented bit extraction logic.

The readBits and readBit methods correctly handle multi-bit status values with proper bounds checking. The bit ordering (MSB first within the status value) aligns with the StatusList2021 specification.


169-170: Read validFrom and validUntil from credential root, not credentialSubject.

Per W3C VC Data Model and StatusList2021 specifications, validFrom and validUntil are properties at the credential root level indicating the validity period of the status list itself. The code currently reads these from credentialSubject (lines 169–170), but should access them from statusListVC.jsonObject instead.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt (1)

81-453: Comprehensive test coverage for status checking scenarios.

The test suite covers a wide range of scenarios including:

  • Valid/revoked credential detection
  • Missing/invalid credentialStatus handling
  • Range errors for statusListIndex
  • Encoding/decoding failures (Base64, GZIP)
  • Purpose mismatches
  • Temporal validation (validFrom/validUntil)
  • statusSize and statusMessage validation

This provides good confidence in the LdpStatusChecker implementation.

- `types`
- `validator`
- `verifier`
- `statusChecker`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix markdown list indentation.

The indentation should be 2 spaces to match the other list items, not 4 spaces.

🔎 Proposed fix
-    - `statusChecker`
+  - `statusChecker`
📝 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
- `statusChecker`
- `statusChecker`
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

61-61: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

🤖 Prompt for AI Agents
In @README.md around line 61, The markdown list item `statusChecker` is indented
with 4 spaces instead of 2; update the README.md list so the `statusChecker`
entry uses 2-space indentation to match the other list items, preserving the
backticks and list marker.

Comment on lines +42 to +43
| `vc+sd-jwt`, `dc+sd-jwt` | [IETF SD-JWT based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/10/) |

Copy link

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

🌐 Web query:

latest version IETF SD-JWT VC draft specification 2025

💡 Result:

The latest IETF SD-JWT VC draft (2025) is draft-ietf-oauth-sd-jwt-vc-13, published November 2025 (expires 10 May 2026). [1]

Sources: IETF Datatracker entry for draft-ietf-oauth-sd-jwt-vc-13. [1]


🏁 Script executed:

# Search for SD-JWT version references in the kotlin codebase
rg "sd-jwt|SD-JWT" --type kotlin -i -A 3 -B 3

Repository: inji/vc-verifier

Length of output: 12923


🏁 Script executed:

# Look for any version specifications in build files or configuration
fd "build\|pom\|gradle\|package" --type f | xargs rg "sd-jwt" -i 2>/dev/null || true

Repository: inji/vc-verifier

Length of output: 8438


🏁 Script executed:

# Check for any explicit version references in the kotlin directory
fd . vc-verifier/kotlin --type f | xargs rg "draft-ietf-oauth-sd-jwt|10\|11\|12" 2>/dev/null || true

Repository: inji/vc-verifier

Length of output: 266


Update documentation to reference the latest IETF SD-JWT VC specification draft.

The README currently references draft-ietf-oauth-sd-jwt-vc/10, but the latest version is draft-ietf-oauth-sd-jwt-vc-13 (published November 2025). Update the link to point to the current specification.

🤖 Prompt for AI Agents
In @vc-verifier/kotlin/README.md around lines 42-43, Update the README table
entry that references the SD-JWT VC draft for `vc+sd-jwt`, `dc+sd-jwt` so the
link points to the latest spec (change the URL from
draft-ietf-oauth-sd-jwt-vc/10 to draft-ietf-oauth-sd-jwt-vc-13); locate the
table row containing the symbols `vc+sd-jwt`, `dc+sd-jwt` and replace the old
draft link with the new draft-ietf-oauth-sd-jwt-vc-13 URL (published November
2025).

Comment on lines 17 to 27
private val cborMapper = ObjectMapper(CBORFactory())
.registerKotlinModule()

fun hexToBytes(hex: String): ByteArray {
val cleanHex = hex.replace("\\s".toRegex(), "")
require(cleanHex.length % 2 == 0) { "Invalid hex length" }

return ByteArray(cleanHex.length / 2) { i ->
cleanHex.substring(i * 2, i * 2 + 2).toInt(16).toByte()
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove unused field and duplicate function.

  1. cborMapper (lines 17-18) is never used in this class.
  2. hexToBytes duplicates the existing utility in Util.kt (lines 151-158).
🔎 Proposed fix

Remove the unused mapper and import the utility function:

+import io.mosip.vercred.vcverifier.utils.Util.hexToBytes
 
 class CwtVerifer {
-
-    private val cborMapper = ObjectMapper(CBORFactory())
-        .registerKotlinModule()
-
-    fun hexToBytes(hex: String): ByteArray {
-        val cleanHex = hex.replace("\\s".toRegex(), "")
-        require(cleanHex.length % 2 == 0) { "Invalid hex length" }
-
-        return ByteArray(cleanHex.length / 2) { i ->
-            cleanHex.substring(i * 2, i * 2 + 2).toInt(16).toByte()
-        }
-    }

Also remove unused imports:

-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.dataformat.cbor.CBORFactory
-import com.fasterxml.jackson.module.kotlin.registerKotlinModule

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt
around lines 17-27, Remove the unused CBOR ObjectMapper field and the duplicate
hexToBytes function: delete the private val cborMapper =
ObjectMapper(CBORFactory()).registerKotlinModule() and remove the
hexToBytes(hex: String) method from CwtVerifer, and replace any calls (if
present) with the shared utility implementation in Util.kt (reuse the existing
hexToBytes there); also clean up any now-unused imports resulting from these
deletions.

Comment on lines +47 to +48
val verifiableCredentials = JSONObject(presentation).getJSONArray(Shared.KEY_VERIFIABLE_CREDENTIAL)
val vcVerificationResults: List<VCResult> = getVCVerificationResults(verifiableCredentials)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

JSON parsing not wrapped in error handling.

JSONObject(presentation).getJSONArray(...) can throw JSONException if the presentation is malformed or missing the verifiableCredential key. In verify(), this happens after getPresentationVerificationStatus() which already handles JSON parsing failures via PresentationNotSupportedException. However, if the proof verification succeeds but the verifiableCredential array is missing, an unhandled exception will propagate.

Consider wrapping the JSON access or validating the structure earlier in the flow.

Also applies to: 179-179

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt
around lines 47-48, The JSON extraction of verifiableCredentials in
PresentationVerifier.verify() (the
JSONObject(presentation).getJSONArray(Shared.KEY_VERIFIABLE_CREDENTIAL) call)
can throw JSONException and is not currently handled; wrap this access in a
try/catch for JSONException (or validate presence with has/optJSONArray) and on
failure throw the existing PresentationNotSupportedException (or return an empty
VC result list) so a malformed or missing verifiableCredential array doesn’t
propagate an unhandled exception after getPresentationVerificationStatus()
succeeds; apply the same pattern to the similar extraction site around
getVCVerificationResults() at the other occurrence (line ~179).

Comment on lines +1 to +25
{
"credentialSubject": {
"statusPurpose": "revocation",
"id": "https://injicertify-mock.qa-inji1.mosip.net/v1/certify/credentials/status-list/56622ad1-c304-4d7a-baf0-08836d63c2bf",
"type": "BitstringStatusList",
"encodedList": "uH4sIAAAAAAAA_-3OMQ0AIRQFQS6hoDwJSEU6GgjJfwUzBnZbAwAAAACgwEgPAG_6K2OrMgYAwJ0vPQBAnZ4eAAA4NNMDAAAASRupW2djAEAAAA"
},
"id": "https://injicertify-mock.qa-inji1.mosip.net/v1/certify/credentials/status-list/56622ad1-c304-4d7a-baf0-08836d63c2bf",
"validFrom": "2025-11-11T07:29:00.054Z",
"proof": {
"proofValue": "z2P8k8zWJ9st2hHCir7gjWs1JxznsdsBvKXNuaeN7kmrTqHaA6srziB5kZahz2iC2TsKsJ6FUniwPtAKKA2mvNmr",
"created": "2025-11-11T07:29:00Z",
"proofPurpose": "assertionMethod",
"type": "Ed25519Signature2020",
"verificationMethod": "did:web:mosip.github.io:inji-config:qa-inji1:mock#kMVyZTvx8G0h1YZnUW4OJtr2LRVZUuGl8pQuJl3ymXI"
},
"type": [
"VerifiableCredential",
"BitstringStatusListCredential"
],
"@context": [
"https://www.w3.org/ns/credentials/v2"
],
"issuer": "did:web:mosip.github.io:inji-config:qa-inji1:mock"
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add newline at end of file.

This test fixture is missing a newline at the end of the file. While this doesn't affect JSON parsing, it's best practice to end files with a newline character per POSIX standards.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedStatusList.json
around lines 1-25, The test fixture file mosipRevokedStatusList.json is missing
a trailing newline; open mosipRevokedStatusList.json and add a single newline
character at the end of the file so it ends with '\n' (ensure no other changes
to the JSON content).

"credentialSubject": {
"dateOfBirth": "1999/10/21",
"UIN": 123456,
"email": "siwer.km@gmail.com",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove PII from test fixtures.

Same issue as VPWithRevokedVC.json: use clearly fake email addresses (e.g., "test@example.com") to avoid compliance risks.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedVC.json
around line 5, The test fixture contains a real email under the "email" key in
mosipUnrevokedVC.json; replace that PII with a clearly fake address (e.g.,
"test@example.com") to remove personal data; apply the same change to the other
fixture mentioned (VPWithRevokedVC.json) to ensure no real emails remain in test
resources.

}
],
"id": "did:jwk:eyJrdHkiOiJPS1AiLCJ1c2UiOiJzaWciLCJjcnYiOiJFZDI1NTE5IiwieCI6IlVFSWlCZXk3Y0xUakNxZVZpejZBWFFEV2lvR2pNNXo0M21qV3NCTjRwTTgifQ==",
"phone": "+919427357934",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove PII from test fixtures.

Same issue as VPWithRevokedVC.json: use obviously fake phone numbers (e.g., "+1-555-0100") to avoid compliance concerns.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedVC.json
around line 51, The test fixture contains real PII in the "phone" property of
mosipUnrevokedVC.json; replace the real number "+919427357934" with an obviously
fake number (e.g., "+1-555-0100" or another reserved test number) so the "phone"
field in the fixture no longer contains real personal data.

"id": "did:web:vharsh.github.io:DID:local",
"alsoKnownAs": [
"testUUID",
"test@gmail.com"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider using a reserved test domain.

The email "test@gmail.com" references a real domain. For test resources, it's better practice to use reserved test domains like "test@example.com" per RFC 2606 to avoid any potential confusion or privacy concerns.

🔎 Suggested fix
-    "test@gmail.com"
+    "test@example.com"
📝 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
"test@gmail.com"
"test@example.com"
🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEdPublicKey.json
around line 8, Replace the real email string "test@gmail.com" in the test
resource with a reserved test domain such as "test@example.com" (i.e., update
the value "test@gmail.com" in didEdPublicKey.json to "test@example.com") to
avoid referencing a real domain in test fixtures.

"credentialSubject": {
"dateOfBirth": "1999/10/21",
"UIN": 123456,
"email": "siwer.km@gmail.com",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove PII from test fixtures.

The email address appears to be real or realistic personal data. Test fixtures should use clearly fake data (e.g., "test@example.com") to avoid compliance risks.

Based on the AI summary, this PR introduces status-check and revocation-related components that handle sensitive credential data. Ensuring test data does not contain real PII is essential for GDPR/CCPA compliance.

🤖 Prompt for AI Agents
In @vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json
around line 14, Replace the real-looking email value in the VPWithRevokedVC.json
test fixture by using clearly fake/test data (e.g., change the "email" field
value from "siwer.km@gmail.com" to "test@example.com" or similar); update the
"email" property inside the JSON object in VPWithRevokedVC.json so no real PII
remains, and run tests to ensure the fixture is still valid.

jaswanthkumartw and others added 6 commits January 6, 2026 09:41
Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
* [INJIMOB-3591] refactor revokechecker to statuschecker

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3591] add validations for status check

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3591] expose method for getting verification result and status as verfication summary

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3581] replace expired mso_mdoc vc

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3581] rename verifyAndGetStatus to verifyAndGetCredentialStatus and refactor

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

---------

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
…nji#205)

* [INJIVER-1400] - support revocation in presentationVerifier

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - add test for revocation

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - Add PresentationResultWithCredentialStatus and VCResultWithCredentialStatus data classes

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - add mock-identity and w3v1 context mappings

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - add VPWithRevokedVC json

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - add VPWithUnrevokedVC json

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - add context json

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - remove w3v1 context

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - rename presentationVerificationStatus to getPresentationVerificationStatus

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - rename tests and add VP verification check

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - Remove handling of VC_REVOKED error code

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - Remove unused import

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - Remove test for VC_Revoked error code

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - Remove constants ERROR_CODE_VC_REVOKED

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - extract verifiableCredentials

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

* [INJIVER-1400] - update version to 1.7.0-snapshot

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>

---------

Signed-off-by: sarupmoni <93664377+sarupmoni@users.noreply.github.com>
Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
…tus check (inji#211)

* [INJIMOB-3647] refactor: enhance response structure of credential status check (inji#207)

* [INJIMOB-3647] refactor: remove getting ldp class from factory in LdpStatusChecker

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: remove unused variable

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: throw error for unsupported status check instead of returning null

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: modify CredentialStatusResult structure

CredentialStatusResult has 2 params
1. purpose
2. result -> This holds a boolean of iSuccess and error of type StatusCheckException for any failure

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: extract magic numbers to const in status checker

Other changes:
- add info logs to print status message for avoiding loss of data

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: change Result's isSuccess to isValid

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: update ldp status check to return empty list when not applicable

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: modify error code for - invalid credential status

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: update isValid function

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] enhance readme

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* Revert "[INJIMOB-3647] enhance readme"

This reverts commit 1f3aa8c.

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3647] enhance readme

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3647] refactor: modify CredentialVerificationSummary data type

CredentialVerificationSummary -> has verification result and credential status
- credentialStatus will now be holding a map of purpose to its relative result instead of a list of (purpose + result)

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] test: mock did web url responses

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: update PresentationVerifier to use updated Credential summary result class

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] enhance readme

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3647] refactor: remove unused exception

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: CredentialVerificationSummary - credentialStatus

credentialStatus is a map of purpose to its CredentialStatusResult. CredentialStatusResult holds isValid and error

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] test: reuse extracted test utils for reading resource files

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] enhance readme

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3647] test: mock all network calls in verifier test

Mock context and https / did web public key loading

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] docs: fix typo in readme

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

---------

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Co-authored-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3647] enhance readme47] enhance readme

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

---------

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Co-authored-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🤖 Fix all issues with AI Agents
In @vc-verifier/kotlin/gradle/libs.versions.toml:
- Around line 23-24: You upgraded jacksonAnnotations and jacksonModuleKotlin to
2.17.2; before merging, run the full test suite and explicitly verify
breaking-change areas: confirm StreamReadConstraints limits won't reject large
strings/deep nesting or set custom StreamReadConstraints in Jackson
configuration; audit any uses of JsonNode.with() for keys starting with "/" and
update callers expecting literal "/" behavior; re-test places using
@JsonIgnore/@JsonProperty to ensure precedence changes don't break mappings;
exercise all enum (serialize/deserialize) paths and @JsonTypeInfo polymorphic
deserialization to catch behavioral changes; verify Kotlin compatibility (module
requires Kotlin >=1.5), and check the dependency tree for transitive changes
(SnakeYAML/Guava/Woodstox) that could cause conflicts. Ensure CI includes JSON
parsing tests for large/nested payloads, enum cases, and polymorphic types
before approving the version bump of jacksonAnnotations and jacksonModuleKotlin.

In @vc-verifier/kotlin/README.md:
- Around line 394-411: The example JSON in README uses
verificationResult.verificationStatus: true while describing an expired &
revoked VC; update the example so verificationResult.verificationStatus is
false, set verificationResult.verificationErrorCode to a suitable code (e.g.,
"EXPIRED") and keep verificationResult.verificationMessage as "VC is expired",
and ensure credentialStatus.revocation.isValid remains false to reflect
revocation.
- Line 42: Update the SD-JWT VC spec link and label in the README table entry
for `vc+sd-jwt`, `dc+sd-jwt` to point to the latest draft (change the URL from
draft-ietf-oauth-sd-jwt-vc/10 to draft-ietf-oauth-sd-jwt-vc-13) and, if present,
update any displayed version number text to "-13" or remove the version suffix
so it reflects the current draft; modify the table row containing the string
`vc+sd-jwt`, `dc+sd-jwt` and the linked URL to use the new draft URL.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt:
- Around line 18-20: The CwtVerifiableCredential.checkStatus override currently
returns an empty map which contradicts the interface's default behavior; change
the implementation in CwtVerifiableCredential.checkStatus to throw
UnsupportedOperationException (or, if you prefer the empty-map semantics, add
clear javadoc to the method stating that an empty map denotes "not supported"
for CWT), but prefer throwing UnsupportedOperationException to align with the
interface contract so callers receive a clear error when status checking isn't
supported by CWT.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/LdpVerifiableCredential.kt:
- Around line 19-21: Add a Breaking Changes entry in README.md documenting that
the LdpVerifiableCredential API changed: the old isRevoked(credential: String):
Boolean method was removed and replaced by checkStatus(credential: String,
statusPurposes: List<String>?): Map<String, CredentialStatusResult>; explain how
callers should migrate by replacing boolean checks with calls to
LdpVerifiableCredential.checkStatus, passing any relevant statusPurposes (or
null) and inspecting the returned Map<String, CredentialStatusResult> for the
credential's status (e.g., map lookup for the expected purpose and interpreting
CredentialStatusResult fields), and include a short example snippet and notes
about nullability of statusPurposes and how multiple purposes are represented in
the map.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt:
- Around line 20-27: The file defines a duplicate hexToBytes function; remove
this local hexToBytes and update decodeCose to call the shared utility
implementation (the hexToBytes in Util.kt) instead; also remove any now-unused
imports brought in solely for the duplicate function so the file compiles
without warnings.
- Around line 122-125: In CwtVerifer.kt remove the dead code that extracts and
decodes the COSE header: delete the unused variables header1 and headerValue and
the call that decodes header1 (the lines declaring header1 and headerValue and
CBORObject.DecodeFromBytes(header1)); keep only payloadBytes and claims
decoding, and remove any now-unused imports if needed.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt:
- Around line 162-170: The method getVCVerificationResultsWithCredentialStatus
currently hardcodes CredentialFormat.LDP_VC which breaks verification for
non-LDP credentials; update it to detect the credential format per item (e.g.,
implement a detectCredentialFormat(credentialJsonString): CredentialFormat) and
pass that detected format into credentialsVerifier.verifyAndGetCredentialStatus
instead of CredentialFormat.LDP_VC, leaving the rest of the mapping to construct
VCResultWithCredentialStatus unchanged.

In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt:
- Around line 177-183: The httpGet function currently swallows all exceptions;
add logging so failures are visible: import org.slf4j.LoggerFactory, declare a
logger for Util (e.g., private val logger =
LoggerFactory.getLogger(Util::class.java) or similar), and inside the catch in
httpGet(url: String) log an error including the url and the exception (e.g.,
logger.error("HTTP GET failed for url: $url", e)) before returning null; keep
the method signature and restTemplate.getForObject usage unchanged.
- Line 36: The RestTemplate instance declared as val restTemplate =
RestTemplate() in Util.kt has no timeouts configured and can hang; replace it
with a RestTemplate configured with sensible connection and read/socket timeouts
(e.g., via RestTemplateBuilder or by creating an
HttpComponentsClientHttpRequestFactory/OkHttp3ClientHttpRequestFactory and
setting connect and read timeouts) and use that configured instance everywhere
the restTemplate variable is referenced; ensure the chosen timeout values are
reasonable for your environment and include them when constructing the
RestTemplate.

In
@vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt:
- Around line 267-295: Test leaks the second MockWebServer because
prepareVC(...) for the zero case discards the server; capture that server (e.g.,
val (replacedVCZero, serverZero) = prepareVC(statusListJson =
statusListJsonZero)) and call serverZero.shutdown() at the end (or shut both
down in a finally/tearDown block). Update the underscore in the second prepareVC
call to a named variable and ensure shutdown is invoked to close the resource.

In
@vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt:
- Around line 32-41: The test asserting UnsupportedOperationException for
MsoMdocVerifiableCredential.checkStatus is misplaced in SdJwtVerifierTest and
unnecessarily reads an SD-JWT file; move the entire test to a new test class
MsoMdocVerifiableCredentialTest (create file/class named
MsoMdocVerifiableCredentialTest) and remove the ResourceUtils file-loading lines
(the lines that set file and vc); call MsoMdocVerifiableCredential().checkStatus
with a simple placeholder (e.g., empty string) or null for the VC parameter and
keep the assertThrows and assertEquals checking the message unchanged.

In @vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json:
- Line 60: The test fixture contains real-looking PII in the "phone" JSON field;
replace the value in the VPWithRevokedVC fixture's "phone" key with an obviously
fake number (e.g., "+1-555-0100") to remove personal data, ensuring any other
test assertions still accept the updated fake value.
🧹 Nitpick comments (8)
vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/idaPublicKey.json (1)

7-7: Consider adding a trailing newline.

The file ends without a trailing newline. While not critical, many coding standards and version control systems prefer files to end with a newline character.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt (1)

15-19: Remove unnecessary semicolons.

Kotlin doesn't require semicolons at the end of statements. Remove them for idiomatic Kotlin code.

🔎 Proposed fix
     override fun verify(credential: String): Boolean {
-        return CwtVerifer().verify(credential);
+        return CwtVerifer().verify(credential)
     }

     override fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
-        return emptyMap();
+        return emptyMap()
     }
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (1)

118-135: Remove unnecessary semicolons.

Kotlin doesn't require semicolons. Remove them for idiomatic code.

🔎 Proposed fix
     fun verify(credential: String): Boolean {
-        val coseObj = decodeCose(credential) ?: return false;
-        if (!isValidCoseStructure(coseObj)) return false;
+        val coseObj = decodeCose(credential) ?: return false
+        if (!isValidCoseStructure(coseObj)) return false

         val payloadBytes = coseObj[2].GetByteString()
-        val header1 = coseObj[0].GetByteString()
-        val headerValue = CBORObject.DecodeFromBytes(header1)
         val claims = CBORObject.DecodeFromBytes(payloadBytes)
-        if (!isValidCwtStructure(claims)) return false;
+        if (!isValidCwtStructure(claims)) return false

-        val issuer = extractIssuer(claims) ?: return false;
+        val issuer = extractIssuer(claims) ?: return false

-        val issuerMetadata = resolveIssuerMetadata(issuer) ?: return false;
+        val issuerMetadata = resolveIssuerMetadata(issuer) ?: return false

-        val publicKey = fetchPublicKey(coseObj, issuerMetadata) ?: return false;
+        val publicKey = fetchPublicKey(coseObj, issuerMetadata) ?: return false

         return verifySignature(coseObj, publicKey)
     }
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)

204-207: Consider validating hex string length is even.

isValidHex only checks for valid hex characters but doesn't verify the string has even length. While hexToBytes in Util.kt does have a require(cleanHex.length % 2 == 0) check, validating upfront would provide a clearer error message.

🔎 Proposed fix
 private fun isValidHex(credential: String): Boolean {
     val hexRegex = "^[0-9a-fA-F]+$".toRegex()
-    return credential.matches(hexRegex)
+    return credential.length % 2 == 0 && credential.matches(hexRegex)
 }
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt (1)

13-15: Remove empty @BeforeEach method.

The empty setup() method adds no value. Based on static analysis hints, this should be removed.

🔎 Proposed fix
-    @BeforeEach
-    fun setup() {
-    }
-
     private val validator = CwtValidator()
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt (1)

265-265: Consider using safe parsing for consistency.

While validateCredentialStatusEntry ensures STATUS_LIST_INDEX is valid, using toInt() directly could still throw if the map entry is modified concurrently. Using toIntOrNull() with a fallback would be more defensive.

🔎 Proposed fix
-        val statusListIndex = entry[STATUS_LIST_INDEX].toString().toInt()
+        val statusListIndex = entry[STATUS_LIST_INDEX]?.toString()?.toIntOrNull()
+            ?: throw StatusCheckException(
+                "Invalid '$STATUS_LIST_INDEX'",
+                INVALID_INDEX
+            )
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt (2)

40-43: Complete the test cleanup by unmocking NetworkManagerClient.

The teardownAll() method resets the documentLoader but doesn't unmock NetworkManagerClient.Companion that was mocked in setup() (line 36). This could cause test pollution if other tests interact with NetworkManagerClient.

🔎 Proposed fix
 @AfterAll
 fun teardownAll() {
     Util.documentLoader = null
+    unmockkAll()
 }

179-179: Remove redundant mockkObject call.

The mockkObject(NetworkManagerClient.Companion) call is redundant since it's already executed in the setup() method (line 36) which runs once before all tests due to the @BeforeAll annotation.

🔎 Proposed fix
-        mockkObject(NetworkManagerClient.Companion)
-
         mockHttpResponse(realUrl, mockStatusListJson)
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 392a035 and 0fab654.

📒 Files selected for processing (55)
  • README.md
  • vc-verifier/kotlin/README.md
  • vc-verifier/kotlin/example/src/main/java/io/mosip/vccred/example/MainActivity.kt
  • vc-verifier/kotlin/gradle/libs.versions.toml
  • vc-verifier/kotlin/vcverifier/build.gradle.kts
  • vc-verifier/kotlin/vcverifier/publish-artifact.gradle
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/CredentialsVerifier.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialFormat.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialVerifierConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/StatusCheckerConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/CredentialVerifierFactory.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/VerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/LdpRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/MsoMdocRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/LdpVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/SdJwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/msomdoc/MsoMdocVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/RevocationCheckException.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/StatusCheckException.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/LocalDocumentLoader.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/StatusListRevocationCheckerTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/LdpVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/MsoMdocVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/utils/UtilsTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt
  • vc-verifier/kotlin/vcverifier/src/test/resources/contexts/mock-identity-context.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mockDid.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedStatusList.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedStatusList.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEcKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEdPublicKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didMosipKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey2.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/idaPublicKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithUnrevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didIdentityServiceKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didMockKey.json
💤 Files with no reviewable changes (8)
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/utils/UtilsTest.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/RevocationCheckException.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/SdJwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/msomdoc/MsoMdocVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/LdpRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialVerifierConstants.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/MsoMdocRevokeChecker.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/revocation/StatusListRevocationCheckerTest.kt
✅ Files skipped from review due to trivial changes (1)
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didMosipKey.json
🚧 Files skipped from review as they are similar to previous changes (16)
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedVC.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didMockKey.json
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/MsoMdocVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEdPublicKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mockDid.json
  • vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialFormat.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/CredentialVerifierFactory.kt
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey2.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedStatusList.json
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/LocalDocumentLoader.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/CredentialValidatorConstants.kt
  • vc-verifier/kotlin/vcverifier/src/test/resources/vp/public_key/didIdentityServiceKey.json
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/PresentationVerifierTest.kt
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/httpsMockKey.json
  • vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipUnrevokedStatusList.json
👮 Files not reviewed due to content moderation or server errors (1)
  • vc-verifier/kotlin/example/src/main/java/io/mosip/vccred/example/MainActivity.kt
🧰 Additional context used
🧬 Code graph analysis (5)
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/LdpVerifierTest.kt (1)
vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt (2)
  • mockHttpResponse (13-17)
  • readClasspathFile (8-9)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)
  • decodeCose (29-36)
  • hexToBytes (20-27)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (2)
  • validateNumericDate (161-175)
  • hexToBytes (152-159)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (2)
  • hexToBytes (152-159)
  • httpGet (177-183)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (1)
  • decodeCose (189-192)
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt (1)
vc-verifier/kotlin/vcverifier/src/test/java/testutils/TestUtils.kt (2)
  • readClasspathFile (8-9)
  • mockHttpResponse (13-17)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt (2)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt (1)
  • isValid (57-60)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)
  • isValidUri (80-91)
🪛 detekt (1.23.8)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt

[warning] 180-180: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt

[warning] 14-15: This empty block of code can be removed.

(detekt.empty-blocks.EmptyFunctionBlock)

🪛 Gitleaks (8.30.0)
vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithUnrevokedVC.json

[high] 114-114: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json

[high] 114-114: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 markdownlint-cli2 (0.18.1)
vc-verifier/kotlin/README.md

74-74: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


75-75: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


76-76: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


78-78: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


90-90: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


91-91: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


92-92: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


100-100: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


101-101: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


102-102: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


104-104: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


105-105: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


107-107: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


108-108: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


109-109: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


110-110: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


112-112: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


113-113: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


115-115: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


116-116: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


117-117: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


174-174: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


175-175: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


176-176: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


206-206: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


207-207: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


208-208: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


213-213: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


214-214: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


220-220: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


221-221: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


255-255: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


268-268: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


269-269: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


273-273: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


276-276: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


280-280: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


292-292: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


293-293: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


298-298: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


299-299: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


300-300: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


305-305: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


317-317: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


318-318: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


322-322: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


324-324: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


325-325: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


326-326: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


327-327: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


328-328: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


332-332: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


496-496: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


503-503: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


593-593: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


604-604: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


605-605: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


607-607: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


608-608: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


609-609: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


610-610: Unordered list indentation
Expected: 4; Actual: 8

(MD007, ul-indent)


611-611: Unordered list indentation
Expected: 6; Actual: 12

(MD007, ul-indent)


627-627: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


741-741: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


784-784: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


793-793: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


833-833: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

README.md

61-61: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

🔇 Additional comments (47)
vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt (1)

3-7: LGTM! Good practice to use explicit imports.

Replacing wildcard imports with explicit imports improves code clarity and makes dependencies more transparent.

vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/idaPublicKey.json (1)

4-5: No changes needed. The external URLs in the test fixture are properly handled by test mocks. The mockHttpResponse() function intercepts HTTP calls to these URLs and returns the fixture data locally, preventing any actual network requests or external dependencies. Using real MOSIP system URLs in fixture data (while mocking the network calls) is an appropriate testing pattern.

Likely an incorrect or invalid review comment.

vc-verifier/kotlin/vcverifier/publish-artifact.gradle (2)

99-99: LGTM!

Version bump to 1.7.0-SNAPSHOT is appropriate for the new feature additions in this PR.


113-113: LGTM!

Version bump to 1.7.0-SNAPSHOT is consistent with the aar publication and appropriate for the new features.

vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithUnrevokedVC.json (1)

114-114: Static analysis false positive - DID is not a secret.

The static analysis tool flagged this line as containing an API key, but this is a DID (Decentralized Identifier) following the did:key method specification. DIDs are public identifiers designed to be shared and are not secrets. This is a false positive.

vc-verifier/kotlin/vcverifier/src/test/resources/contexts/mock-identity-context.json (1)

1-103: LGTM!

Well-structured JSON-LD context for test resources. The multilingual field mappings and namespace declarations follow JSON-LD best practices and support the expanded test coverage for credential verification.

vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/mosipRevokedVC.json (1)

1-94: LGTM!

Well-formed test fixture for a revoked Verifiable Credential. The credentialStatus structure properly follows the Bitstring Status List specification and supports the new status-checking functionality introduced in this PR.

vc-verifier/kotlin/gradle/libs.versions.toml (1)

66-67: New dependencies support CWT verification.

The addition of jackson-dataformat-cbor and cose-java appropriately supports the new CWT (CBOR Web Token) verification functionality introduced in this PR.

README.md (2)

41-41: Well-documented new feature.

The addition of the "Status Check" feature description clearly communicates the new credential status verification capability.


46-51: Table accurately reflects signature support.

The updates to the VC formats table correctly document the addition of EcdsaSecp256k1Signature2019 support and clarify that SD-JWT formats use X.509 certificates rather than specific signature suites.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (2)

152-159: Hex conversion implementation is correct.

The hexToBytes function properly validates input (even length after removing whitespace) and correctly converts hex pairs to bytes.


161-175: CBOR numeric date validation is well-implemented.

The validateNumericDate function correctly enforces CBOR type requirements for numeric dates, providing clear error messages and proper null handling for optional claims.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/LdpVerifierTest.kt (2)

29-30: Good test isolation with HTTP mocking.

The addition of mockkObject(NetworkManagerClient) and loadMockPublicKeys() properly isolates tests from external network dependencies, ensuring deterministic and fast test execution.


98-104: Mock setup is well-organized.

The loadMockPublicKeys() helper cleanly organizes HTTP response mocking for multiple public key endpoints, improving test maintainability.

vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json (2)

112-114: Static analysis false positive - DID is not an API key.

The Gitleaks warning about a "Generic API Key" on line 114 is a false positive. The holder field contains a valid DID (did:key:...), which is the expected format for identifying the presentation holder.

The JWS signature at line 112 contains .hello. as a placeholder payload, which is appropriate for test fixtures where the actual signature content is mocked.


14-14: Remove PII from test fixtures.

The email address appears to be real or realistic personal data. Use clearly fake data (e.g., "test@example.com") to avoid GDPR/CCPA compliance risks.

Likely an incorrect or invalid review comment.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/VerifiableCredential.kt (1)

9-11: Good use of default implementation for backward compatibility.

Providing a default implementation that throws UnsupportedOperationException is appropriate for extending the interface without breaking existing implementations. Formats that don't support status checking will get a clear error message.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt (2)

173-183: New public API verifyAndGetCredentialStatus looks good.

The method provides a clean way to get combined VP verification and per-credential status results. The default empty list for statusPurposeList is a sensible default.


47-48: JSON parsing not wrapped in error handling.

JSONObject(presentation).getJSONArray(...) can throw JSONException if the verifiableCredential key is missing or malformed. If VP proof verification succeeds but the array is missing, an unhandled exception propagates.

Likely an incorrect or invalid review comment.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/exception/StatusCheckException.kt (1)

1-16: Well-structured exception with typed error codes.

The StatusCheckException with StatusCheckErrorCode enum provides clear categorization of status-check failures. Error codes cover the expected failure modes comprehensively.

Note: File is missing a trailing newline (minor style issue).

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifer.kt (4)

38-46: LGTM: COSE structure validation is thorough.

The validation correctly checks for the COSE Sign1 structure (4-element array with expected types: protected header, unprotected header, payload, signature as byte strings, and unprotected header as map).


103-116: LGTM: Signature verification properly wraps exceptions.

The verifySignature method correctly catches exceptions and returns false on failure, preventing exception propagation during verification.


15-15: Typo in class name: CwtVeriferCwtVerifier.

The class name is missing an 'i'.

Likely an incorrect or invalid review comment.


17-18: Remove unused cborMapper field.

The ObjectMapper with CBORFactory is initialized but never used in this class.

Likely an incorrect or invalid review comment.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt (1)

5-5: Typo: CwtVerifer should be CwtVerifier.

The imported class name is misspelled (missing 'i').

Likely an incorrect or invalid review comment.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/constants/StatusCheckerConstants.kt (1)

1-13: LGTM!

The constants are well-defined and align with the W3C StatusList2021 specification field names.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidator.kt (4)

24-59: LGTM!

The validate method follows a clear validation pipeline with appropriate error handling for both specific validation failures and unexpected exceptions.


62-109: LGTM!

The COSE_Sign1 structure validation correctly checks the RFC 8152 requirements: array with 4 elements where protected header and payload are byte strings, unprotected header is a map, and signature is a byte string.


112-136: LGTM!

Protected header validation correctly ensures ALG (COSE label 1) is present and numeric.


150-185: LGTM!

The numeric date validation correctly implements CWT temporal claim checks using the standard CBOR integer keys (4=exp, 5=nbf, 6=iat) with appropriate boundary conditions.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/data/Data.kt (2)

17-31: LGTM!

The new data classes PresentationResultWithCredentialStatus and VCResultWithCredentialStatus provide clean wrappers for combining verification status with credential status results.


57-65: LGTM!

CredentialStatusResult and CredentialVerificationSummary properly model the status check outcomes with nullable error for failure cases.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/validator/CwtValidatorTest.kt (2)

19-32: LGTM!

The createCoseHex helper is well-designed with sensible defaults, making it easy to test specific failure cases by overriding individual components.


116-151: LGTM!

The success path test thoroughly validates a complete valid COSE/CWT structure with proper temporal claims, confirming the validator returns empty error code and message on success.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/CredentialsVerifier.kt (3)

18-18: LGTM!

Using a shared credentialVerifierFactory instance is a good improvement over creating new instances inline.


41-74: LGTM!

The verify method correctly separates validation and signature verification with appropriate fallback error codes.


76-104: LGTM!

The status checking methods are well-designed:

  • getCredentialStatus gracefully handles unsupported formats by returning an empty map
  • verifyAndGetCredentialStatus correctly skips status checks for failed verifications, avoiding unnecessary work
vc-verifier/kotlin/README.md (1)

183-246: LGTM!

The credential status check documentation clearly explains the StatusList2021 flow, bit extraction logic, and result structure with helpful tables.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/LdpStatusChecker.kt (4)

62-124: LGTM!

The getStatuses method correctly handles both single and list forms of credentialStatus, with case-insensitive purpose filtering and per-entry error isolation.


226-283: LGTM!

The status computation correctly implements the StatusList2021 bit extraction: decoding the encoded list, computing bit positions based on index and status size, and interpreting 0 as valid.


362-388: LGTM!

The bit extraction correctly uses big-endian bit ordering where bit 0 is the MSB within each byte, matching the StatusList2021 specification.


169-201: Move validFrom and validUntil validation to read from the top-level VC, not credentialSubject.

Per the W3C StatusList2021 specification and the actual test data structure, validFrom and validUntil are properties of the status list VC itself, not the credential subject. The code currently reads these from credentialSubject (lines 169–170), which will fail to locate them and silently skip validation. Change to read from statusListVC.jsonObject instead.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/CredentialsVerifierTest.kt (2)

157-168: LGTM!

The test correctly verifies that when credential verification fails, the status list is empty. The assertions properly check both the verification failure and the empty status list.


202-228: LGTM!

The test correctly verifies that a revoked VC returns an invalid status result. The mocking setup and assertions are appropriate.

vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt (2)

27-79: LGTM!

The test setup, teardown, and helper methods are well-structured. The prepareVC and prepareVCFromRaw methods correctly return the MockWebServer instance to the caller, making it clear that the caller is responsible for shutting down the server.


81-452: Excellent test coverage!

The test suite comprehensively covers various edge cases and error scenarios for status list checking, including:

  • Valid and invalid status checks
  • Missing or malformed fields
  • Encoding/decoding errors
  • Purpose mismatches
  • Temporal validity checks
  • Status size and message validation

All tests (except the one flagged separately) properly manage MockWebServer lifecycle by shutting down servers after use.

vc-verifier/kotlin/vcverifier/src/test/resources/ldp_vc/public_key/didEcKey.json (1)

1-28: The nested @context in verificationMethod is an intentional test pattern.

This file follows a consistent structure used across multiple DID test resources (didEcKey.json, didEdPublicKey.json, and didMosipKey.json all contain nested @context in verificationMethod objects). While nested @context is non-standard per W3C DID Core spec (which places it only at root level), it appears to be deliberately used in these test cases to verify how the verifier handles security context information attached directly to verification methods. If the verifier correctly handles this pattern in tests, no changes are needed.

Comment on lines +23 to +24
jacksonAnnotations = "2.17.2"
jacksonModuleKotlin = "2.17.2"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Jackson 2.14.0 CVE vulnerabilities security issues

💡 Result:

Short answer: Jackson (jackson-databind) 2.14.0 mainly contains fixes for many prior "unsafe deserialization" CVEs, but the jackson-databind family has a long history of deserialization and resource‑exhaustion vulnerabilities. Distributors/security trackers mark several high‑severity deserialization CVEs as fixed by the 2.14.x fixes; additional denial‑of‑service / resource exhaustion issues have also been addressed in later 2.11–2.14 series releases. Upgrade to a patched release (or the latest 2.15+/maintenance release) and avoid enabling DefaultTyping / untrusted polymorphic deserialization. Sources: Snyk vulnerability list, Debian security tracker, CVE summary. [1][2][3]

References

  • Snyk jackson-databind vulnerability summary. [1]
  • Debian security tracker entries showing fixes in 2.14.0 packaging. [2]
  • CVE/CVEdetails summary for 2.14.x. [3]

If you want, I can run a live check of the very latest jackson-databind release and list specific CVE numbers and which are fixed in 2.14.0 vs later releases.


🌐 Web query:

Jackson breaking changes 2.14.0 to 2.17.2 upgrade guide

💡 Result:

Below is a concise upgrade checklist noting the important breaking/behavior changes and recommended actions when moving from Jackson 2.14.0 → 2.17.2.

High-impact changes to review and adapt for

  • Java / platform: Jackson 2.14 raised baseline to Java 8 for most components. Confirm your runtime/CI use Java 8+ (and Android SDK minimum changes noted). [1]
  • JsonNode API/behavior:
    • JsonNode.with(...) and withArray(...) treat arguments starting with "/" as JsonPointer expressions since 2.14; use withObjectProperty/withArrayProperty (added later) if you relied on literal names containing slashes. [1][3]
  • Annotation/visibility/ignore semantics:
    • Handling of conflicting @JsonIgnore vs @JsonProperty changed (2.14): @JsonIgnore now generally wins in ambiguous cases — audit any code relying on previous precedence. [1]
  • Stream / parsing constraints and defaults:
    • Starting in 2.15+ Jackson introduced StreamReadConstraints (limits on textual length, nesting, numeric sizes) and defaults that may cause deserialization failures for very large payloads; either raise/override constraints or explicitly configure JsonFactory/StreamReadConstraints if you process large inputs. [2][4]
  • Number parsing/formatting:
    • New faster float/double parsing/writing options (Schubfach) and changes to numeric handling (multi-release JAR optimizations) exist since 2.14–2.15; these are opt-in features but numeric behavior and rounding/parsing of corner cases (e.g., "3.") have been tightened/fixed across 2.15–2.17 — run numeric tests. [1][2][4]
  • Enums / mix-ins / naming:
    • 2.15–2.16 added better enum annotation support, new EnumNaming/EnumFeature options, and mix-in fixes for enums; if you used enum mix-ins or custom naming, re-test and consider the new annotation options. [3][2]
  • Polymorphic typing / type id handling:
    • 2.16 introduced per-type strict type-id options (OptBoolean in @JsonTypeInfo, JsonTypeInfo.Value) and new Id.SIMPLE_NAME — review polymorphic type handling and any custom type-id code. [5]
  • Kotlin/other language modules:
    • 2.15+ changed Kotlin support (no longer Kotlin 1.4 supported) — check module compatibility for kotlin/scala modules you use. [2]
  • Transitive dependency changes:
    • SnakeYAML bumped for YAML module, and other module dependency versions changed (check your BOM/custom dependency constraints). [2]
  • Bugfixes you may benefit from:
    • 2.17.x patch releases (2.17.2) contain many fixes for Reactor interaction, BigDecimal parsing edge-cases and other regressions — if you hit those issues upgrade to latest 2.17.x. [4]

Recommended upgrade steps

  1. Update BOM / dependencies to Jackson 2.17.2 (or latest 2.17.x) in your build (Maven/Gradle). [4]
  2. Run full test suite (unit + integration) — focus on:
    • JSON parsing of large strings, deep nesting and large numbers (StreamReadConstraints).
    • Enum serialization/deserialization, enum mix-ins, and any custom EnumNaming usage.
    • Polymorphic type handling and @JsonTypeInfo-annotated types.
    • Any code relying on JsonNode.with(...) semantics or on @JsonIgnore/@JsonProperty precedence.
  3. If you encounter "limit" errors (too long string, depth, numeric size), configure StreamReadConstraints or JsonFactory.overrideDefaultStreamReadConstraints(...) to the values your application needs. [2][4]
  4. If you use Kotlin/Scala modules, ensure module versions match supported language versions (2.15+ Kotlin change). [2]
  5. Check transitive deps (SnakeYAML, Guava baseline, Woodstox etc.) and adjust BOM pins or exclusions if your ecosystem requires older versions. [2]
  6. Smoke-test performance-sensitive code paths that parse/serialize floating point numbers if you opt-in to new fast parsers/writers. [1][2]
  7. Review changelogs of intermediate releases (2.15, 2.16, 2.17.2) for any additional fixes affecting your code and for patch-level bugfixes to apply. [2][3][4]

Primary sources / release notes (read before upgrading)

  • Jackson 2.14 release notes (behavior/API changes). [1]
  • Jackson 2.15 release notes (StreamReadConstraints, multi-release jar, module changes, enum features). [2]
  • Jackson 2.16 overview / 2.16.x notes (enum improvements, JsonNode additions, JsonTypeInfo per-type config). [3][5]
  • Jackson 2.17.2 release notes (patch fixes, Reactor/BigDecimal/edge-case fixes). [4]

If you want, I can:

  • produce a diff-style checklist for your codebase (search for usages of JsonNode.with, @JsonIgnore/@JsonProperty, @JsonTypeInfo, enum mix-ins), or
  • generate concrete JsonFactory/StreamReadConstraints sample code to override defaults. Which would you prefer?

References
[1] Jackson Release 2.14 — FasterXML (release notes).
[2] Jackson Release 2.15 — FasterXML (release notes).
[3] Jackson 2.16 overview (cowtowncoder blog / rc notes).
[4] Jackson Release 2.17.2 — FasterXML (release notes).
[5] Jackson 2.16.1 / 2.16.x summary (package/announcements).


Test Jackson upgrade to 2.17.2 for breaking changes before merging.

The upgrade spans multiple minor versions with several breaking changes requiring verification:

  • StreamReadConstraints (2.15+): May reject deserialization of large strings, deep nesting, or large numbers; verify your payload sizes don't exceed new defaults or configure StreamReadConstraints if needed.
  • JsonNode.with() (2.14+): Arguments starting with "/" are now treated as JsonPointer expressions; audit code relying on literal "/" in names.
  • @JsonIgnore/@JsonProperty (2.14+): Precedence rules changed; @JsonIgnore now generally wins in conflicts.
  • Enum handling (2.15+): New enum annotation support and naming options; re-test any enum serialization/deserialization.
  • Polymorphic types (2.16+): Per-type strict type-id options added; review @JsonTypeInfo-annotated types.
  • Kotlin module compatibility (2.15+): Module no longer supports Kotlin 1.4; confirm your Kotlin version matches.
  • Transitive dependencies: SnakeYAML, Guava, Woodstox versions changed; verify no conflicts in your dependency tree.

Additionally, 2.17.2 includes security patches and BigDecimal/Reactor fixes beyond what 2.14.0 had. Run full test suite, especially for JSON parsing of large/nested data, enum handling, and polymorphic deserialization.

🤖 Prompt for AI Agents
In @vc-verifier/kotlin/gradle/libs.versions.toml around lines 23-24, You
upgraded jacksonAnnotations and jacksonModuleKotlin to 2.17.2; before merging,
run the full test suite and explicitly verify breaking-change areas: confirm
StreamReadConstraints limits won't reject large strings/deep nesting or set
custom StreamReadConstraints in Jackson configuration; audit any uses of
JsonNode.with() for keys starting with "/" and update callers expecting literal
"/" behavior; re-test places using @JsonIgnore/@JsonProperty to ensure
precedence changes don't break mappings; exercise all enum
(serialize/deserialize) paths and @JsonTypeInfo polymorphic deserialization to
catch behavioral changes; verify Kotlin compatibility (module requires Kotlin
>=1.5), and check the dependency tree for transitive changes
(SnakeYAML/Guava/Woodstox) that could cause conflicts. Ensure CI includes JSON
parsing tests for large/nested payloads, enum cases, and polymorphic types
before approving the version bump of jacksonAnnotations and jacksonModuleKotlin.

|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `ldp_vc` | W3C Linked Data Proof Verifiable Credentials [(v2.0)](https://www.w3.org/TR/vc-data-model-2.0/) ([v1.1](https://www.w3.org/TR/vc-data-model-1.1/)) |
| `mso_mdoc` | ISO/IEC 18013-5 compliant mobile documents |
| `vc+sd-jwt`, `dc+sd-jwt` | [IETF SD-JWT based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/10/) |
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update SD-JWT VC specification reference to latest draft.

The README references draft-ietf-oauth-sd-jwt-vc/10, but the latest version is draft-ietf-oauth-sd-jwt-vc-13 (published November 2025).

🔎 Proposed fix
-| `vc+sd-jwt`, `dc+sd-jwt` | [IETF SD-JWT based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/10/)                                        |
+| `vc+sd-jwt`, `dc+sd-jwt` | [IETF SD-JWT based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/13/)                                        |
📝 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
| `vc+sd-jwt`, `dc+sd-jwt` | [IETF SD-JWT based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/10/) |
| `vc+sd-jwt`, `dc+sd-jwt` | [IETF SD-JWT based Verifiable Credentials](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/13/) |
🤖 Prompt for AI Agents
In @vc-verifier/kotlin/README.md around line 42, Update the SD-JWT VC spec link
and label in the README table entry for `vc+sd-jwt`, `dc+sd-jwt` to point to the
latest draft (change the URL from draft-ietf-oauth-sd-jwt-vc/10 to
draft-ietf-oauth-sd-jwt-vc-13) and, if present, update any displayed version
number text to "-13" or remove the version suffix so it reflects the current
draft; modify the table row containing the string `vc+sd-jwt`, `dc+sd-jwt` and
the linked URL to use the new draft URL.

Comment on lines +394 to +411
```json
{
"verificationResult": {
"verificationStatus": true,
"verificationMessage": "VC is expired",
"verificationErrorCode": ""
},
"credentialStatus": {
"revocation": {
"isValid": false,
"error": null
}
}
}

```

The VC is expired and revoked.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent example: expired VC shows verificationStatus: true.

The example text says "The VC is expired and revoked" but shows verificationStatus: true. An expired VC should have verificationStatus: false with an appropriate error code.

🔎 Proposed fix
 {
   "verificationResult": {
-    "verificationStatus": true,
+    "verificationStatus": false,
     "verificationMessage": "VC is expired",
-    "verificationErrorCode": ""
+    "verificationErrorCode": "ERR_VC_EXPIRED"
   },
🤖 Prompt for AI Agents
In @vc-verifier/kotlin/README.md around lines 394-411, The example JSON in
README uses verificationResult.verificationStatus: true while describing an
expired & revoked VC; update the example so
verificationResult.verificationStatus is false, set
verificationResult.verificationErrorCode to a suitable code (e.g., "EXPIRED")
and keep verificationResult.verificationMessage as "VC is expired", and ensure
credentialStatus.revocation.isValid remains false to reflect revocation.

Comment on lines +18 to +20
override fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
return emptyMap();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Returning empty map vs throwing UnsupportedOperationException.

The interface's default implementation throws UnsupportedOperationException, but this override returns an empty map. This creates ambiguity:

  • Empty map: "no status entries found" (successful check, nothing to report)
  • Exception: "format doesn't support status checking"

Consider either throwing the exception to be consistent with the interface contract, or documenting that an empty map means "not supported" for CWT format.

🔎 Suggested fix to align with interface semantics
 override fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
-    return emptyMap();
+    throw UnsupportedOperationException("Credential status checking not supported for CWT format")
 }
📝 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
override fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
return emptyMap();
}
override fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
throw UnsupportedOperationException("Credential status checking not supported for CWT format")
}
🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
around lines 18-20, The CwtVerifiableCredential.checkStatus override currently
returns an empty map which contradicts the interface's default behavior; change
the implementation in CwtVerifiableCredential.checkStatus to throw
UnsupportedOperationException (or, if you prefer the empty-map semantics, add
clear javadoc to the method stating that an empty map denotes "not supported"
for CWT), but prefer throwing UnsupportedOperationException to align with the
interface contract so callers receive a clear error when status checking isn't
supported by CWT.

Comment on lines +19 to 21
override fun checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> {
return LdpStatusChecker().getStatuses(credential, statusPurposes)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -iname "README*" -o -iname "CHANGELOG*" -o -iname "BREAKING*" | head -20

Repository: inji/vc-verifier

Length of output: 102


🏁 Script executed:

rg -i "breaking.*change|migration.*guide" --type md | head -30

Repository: inji/vc-verifier

Length of output: 341


🏁 Script executed:

rg -i "isRevoked|checkStatus" README.md CHANGELOG.md 2>/dev/null | head -20

Repository: inji/vc-verifier

Length of output: 216


🏁 Script executed:

cat README.md | grep -A 20 "## 🚨 Breaking Changes"

Repository: inji/vc-verifier

Length of output: 677


🏁 Script executed:

rg -A 10 -B 2 "isRevoked|checkStatus" README.md

Repository: inji/vc-verifier

Length of output: 927


Document the breaking API change from isRevoked to checkStatus.

The replacement of isRevoked(credential: String): Boolean with checkStatus(credential: String, statusPurposes: List<String>?): Map<String, CredentialStatusResult> is a breaking API change that is not currently documented. The README still references the old isRevoked(credential) method and does not list this signature change in the Breaking Changes section.

Update the Breaking Changes section in README.md to include this API change and provide migration guidance for users upgrading from versions that used isRevoked.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/LdpVerifiableCredential.kt
around lines 19-21, Add a Breaking Changes entry in README.md documenting that
the LdpVerifiableCredential API changed: the old isRevoked(credential: String):
Boolean method was removed and replaced by checkStatus(credential: String,
statusPurposes: List<String>?): Map<String, CredentialStatusResult>; explain how
callers should migrate by replacing boolean checks with calls to
LdpVerifiableCredential.checkStatus, passing any relevant statusPurposes (or
null) and inspecting the returned Map<String, CredentialStatusResult> for the
credential's status (e.g., map lookup for the expected purpose and interpreting
CredentialStatusResult fields), and include a short example snippet and notes
about nullability of statusPurposes and how multiple purposes are represented in
the map.


object Util {

val restTemplate = RestTemplate()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Configure RestTemplate with timeouts to prevent hanging.

The RestTemplate instance lacks timeout configuration. When making HTTP calls to external services (e.g., for key resolution or status checks), missing timeouts can cause indefinite hangs if remote services are unresponsive, impacting application reliability.

🔎 Proposed fix with connection and read timeouts
+import org.springframework.boot.web.client.RestTemplateBuilder
+import java.time.Duration
+
 object Util {
 
-    val restTemplate = RestTemplate()
+    val restTemplate = RestTemplateBuilder()
+        .setConnectTimeout(Duration.ofSeconds(10))
+        .setReadTimeout(Duration.ofSeconds(10))
+        .build()

Alternatively, if RestTemplateBuilder is not available:

+import org.springframework.http.client.SimpleClientHttpRequestFactory
+
 object Util {
 
-    val restTemplate = RestTemplate()
+    val restTemplate = RestTemplate().apply {
+        requestFactory = SimpleClientHttpRequestFactory().apply {
+            setConnectTimeout(10_000) // 10 seconds
+            setReadTimeout(10_000) // 10 seconds
+        }
+    }
📝 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
val restTemplate = RestTemplate()
import org.springframework.boot.web.client.RestTemplateBuilder
import java.time.Duration
object Util {
val restTemplate = RestTemplateBuilder()
.setConnectTimeout(Duration.ofSeconds(10))
.setReadTimeout(Duration.ofSeconds(10))
.build()
🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt
around line 36, The RestTemplate instance declared as val restTemplate =
RestTemplate() in Util.kt has no timeouts configured and can hang; replace it
with a RestTemplate configured with sensible connection and read/socket timeouts
(e.g., via RestTemplateBuilder or by creating an
HttpComponentsClientHttpRequestFactory/OkHttp3ClientHttpRequestFactory and
setting connect and read timeouts) and use that configured instance everywhere
the restTemplate variable is referenced; ensure the chosen timeout values are
reasonable for your environment and include them when constructing the
RestTemplate.

Comment on lines +177 to +183
fun httpGet(url: String): String? {
return try {
restTemplate.getForObject(url, String::class.java)
} catch (e: Exception) {
null
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add logging for HTTP failures to aid debugging.

The httpGet method silently swallows all exceptions and returns null, making it difficult to diagnose failures in production. Consider logging the exception at minimum, or returning a Result type that preserves error information.

🔎 Proposed fix with logging

Add logging import if not already present:

import org.slf4j.LoggerFactory

Then update the method:

+    private val logger = LoggerFactory.getLogger(Util::class.java)
+
     fun httpGet(url: String): String? {
         return try {
             restTemplate.getForObject(url, String::class.java)
         } catch (e: Exception) {
+            logger.warn("HTTP GET failed for URL: $url", e)
             null
         }
     }
🧰 Tools
🪛 detekt (1.23.8)

[warning] 180-180: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt
around lines 177-183, The httpGet function currently swallows all exceptions;
add logging so failures are visible: import org.slf4j.LoggerFactory, declare a
logger for Util (e.g., private val logger =
LoggerFactory.getLogger(Util::class.java) or similar), and inside the catch in
httpGet(url: String) log an error including the url and the exception (e.g.,
logger.error("HTTP GET failed for url: $url", e)) before returning null; keep
the method signature and restTemplate.getForObject usage unchanged.

Comment on lines +267 to +295
@Test
fun `should return error when statusSize is zero or negative`() {
val statusListJsonNegative = readFile("classpath:ldp_vc/status-list-vc.json")
.replace("\"encodedList\"", "\"statusSize\": -2, \"encodedList\"")
val statusListJsonZero = readFile("classpath:ldp_vc/status-list-vc.json")
.replace("\"encodedList\"", "\"statusSize\": 0, \"encodedList\"")
val (replacedVC, server) = prepareVC(statusListJson = statusListJsonNegative)
val (replacedVCZero, _) = prepareVC(
statusListJson = statusListJsonZero
)

val resultNeg = checker.getStatuses(replacedVC).entries.first()

assertFalse(resultNeg.value.isValid)
assertEquals(
StatusCheckErrorCode.STATUS_VERIFICATION_ERROR,
resultNeg.value.error?.errorCode
)

val resultZero = checker.getStatuses(replacedVCZero).entries.first()

assertFalse(resultZero.value.isValid)
assertEquals(
StatusCheckErrorCode.STATUS_VERIFICATION_ERROR,
resultZero.value.error?.errorCode
)

server.shutdown()
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Resource leak: second MockWebServer not shut down.

The test creates two mock web servers (lines 273 and 274-276) but only shuts down the first one at line 294. The server created for replacedVCZero is never shut down.

🔎 Proposed fix
     val (replacedVC, server) = prepareVC(statusListJson = statusListJsonNegative)
-    val (replacedVCZero, _) = prepareVC(
+    val (replacedVCZero, serverZero) = prepareVC(
         statusListJson = statusListJsonZero
     )

     val resultNeg = checker.getStatuses(replacedVC).entries.first()

     assertFalse(resultNeg.value.isValid)
     assertEquals(
         StatusCheckErrorCode.STATUS_VERIFICATION_ERROR,
         resultNeg.value.error?.errorCode
     )

     val resultZero = checker.getStatuses(replacedVCZero).entries.first()

     assertFalse(resultZero.value.isValid)
     assertEquals(
         StatusCheckErrorCode.STATUS_VERIFICATION_ERROR,
         resultZero.value.error?.errorCode
     )

     server.shutdown()
+    serverZero.shutdown()
 }
🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/statusChecker/StatusListRevocationCheckerTest.kt
around lines 267-295, Test leaks the second MockWebServer because prepareVC(...)
for the zero case discards the server; capture that server (e.g., val
(replacedVCZero, serverZero) = prepareVC(statusListJson = statusListJsonZero))
and call serverZero.shutdown() at the end (or shut both down in a
finally/tearDown block). Update the underscore in the second prepareVC call to a
named variable and ensure shutdown is invoked to close the resource.

Comment on lines +32 to +41
@Test
fun `should throw exception for mso_mdoc status check as its not supported`() {
val file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "sd-jwt_vc/sdJwt.txt")
val vc = String(Files.readAllBytes(file.toPath()))
val unsupportedStatusCheckException = assertThrows(UnsupportedOperationException::class.java) {
MsoMdocVerifiableCredential().checkStatus(vc, null)
}

assertEquals("Credential status checking not supported for this credential format",unsupportedStatusCheckException.message)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Test remains misplaced and loads irrelevant SD-JWT file.

This issue was previously flagged but not addressed. The test verifies MsoMdocVerifiableCredential behavior but is in SdJwtVerifierTest. Move it to a dedicated MsoMdocVerifiableCredentialTest file and remove the unnecessary SD-JWT file loading (lines 34-35), as the file content is irrelevant for testing unsupported status check behavior.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/SdJwtVerifierTest.kt
around lines 32-41, The test asserting UnsupportedOperationException for
MsoMdocVerifiableCredential.checkStatus is misplaced in SdJwtVerifierTest and
unnecessarily reads an SD-JWT file; move the entire test to a new test class
MsoMdocVerifiableCredentialTest (create file/class named
MsoMdocVerifiableCredentialTest) and remove the ResourceUtils file-loading lines
(the lines that set file and vc); call MsoMdocVerifiableCredential().checkStatus
with a simple placeholder (e.g., empty string) or null for the VC parameter and
keep the assertThrows and assertEquals checking the message unchanged.

}
],
"id": "did:jwk:eyJrdHkiOiJPS1AiLCJ1c2UiOiJzaWciLCJjcnYiOiJFZDI1NTE5IiwieCI6IlVFSWlCZXk3Y0xUakNxZVZpejZBWFFEV2lvR2pNNXo0M21qV3NCTjRwTTgifQ==",
"phone": "+919427357934",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove PII from test fixtures.

The phone number appears to be realistic personal data. Use obviously fake data (e.g., "+1-555-0100") to avoid compliance concerns.

🤖 Prompt for AI Agents
In @vc-verifier/kotlin/vcverifier/src/test/resources/vp/VPWithRevokedVC.json
around line 60, The test fixture contains real-looking PII in the "phone" JSON
field; replace the value in the VPWithRevokedVC fixture's "phone" key with an
obviously fake number (e.g., "+1-555-0100") to remove personal data, ensuring
any other test assertions still accept the updated fake value.

Signed-off-by: jaswanthkumarpolisetty <jaswanthkumar.p@thoughtworks.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)

61-69: Revocation is properly handled through the new credential status checking mechanism, but the REVOKED enum value should be removed.

Revocation is not lost—it's now handled via the credentialStatus map in CredentialVerificationSummary and VCResultWithCredentialStatus, populated by LdpStatusChecker.getStatuses(). Tests confirm this works correctly (e.g., revocation checks return CredentialStatusResult with isValid = false for revoked credentials).

However, the REVOKED enum value in VerificationStatus is now orphaned—never returned by getVerificationStatus(). Remove it to avoid confusion and maintain a single source of truth for revocation status through the credentialStatus map.

🤖 Fix all issues with AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt:
- Around line 72-98: The methods resolveIssuerMetadata and fetchPublicKey are
dead code and should be removed: delete the private functions
resolveIssuerMetadata(issuer: String): String? and fetchPublicKey(coseObj:
CBORObject, issuerMetadataJson: String): PublicKey? from CwtVerifier.kt and
remove any imports that become unused as a result (e.g., org.json.JSONObject,
JWKSet, RSAKey, ECKey, OctetKeyPair, CBORObject-related imports and any JSON/JWK
libraries only referenced by those methods) to keep the class tidy; leave
verify() and the existing PublicKeyResolverFactory().get(issuer) usage
unchanged.
- Around line 148-152: The call to PublicKeyResolverFactory().get(issuer) can
throw PublicKeyTypeNotSupportedException even though it is non-nullable; wrap
the resolver call in a try-catch that catches PublicKeyTypeNotSupportedException
(alongside any existing exception handling pattern used in this class), log or
handle the exception consistently, and return false on failure; specifically
modify the code around extractIssuerUri(claims) and the call to
PublicKeyResolverFactory().get(issuer) in CwtVerifier (referencing
extractIssuerUri, PublicKeyResolverFactory.get, and verifySignature) so
unsupported public key types do not propagate uncaught.
🧹 Nitpick comments (3)
vc-verifier/kotlin/vcverifier/build.gradle.kts (1)

11-13: Consolidate duplicate configurations.all blocks.

There are two separate configurations.all blocks in this file. Consider merging them for better maintainability.

🔎 Proposed consolidation
 configurations.all {
     resolutionStrategy.force( "com.fasterxml.jackson.core:jackson-core:2.14.0")
+    exclude(group = "org.bouncycastle", module = "bcprov-jdk15on")
+    exclude(group = "org.bouncycastle", module = "bcpkix-jdk15on")
+    exclude(group = "org.bouncycastle", module = "bcutil-jdk15on")
+    exclude(group = "org.bouncycastle", module = "bcprov-jdk15to18")
 }
 
-...
-
-configurations.all {
-    exclude(group = "org.bouncycastle", module = "bcprov-jdk15on")
-    exclude(group = "org.bouncycastle", module = "bcpkix-jdk15on")
-    exclude(group = "org.bouncycastle", module = "bcutil-jdk15on")
-    exclude(group = "org.bouncycastle", module = "bcprov-jdk15to18")
-}

Also applies to: 76-81

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt (1)

10-16: Consider reusing validator/verifier instances.

Creating new CwtValidator() and CwtVerifier() instances on each method call adds unnecessary object allocation. Consider using singleton instances or dependency injection if these classes are stateless.

🔎 Proposed fix
-class CwtVerifiableCredential: VerifiableCredential {
+class CwtVerifiableCredential: VerifiableCredential {
+    private val validator = CwtValidator()
+    private val verifier = CwtVerifier()
+
     override fun validate(credential: String): ValidationStatus {
-        return CwtValidator().validate(credential)
+        return validator.validate(credential)
     }

     override fun verify(credential: String): Boolean {
-        return CwtVerifier().verify(credential);
+        return verifier.verify(credential)
     }
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt (1)

3-3: Remove unused import.

android.net.Uri is imported but never used. The code uses java.net.URI instead.

🔎 Proposed fix
-import android.net.Uri
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fab654 and 812bf0d.

📒 Files selected for processing (7)
  • vc-verifier/kotlin/example/build.gradle.kts
  • vc-verifier/kotlin/gradle/libs.versions.toml
  • vc-verifier/kotlin/vcverifier/build.gradle.kts
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/types/CwtVerifiableCredential.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt
  • vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt
  • vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifierTest.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • vc-verifier/kotlin/gradle/libs.versions.toml
🧰 Additional context used
🧬 Code graph analysis (1)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt (1)
vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (1)
  • httpGet (177-183)
🔇 Additional comments (5)
vc-verifier/kotlin/example/build.gradle.kts (1)

49-51: LGTM!

The additional exclusion for the nested OSGI manifest path is appropriate since the wildcard META-INF/* only matches direct children. This prevents packaging conflicts from the new COSE library dependency.

vc-verifier/kotlin/vcverifier/build.gradle.kts (1)

68-68: Good choice using se.digg.cose:cose-lib.

This addresses the previous concern about using the unmaintained com.augustcellars.cose:cose-java. The se.digg.cose:cose-lib is an actively maintained alternative.

vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt (3)

5-6: LGTM! CBOR imports support CWT credential handling.

The addition of CBOR imports is appropriate for implementing CWT (CBOR Web Token) verification capabilities.


24-24: LGTM! RestTemplate import needed for HTTP utilities.

The RestTemplate import supports the new httpGet utility function for external HTTP calls.


152-159: LGTM! Hex to bytes conversion is correctly implemented.

The function properly validates input (even length requirement) and handles the conversion correctly. The use of require() for validation appropriately throws IllegalArgumentException on malformed input.

Comment on lines +72 to +98
private fun resolveIssuerMetadata(issuer: String): String? {
val metadataUrl = "$issuer/.well-known/openid-credential-issuer"
return httpGet(metadataUrl)
}

private fun fetchPublicKey(
coseObj: CBORObject,
issuerMetadataJson: String
): PublicKey? {

val metadata = org.json.JSONObject(issuerMetadataJson)
val jwksUri = metadata.optString("jwks_uri", null) ?: return null

val jwksJson = httpGet(jwksUri) ?: return null
val jwkSet = JWKSet.parse(jwksJson)

val kid = extractKid(coseObj) ?: return null

val jwk = jwkSet.keys.firstOrNull { it.keyID == kid } ?: return null

return when (jwk) {
is RSAKey -> jwk.toRSAPublicKey()
is ECKey -> jwk.toECPublicKey()
is OctetKeyPair -> jwk.toPublicKey()
else -> null
}
}
Copy link

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
# Verify if resolveIssuerMetadata or fetchPublicKey are used anywhere
echo "=== Searching for usages of resolveIssuerMetadata ==="
rg -n "resolveIssuerMetadata" --type=kotlin

echo ""
echo "=== Searching for usages of fetchPublicKey ==="
rg -n "fetchPublicKey" --type=kotlin

echo ""
echo "=== Searching for calls in verify() method ==="
rg -n "verify" vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt --type=kotlin -A 10 -B 2

Repository: inji/vc-verifier

Length of output: 1599


Remove unused methods: resolveIssuerMetadata and fetchPublicKey are dead code.

These methods are never called anywhere in the codebase. The verify() method obtains the public key directly via PublicKeyResolverFactory().get(issuer) (line 150), bypassing both methods entirely. Remove them to reduce code clutter.

🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt
around lines 72 - 98, The methods resolveIssuerMetadata and fetchPublicKey are
dead code and should be removed: delete the private functions
resolveIssuerMetadata(issuer: String): String? and fetchPublicKey(coseObj:
CBORObject, issuerMetadataJson: String): PublicKey? from CwtVerifier.kt and
remove any imports that become unused as a result (e.g., org.json.JSONObject,
JWKSet, RSAKey, ECKey, OctetKeyPair, CBORObject-related imports and any JSON/JWK
libraries only referenced by those methods) to keep the class tidy; leave
verify() and the existing PublicKeyResolverFactory().get(issuer) usage
unchanged.

Comment on lines +148 to +152
val issuer = extractIssuerUri(claims) ?: return false;

val publicKey = PublicKeyResolverFactory().get(issuer)

return verifySignature(coseBytes, publicKey)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== Finding PublicKeyResolverFactory implementation ==="
find . -type f -name "*.kt" | xargs grep -l "class PublicKeyResolverFactory"

echo ""
echo "=== Searching for PublicKeyResolverFactory in all Kotlin files ==="
fd --type f -e kt | xargs grep -l "PublicKeyResolverFactory" | head -10

Repository: inji/vc-verifier

Length of output: 969


🏁 Script executed:

#!/bin/bash
echo "=== Reading PublicKeyResolverFactory.kt ==="
cat -n "./vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/keyResolver/PublicKeyResolverFactory.kt"

echo ""
echo "=== Reading CwtVerifier.kt lines 140-160 ==="
sed -n '140,160p' "./vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt"

Repository: inji/vc-verifier

Length of output: 1793


🏁 Script executed:

#!/bin/bash
echo "=== Checking usage in LdpVerifier.kt ==="
grep -n -B2 -A2 "PublicKeyResolverFactory" "./vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/LdpVerifier.kt"

echo ""
echo "=== Checking usage in PresentationVerifier.kt ==="
grep -n -B2 -A2 "PublicKeyResolverFactory" "./vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/PresentationVerifier.kt"

echo ""
echo "=== Checking test file for expected behavior ==="
cat -n "./vc-verifier/kotlin/vcverifier/src/test/java/io/mosip/vercred/vcverifier/keyResolver/PublicKeyResolverFactoryTest.kt"

Repository: inji/vc-verifier

Length of output: 6190


Add exception handling for unsupported public key types.

PublicKeyResolverFactory().get(issuer) does not return null (return type is non-nullable PublicKey), but it throws PublicKeyTypeNotSupportedException when the issuer URI type is not supported. Add try-catch handling similar to other potential failure points in this method.

Proposed fix
        val issuer = extractIssuerUri(claims) ?: return false;

-        val publicKey = PublicKeyResolverFactory().get(issuer)
+        val publicKey = try {
+            PublicKeyResolverFactory().get(issuer)
+        } catch (e: PublicKeyTypeNotSupportedException) {
+            return false
+        }

        return verifySignature(coseBytes, publicKey)
🤖 Prompt for AI Agents
In
@vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/credentialverifier/verifier/CwtVerifier.kt
around lines 148 - 152, The call to PublicKeyResolverFactory().get(issuer) can
throw PublicKeyTypeNotSupportedException even though it is non-nullable; wrap
the resolver call in a try-catch that catches PublicKeyTypeNotSupportedException
(alongside any existing exception handling pattern used in this class), log or
handle the exception consistently, and return false on failure; specifically
modify the code around extractIssuerUri(claims) and the call to
PublicKeyResolverFactory().get(issuer) in CwtVerifier (referencing
extractIssuerUri, PublicKeyResolverFactory.get, and verifySignature) so
unsupported public key types do not propagate uncaught.

Comment on lines +161 to +175
fun validateNumericDate(
claims: CBORObject,
key: CBORObject,
name: String
): Long? {
if (!claims.ContainsKey(key)) return null

val value = claims[key]

require(value.type == CBORType.Integer) {
"$name must be a CBOR integer (NumericDate)"
}

return value.ToObject(Long::class.java)
}
Copy link

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

🌐 Web query:

RFC 8392 CWT NumericDate section 3.1 specification

💡 Result:

Section 3.1 (Terminology) of RFC 8392 defines NumericDate as:

  • It has the same meaning and processing rules as the JWT "NumericDate" from RFC 7519 Section 2.
  • In CWT it is represented as a CBOR numeric date (RFC 7049 §2.4.1) instead of a JSON number.
  • The CBOR encoding MUST omit the leading tag 1 (epoch-based date/time).
  • The registered claims exp, nbf, and iat use this NumericDate type. (rfc-editor.org)

Note: an erratum clarifies that RFC 8392 should require a finite CBOR numeric date (i.e., exclude IEEE infinities), aligning the intent with JSON's numeric limitations. (rfc-editor.org)

Citations:


🌐 Web query:

com.upokecenter.cbor library ContainsKey ToObject methods documentation

💡 Result:

ContainsKey (overloads) — determines whether a specified key exists in a CBOR map:

  • ContainsKey(CBORObject key): true if the CBOR key is present (null checks CBORObject.Null). [1]
  • ContainsKey(Object objKey): converts the object to a CBOR key and returns true if present. [1]
  • ContainsKey(String key): converts the string to a CBOR key (null → CBORObject.Null) and returns true if present. [1]

ToObject — converts a CBORObject to a value of a specified type:

  • Java signature example: T ToObject(Type t, CBORTypeMapper mapper> — converts this CBOR object to an instance of the given type; mapper controls POD deserialization and custom converters. Use the overloads that take CBORTypeMapper and PODOptions for more control. Note: reflection-based conversions may not be compatible with AOT/self-contained environments. [1][2]

References:
[1] com.upokecenter.cbor.CBORObject API (Java). [2] PeterO.Cbor.CBORObject documentation (.NET).


🏁 Script executed:

#!/bin/bash
# Search for imports and usage of com.upokecenter.cbor in the file
grep -n "import.*cbor\|import.*CBOR" vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt

# Look for other usages of validateNumericDate in the codebase
rg "validateNumericDate" -t kt -t java -A 3 -B 3

Repository: inji/vc-verifier

Length of output: 183


🌐 Web query:

RFC 7049 CBOR numeric types section 2.4 floating point double integer

💡 Result:

RFC 7049: CBOR supports IEEE 754 half-, single-, and double-precision floating-point encodings (major type 7, additional info 25, 26, 27) and treats different encodings of the same numeric value as equivalent. Floating-point formats and “no-content” simple values are specified in Section 2.3; optional tagging (Section 2.4) covers things like bignums, decimal fractions and bigfloats (tags 2–5). The specification explicitly says an encoder may choose the shortest exact floating-point form and that integer and floating representations of the same numeric value are equivalent (Section 3.6). (rfc-editor.org)

Citations:


🏁 Script executed:

#!/bin/bash
# Search for CBORType enum definition or usage
rg "CBORType\." --max-count 20 | head -40

# Search for validateNumericDate usage in tests or code
rg "validateNumericDate" --max-count 30

# Look for any floating point CBOR handling in the file
rg "Float|Double|Decimal" vc-verifier/kotlin/vcverifier/src/main/java/io/mosip/vercred/vcverifier/utils/Util.kt

Repository: inji/vc-verifier

Length of output: 3921


Accept all CBOR numeric types for NumericDate validation, not just integers.

RFC 7049 Section 3.6 specifies that integer and floating-point representations of the same numeric value are equivalent. The current check require(value.type == CBORType.Integer) rejects valid floating-point NumericDate values (e.g., 1609459200.0). Update the validation to accept CBORType.Integer, CBORType.Float, CBORType.Double, etc.

Additionally, RFC 8392 errata EID8617 requires that NumericDate values be finite; add a check to reject IEEE infinities and NaN after conversion to ensure full spec compliance.

Comment on lines +20 to +94
class CwtVerifierTest {

// @Test
// fun `should verify valid CWT`() {
//
// val kpg = KeyPairGenerator.getInstance("EC")
// kpg.initialize(256)
// val keyPair = kpg.generateKeyPair()
//
// val publicKey = keyPair.public as ECPublicKey
// val privateKey = keyPair.private as ECPrivateKey
//
// val kid = "test-key-1"
//
//
// val jwk = ECKey.Builder(Curve.P_256, publicKey)
// .privateKey(privateKey)
// .keyID(kid)
// .build()
//
// val jwksJson = JWKSet(jwk.toPublicJWK()).toJSONObject().toString()
//
// val issuer = "https://issuer.example.com"
//
// val issuerMetadataJson = """
// {
// "jwks_uri": "$issuer/jwks"
// }
// """.trimIndent()
//
//
// val claims = CBORObject.NewMap().apply {
// Add(1, issuer)
// Add(4, Date().time / 1000 + 600)
// }
//
//
// val sign1 = Sign1COSEObject()
//
// sign1.addAttribute(
// HeaderKeys.Algorithm,
// CBORObject.FromObject(-7), // ES256
// Attribute.PROTECTED
// )
//
// sign1.addAttribute(
// HeaderKeys.KID,
// CBORObject.FromObject(kid.toByteArray()),
// Attribute.PROTECTED
// )
//
// sign1.SetContent(claims.EncodeToBytes())
//
// val coseKey = COSEKey(publicKey, privateKey)
// sign1.sign(coseKey)
//
// val coseHex = sign1.EncodeToBytes().joinToString("") {
// "%02x".format(it)
// }
//
// mockkObject(Util)
//
// every { Util.httpGet(any()) } answers {
// when (firstArg<String>()) {
// "$issuer/.well-known/openid-credential-issuer" -> issuerMetadataJson
// "$issuer/jwks" -> jwksJson
// else -> null
// }
// }
//
//// val coseHex = "d83dd28443a10126a059015fa701782b6469643a7765623a706979757368373033342e6769746875622e696f3a4449443a7069797573682d6d6163041a6a4a2f79051a695ce179061a695ce1796d44617465204f662042697274686a32352d30352d313939306946756c6c204e616d65684a6f686e20446f656446616365a36b4461746120666f726d617465496d6167656f446174612073756220666f726d6174644a455047644461746178be646174613a696d6167652f706e673b6261736536342c6956424f5277304b47676f414141414e5355684555674141414277414141415143415941414141467a782f764141414151306c455156513479324e674741576a594c41445269435943574c382f2f382f48556c774a724969617371424c5077506c5752456b76795070704671636b7a30446c4957494a364652587757486a32306b4273466f3241514151445370535370396b6851704141414141424a52553545726b4a6767673d3d5840baafa376fee591618a03c10dc33b97e5d87053b52882640e3a317fbfa57b571c8c4c3d1bf2a67f68f7d62b4c547fc49a8a4aad89921de06bf85db518ada6b42f"
// assertTrue(CwtVerifier().verify(coseHex))
// }

}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Enable the commented test or remove dead code.

The entire test class is effectively empty with all test logic commented out. This provides no coverage for CwtVerifier. Either uncomment and fix the test so it runs, or remove the commented code to avoid confusion. Leaving large blocks of commented code is a maintenance burden.

If the test is not ready, consider tracking this with a TODO or creating an issue.

Do you want me to help complete this test or open an issue to track the work?

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.

4 participants