Skip to content

Fix/docker vulnurability#353

Open
DeepakNemad wants to merge 115 commits intomainfrom
fix/docker_vulnurability
Open

Fix/docker vulnurability#353
DeepakNemad wants to merge 115 commits intomainfrom
fix/docker_vulnurability

Conversation

@DeepakNemad
Copy link
Copy Markdown

@DeepakNemad DeepakNemad commented Mar 27, 2026

SUMMARY

Total HIGH/CRITICAL Vulnerabilities: 3
OS Vulnerabilities: 3 (HIGH: 2, CRITICAL: 1)
Application Vulnerabilities: 0

REMAINING VULNERABILITIES

Library CVE ID Severity Installed Version Fixed Version Description
libc-bin CVE-2026-0861 HIGH 2.36-9+deb12u13 - glibc: Integer overflow in memalign leads to heap corruption
libc6 CVE-2026-0861 HIGH 2.36-9+deb12u13 - glibc: Integer overflow in memalign leads to heap corruption
zlib1g CVE-2023-45853 CRITICAL 1:1.2.13.dfsg-1 - zlib: integer overflow and resultant heap-based buffer overflow

FIXED VULNERABILITIES

axios: Updated to 1.13.5 (CVE-2026-25639)
flatted: Updated to 3.4.0 (CVE-2026-32141)
undici: Updated to 6.24.0 (CVE-2026-1526, CVE-2026-1528, CVE-2026-2229)
All Node.js packages: 0 vulnerabilities detected

REMEDIATION STATUS

97% vulnerability reduction achieved
All application-level vulnerabilities fixed
Remaining vulnerabilities are OS-level only

SECURITY ENHANCEMENTS IMPLEMENTED

• Non-root user execution (appuser)
• System package updates
• CA certificates installed
• Temporary files cleaned
• Proper file permissions

Summary by CodeRabbit

  • New Features

    • OpenID4VC: holder, issuer, verifier flows plus issuance and verification session APIs
    • X.509 certificate creation, import, trust management and related tooling
    • Token-based trust-service auth and an org token endpoint
  • Dependency Updates

    • Upgraded Node.js runtime and key libraries; updated native storage/crypto dependency
  • Improvements

    • Streamlined env config with new auth/OIDC/app settings and body-size controls
    • Safer runtime: non-root container runtime, improved error guards and caching for tenant lookups

tipusinghaw and others added 30 commits September 12, 2025 10:58
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
…de credential payload

Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: RinkalBhojani <rinkal.bhojani@ayanworks.com>
Feat/support for x509 certs
Mdoc support
moved signer option to credential level
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
* updated creat x509 method and few types

Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>

* corrected mapper function for mdoc payload

Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>

---------

Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
fix: Added getTrustedCert function and refactored code
shitrerohit and others added 19 commits February 16, 2026 13:17
Signed-off-by: shitrerohit <rohit.shitre@ayanworks.com>
Signed-off-by: shitrerohit <rohit.shitre@ayanworks.com>
Signed-off-by: shitrerohit <rohit.shitre@ayanworks.com>
Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
…n sessions

Signed-off-by: Rinkal Bhojani <rinkal.bhojani@ayanworks.com>
…-response

feat:API for verify the authorization response
Signed-off-by: shitrerohit <rohit.shitre@ayanworks.com>
* fix: update credo version to 0.6.2

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: update credo version

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

---------

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
feat: added x509 certificates logic with auth
* fix: add polygon resolver and registrar

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: restore polygon module

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: linting

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: polygon controller

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: take polygon config from env for setupAgent

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: update rpc url

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: polygon signature issue and schema creation

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: polygon package update

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: remove unnecessary logs

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

---------

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>
* fix: did and schema controller

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: naming convention and remove comments

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: formatting

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: remove unused param

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: credential definition controller

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

* fix: error when cred-def failure

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>

---------

Signed-off-by: Krishna Waske <krishna.waske@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
Signed-off-by: Tipu_Singh <tipu.singh@ayanworks.com>
…ogic

refactor: update get x509 certs logic
• **Total HIGH/CRITICAL Vulnerabilities:** 3
• **OS Vulnerabilities:** 3 (HIGH: 2, CRITICAL: 1)
• **Application Vulnerabilities:** 0

### REMAINING VULNERABILITIES

| Library | CVE ID | Severity | Installed Version | Fixed Version | Description |
|---------|--------|----------|-------------------|---------------|-------------|
| libc-bin | CVE-2026-0861 | HIGH | 2.36-9+deb12u13 | - | glibc: Integer overflow in memalign leads to heap corruption |
| libc6 | CVE-2026-0861 | HIGH | 2.36-9+deb12u13 | - | glibc: Integer overflow in memalign leads to heap corruption |
| zlib1g | CVE-2023-45853 | CRITICAL | 1:1.2.13.dfsg-1 | - | zlib: integer overflow and resultant heap-based buffer overflow |

### FIXED VULNERABILITIES
• **axios:** Updated to 1.13.5 (CVE-2026-25639)
• **flatted:** Updated to 3.4.0 (CVE-2026-32141)
• **undici:** Updated to 6.24.0 (CVE-2026-1526, CVE-2026-1528, CVE-2026-2229)
• **All Node.js packages:** 0 vulnerabilities detected

### REMEDIATION STATUS
• **97% vulnerability reduction** achieved
• **All application-level vulnerabilities fixed**
• **Remaining vulnerabilities are OS-level only**

### SECURITY ENHANCEMENTS IMPLEMENTED
•  Non-root user execution (appuser)
•  System package updates
•  CA certificates installed
• Temporary files cleaned
•  Proper file permissions

Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6a619ff-c074-4e68-b84e-79803f68d01a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Consolidates DIDComm migration, adds OpenID4VC holder/issuer/verifier and session APIs, implements X.509 certificate creation/import/trust flows and token/trust-service helpers, updates environment variables and Docker base image, and upgrades multiple @credo-ts dependencies and related patches.

Changes

Cohort / File(s) Summary
Config & Build
\.env.sample, Dockerfile, tsoa.json, samples/cliConfig.json
Removed large inlined genesis blocks, added trust-service/OIDC/OpenID4VC/X.509 env vars and body-size limits; bumped Node base image to 22.x; added ca-certificates and non-root runtime; added tsoa tsconfig setting; updated Bcovrin genesis URL.
Dependencies & Patches
package.json, patches/@credo-ts*
Bumped multiple @credo-ts packages and related libs (didcomm, openid4vc added), switched askar package, added resolutions; applied patches adjusting types (Extensible→CredoExtensible), message-type removal, version string typing, and openid4vc export additions.
Agent / Transport / Modules
src/utils/agent.ts, src/cliAgent.ts, src/cli.ts, src/utils/oid4vc-agent.ts, src/utils/constant.ts
Migrated to @credo-ts/didcomm modules and DidComm transports, wired OpenID4VC/X.509 modules, changed wallet/askar store config (id/key), adjusted wallet config shape and allowInsecure flag, added mapping/helpers for OpenID4VC credential requests and trusted-cert retrieval.
Auth & Trust Utilities
src/controllers/auth/AuthController.ts, src/utils/auth.ts, src/utils/helpers.ts
Added AuthController to proxy trust-service token requests; introduced discriminated auth types, env validation, token caching, trust-service token fetch, and trust-check APIs; certificate validity computation helpers.
OpenID4VC — Holder / Issuer / Verifier / Sessions
src/controllers/openid4vc/..., src/controllers/openid4vc/types/*, src/controllers/openid4vc/examples/*
Added extensive OpenID4VC surface: issuer CRUD, issuance-sessions service/controllers, holder controller/service and binding resolver, verifier controllers/services and verification-sessions, and associated types/examples.
X.509 API & Utilities
src/controllers/x509/x509.Controller.ts, src/controllers/x509/x509.service.ts, src/controllers/x509/x509.types.ts, src/controllers/x509/crypto-util.ts
Implemented certificate creation/import, trust management, parsing/decoding, KMS import helpers, and DTOs for certificate options and extensions.
Controllers — DID / Agent / Anoncreds
src/controllers/did/DidController.ts, src/controllers/agent/AgentController.ts, src/controllers/anoncreds/*
Reworked DID handling to use KMS/JWK imports, revised agent info endpoint and disabled some agent endpoints; disabled endorser-transaction controller; added stronger return typing and dynamic error messaging in schema/cred-def controllers.
DIDComm Controllers (commented/disabled)
src/controllers/didcomm/basic-messages/*, src/controllers/didcomm/credentials/*, src/controllers/didcomm/proofs/*
Entire controller implementations commented out (disabled) in this diff — removes those REST endpoints in this iteration.
Events & WebSocket
src/events/*.ts, src/events/openId4Vc*, src/events/WebSocketEvents.ts, src/index.ts, src/server.ts
Migrated event subscriptions to DIDComm event types; added OpenID4VC issuance/verification event wiring; adjusted WebSocket server type; made Express body size configurable via env; added auth config validation call in server startup.
Types & Examples
src/controllers/types.ts, src/controllers/examples.ts, src/types/request.d.ts
Replaced many core protocol types with DIDComm equivalents, added X.509 and OpenID4VC type modules, simplified tenant config and request augmentation, updated examples.
Samples
samples/sample.ts, samples/sampleWithApp.ts
Changed sample agent init to use explicit id/key; minor greeting change in sampleWithApp.
Miscellaneous
src/authentication.ts, src/errorHandlingService.ts, src/utils/helpers.ts
Switched some imports to didcomm/other packages, used node:crypto.randomUUID, removed some logs, enhanced error handling (getFormatData guarded), and added token/cache helpers.

Sequence Diagram(s)

sequenceDiagram
    actor Holder
    participant Agent as Agent (Holder)
    participant Issuer as Issuer Server
    participant Auth as Authorization Server

    Holder->>Agent: Resolve Credential Offer URI
    Agent->>Issuer: Fetch Offer Details
    Issuer-->>Agent: Offer (credentials, grants)
    Agent-->>Holder: Present Offer

    alt Pre-Authorized Grant
        Holder->>Agent: Use Pre-Auth Code
        Agent->>Issuer: Token Request with pre-auth
        Issuer-->>Agent: Access Token
    else Authorization Code Flow
        Holder->>Auth: Authorize (user agent)
        Auth-->>Holder: Authorization Code
        Holder->>Agent: Provide Code + Verifier
        Agent->>Auth: Token Request (code, verifier)
        Auth-->>Agent: Access Token
    end

    Agent->>Issuer: Credential Request (binding proof: DID/x5c/JWK)
    Issuer-->>Agent: Signed Credential (SD-JWT / mDoc)
    Agent->>Holder: Store Credential
Loading
sequenceDiagram
    actor User
    participant VerifierAgent as Agent (Verifier)
    participant Verifier as Verifier Server
    participant Holder as Holder Agent

    User->>Verifier: Request Proof (create session)
    Verifier-->>User: Authorization Request URI

    User->>Holder: Resolve Proof Request
    Holder->>Verifier: Fetch Presentation Definition
    Verifier-->>Holder: Presentation Definition

    Holder->>Holder: Select Credentials & Build Presentation
    Holder->>Verifier: Submit Authorization Response + Presentation
    Verifier->>Verifier: Verify Presentation
    Verifier-->>Holder: Verification Result
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

bug

Suggested reviewers

  • RinkalBhojani
  • GHkrishna

Poem

🐰 Hop, hop—the agent’s new trails unwind,

Keys and certificates neatly aligned;
Issuers, holders, verifiers all in a row,
Trust services hum, and the credentials flow.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/docker_vulnurability

Copy link
Copy Markdown

@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: 3

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

Caution

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

⚠️ Outside diff range comments (2)
src/cli.ts (1)

176-194: ⚠️ Potential issue | 🔴 Critical

The database property should be storage to match @credo-ts/askar 0.6.2 configuration.

According to Credo documentation for @credo-ts/askar 0.6.2, wallet storage is configured via walletConfig.storage property, not database. The current code structure uses the incorrect property name. Change the property from database: to storage: at line 179 to align with the expected AskarModuleConfigStoreOptions interface.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli.ts` around lines 176 - 194, The walletConfig object is using the
wrong key name for Askar storage; rename the nested "database" property to
"storage" inside walletConfig so it matches the `@credo-ts/askar` 0.6.2
AskarModuleConfigStoreOptions shape (update the object currently constructed for
walletConfig in src/cli.ts: change the property named "database" to "storage"
while keeping its inner keys host/connectTimeout/maxConnections/idleTimeout and
credentials/account/password/adminAccount/adminPassword intact).
src/controllers/didcomm/outofband/OutOfBandController.ts (1)

177-195: ⚠️ Potential issue | 🟠 Major

Deserialize invitations by @type instead of forcing the OOB class.

The endpoint accepts both OOB and connection invitations per the documentation, but always constructs DidCommOutOfBandInvitation from the raw body. This will reject connection invitations and incompletely parse OOB payloads (only handshake_protocols is remapped). Use JsonTransformer.fromJSON() with type-based routing to properly deserialize both invitation formats, similar to the pattern already used elsewhere in this file for DidCommMessage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/didcomm/outofband/OutOfBandController.ts` around lines 177 -
195, The receiveInvitation handler currently always constructs a
DidCommOutOfBandInvitation from the raw body, which rejects connection
invitations and misses other OOB fields; instead, deserialize by `@type` using
JsonTransformer.fromJSON and route to the correct class (e.g.
DidCommOutOfBandInvitation vs the connection-invitation class used in this repo)
before calling request.agent.modules.didcomm.oob.receiveInvitation. Update the
logic in receiveInvitation (and use ReceiveInvitationProps as input) to inspect
invitation["@type"] (or use the same type-based routing pattern used for
DidCommMessage in this file), call JsonTransformer.fromJSON(invitation,
TargetClass) to produce the proper instance, then pass that instance to
didcomm.oob.receiveInvitation.
🟠 Major comments (23)
src/controllers/didcomm/credentials/CredentialController.ts-1-325 (1)

1-325: ⚠️ Potential issue | 🟠 Major

Avoid committing entirely commented-out code.

The entire CredentialController has been commented out, removing DIDComm credential exchange endpoints (/didcomm/credentials/*) from the application. This is confirmed alongside the same issue in ProofController.ts. No replacement handlers for these endpoints exist.

Choose one of:

  • Delete the file if credential exchange functionality is being removed
  • Keep it active if this is work in progress

Commented-out code should not be committed to the main branch.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/didcomm/credentials/CredentialController.ts` around lines 1 -
325, The CredentialController class (CredentialController) and its methods
(e.g., getAllCredentials, getW3cById, getCredentialById, proposeCredential,
acceptProposal, createOffer, createOfferOob, acceptOffer, acceptRequest,
acceptCredential, credentialFormData) and helper ensureLinkSecretExists are
entirely commented out; either remove the file or restore it — to restore,
uncomment the class and all methods, re-enable the imports at the top
(W3cCredentialService, createPeerDidDocumentFromServices, PeerDidNumAlgo,
Request/Req, tsoa decorators, injectables, SCOPES, ErrorHandlingService,
AgentType, examples, types, OutOfBandController), ensure dependency names match
(e.g., request.agent.modules.credentials,
request.agent.dependencyManager.resolve(W3cCredentialService)), and run
linter/tests to fix any missing types or imports; if functionality is
intentionally removed, delete the file instead to avoid committing commented-out
code.
src/controllers/didcomm/proofs/ProofController.ts-1-283 (1)

1-283: ⚠️ Potential issue | 🟠 Major

Do not commit entirely commented-out code.

The entire ProofController has been commented out rather than deleted or kept active. This creates inconsistencies:

  • The README documents "Endpoints to create connections, issue credentials, and request proofs," but proof endpoints are not accessible via the REST API
  • Proof protocols remain configured in the agent (DidCommProofV1Protocol, DidCommProofV2Protocol)
  • The controller is not registered in routes.ts, so commenting it out effectively disables the API endpoints
  • No documentation, TODO, or changelog entry explains why this was disabled

Either:

  • Delete the file if DIDComm proofs functionality is being removed
  • Keep it active and uncomment if still needed
  • Document the change clearly in CHANGELOG with explanation

Commented-out code creates maintenance confusion and makes the intended API capabilities unclear to users and developers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/didcomm/proofs/ProofController.ts` around lines 1 - 283, The
ProofController file is entirely commented out; either remove it or restore and
register its routes and docs. If keeping functionality: uncomment and re-enable
the ProofController class and its public methods (ProofController, getAllProofs,
getProofById, proposeProof, acceptProposal, requestProof, createRequest,
acceptRequest, acceptPresentation, proofFormData), ensure the controller is
registered in routes.ts, and verify protocol registrations
(DidCommProofV1Protocol/DidCommProofV2Protocol) and agent configuration remain
consistent; if removing functionality: delete this file and remove any proof
protocol registration (DidCommProofV1Protocol/DidCommProofV2Protocol) and
related modules, then add a CHANGELOG entry and update the README to reflect the
removal so docs, routes, and agent config stay aligned.
src/controllers/auth/AuthController.ts-36-42 (1)

36-42: ⚠️ Potential issue | 🟠 Major

Add error handling and timeout for external HTTP call.

The axios.post call lacks error handling — network failures, timeouts, or non-2xx responses will propagate as unhandled errors, resulting in generic 500 responses. External calls should also have timeouts to prevent hanging requests.

🔧 Proposed fix with error handling and timeout
+import { InternalServerError } from '../../errors'
+
     const response = await axios.post<OrgTokenResponse>(
       `${trustServiceTokenUrl}`,
       { clientId: body.clientId, clientSecret: body.clientSecret },
-      { headers: { 'Content-Type': 'application/json', accept: 'application/json' } },
+      { 
+        headers: { 'Content-Type': 'application/json', accept: 'application/json' },
+        timeout: 10000, // 10 second timeout
+      },
-    )
+    ).catch((error) => {
+      const message = error.response?.data?.message || error.message || 'Failed to obtain token'
+      throw new InternalServerError(`Trust service error: ${message}`)
+    })
 
     return response.data
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/auth/AuthController.ts` around lines 36 - 42, The axios.post
call in AuthController (the request to trustServiceTokenUrl that returns
OrgTokenResponse) needs a timeout and proper error handling: wrap the axios.post
in a try/catch inside the method in AuthController.ts (where response.data is
returned), add a timeout option (e.g., { timeout: 5000, headers: { ... } }) to
the axios call, check response.status to ensure a 2xx before returning
response.data, and in the catch block convert network/timeouts/non-2xx responses
into a clear, handled error (log context including body.clientId and the caught
error) or throw a controlled error type so the caller can return a meaningful
HTTP response instead of an unhandled 500.
src/controllers/didcomm/connections/ConnectionController.ts-132-139 (1)

132-139: ⚠️ Potential issue | 🟠 Major

This endpoint no longer matches its invitationId contract.

findByInvitationDid(invitationId) switches the lookup from the created invitation ID to the invitation DID, while the route and method name still advertise an invitation ID / URL lookup. Existing clients will start seeing 404s or a different payload shape here unless the endpoint is renamed and its contract is updated accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/didcomm/connections/ConnectionController.ts` around lines 132
- 139, The endpoint Get('/didcomm/url/:invitationId') and method getInvitation
incorrectly call
request.agent.modules.didcomm.connections.findByInvitationDid(invitationId)
which performs a DID lookup instead of an invitation ID/URL lookup; either
update the call to the correct lookup (e.g., use a findByInvitationId or
findByInvitationUrl method on request.agent.modules.didcomm.connections) or
rename the route/method to reflect that it expects an invitation DID (and update
request parameter name and docs), and ensure the NotFoundError message uses the
matching identifier; adjust any response shape if the alternate lookup returns a
different record type.
src/cliAgent.ts-203-205 (1)

203-205: ⚠️ Potential issue | 🟠 Major

Explicit false can never disable connection auto-accept.

autoAcceptConnections || true coerces a configured false back to true both before and inside getModules, so this setting is effectively impossible to turn off for either tenant or non-tenant agents.

💡 Proposed fix
       connections: {
-        autoAcceptConnections: autoAcceptConnections || true,
+        autoAcceptConnections,
       },
...
-      autoAcceptConnections || true,
+      autoAcceptConnections ?? true,
...
-      autoAcceptConnections || true,
+      autoAcceptConnections ?? true,

Also applies to: 441-467

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cliAgent.ts` around lines 203 - 205, The
connections.autoAcceptConnections is currently set with the expression
autoAcceptConnections || true which forces false to true; update the logic
wherever used (e.g., in the connections object at the construction site and
inside getModules) to explicitly check for undefined/null instead of using || so
a configured false is honored — for example, use a conditional like
(autoAcceptConnections === undefined ? true : autoAcceptConnections) or
Object.hasOwnProperty checks before defaulting; ensure the same change is
applied to the other occurrence(s) referenced (lines 441-467) so tenant and
non-tenant agents can disable auto-accept when set to false.
src/controllers/openid4vc/holder/credentialBindingResolver.ts-37-43 (1)

37-43: ⚠️ Potential issue | 🟠 Major

Clamp and validate numeric requestBatch.

The 10-item cap is only enforced when requestBatch === true. A numeric value like 50 will currently generate 50 keys, and 0 / negative / fractional values can fall through to an empty request or an invalid array length at Line 55.

💡 Proposed fix
+    if (typeof requestBatch === 'number' && (!Number.isInteger(requestBatch) || requestBatch < 1)) {
+      throw new Error('requestBatch must be a positive integer')
+    }
+
     const batchSize =
       requestBatch === true
         ? Math.min(issuerMaxBatchSize, 10)
         : typeof requestBatch === 'number'
-          ? Math.min(issuerMaxBatchSize, requestBatch)
+          ? Math.min(issuerMaxBatchSize, requestBatch, 10)
           : 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/holder/credentialBindingResolver.ts` around lines
37 - 43, The batch-size calculation allows numeric requestBatch values to bypass
the 10-cap and accept zero/negative/fractional inputs; update the logic that
computes batchSize (the variable) to first validate and normalize requestBatch:
if requestBatch === true keep Math.min(issuerMaxBatchSize, 10), if typeof
requestBatch === 'number' coerce to an integer via Math.floor, clamp it into the
valid range Math.max(1, Math.min(issuerMaxBatchSize, 10,
normalizedRequestBatch)), otherwise default to 1; ensure you reference
requestBatch, issuerMaxBatchSize and batchSize when making this change so
downstream code that generates keys uses a safe positive integer.
src/cliAgent.ts-278-290 (1)

278-290: ⚠️ Potential issue | 🟠 Major

Remove the certificate-verification debug logs.

This trust callback currently writes tenantId and auth mode to stdout on every X.509 verification. In a multi-tenant deployment that's sensitive operational metadata, and these console.log calls bypass the structured logger/redaction path.

💡 Proposed fix
         //TODO: We need to trust the certificate tenant wise, for that we need to fetch those details from platform
         const tenantId = agentContext.contextCorrelationId
-        console.log('[getTrustedCertificatesForVerification] tenantId from agentContext:', tenantId)

         const authType = getAuthType()
-          console.log('[getTrustedCertificatesForVerification] authType:', authType)

           if (authType === AuthTypes.ClientAuth) {
             return await getX509CertsByClientToken(tenantId, certificateChain)
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cliAgent.ts` around lines 278 - 290, Remove the two debug console.log
statements that leak tenantId and authType during X.509 verification: eliminate
the lines logging agentContext.contextCorrelationId and getAuthType() inside the
trust callback (the block that checks getAuthType() === AuthTypes.ClientAuth).
Instead, if structured auditing is required use the existing structured logger
with redaction elsewhere; keep the conditional flow that calls
getX509CertsByClientToken(tenantId, certificateChain) or getX509CertsByUrl()
unchanged (references: agentContext.contextCorrelationId, getAuthType(),
AuthTypes.ClientAuth, getX509CertsByClientToken, getX509CertsByUrl).
src/cliAgent.ts-248-267 (1)

248-267: ⚠️ Potential issue | 🟠 Major

NODE_ENV === 'PROD' will fail on standard production deployments.

Most Node.js deployments set NODE_ENV=production (lowercase), not PROD. When using the standard convention, these OID4VC base URLs fall back to AGENT_HTTP_URL, causing issuer/verifier metadata to advertise the wrong external address in production.

Proposed fix
-          process.env.NODE_ENV === 'PROD'
+          ['production', 'prod'].includes((process.env.NODE_ENV ?? '').toLowerCase())
             ? `https://${requireEnv('APP_URL')}/oid4vci`
             : `${requireEnv('AGENT_HTTP_URL')}/oid4vci`,
...
-          process.env.NODE_ENV === 'PROD'
+          ['production', 'prod'].includes((process.env.NODE_ENV ?? '').toLowerCase())
             ? `https://${requireEnv('APP_URL')}/oid4vp`
             : `${requireEnv('AGENT_HTTP_URL')}/oid4vp`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cliAgent.ts` around lines 248 - 267, The NODE_ENV check in the
OpenId4VcModule config (openid4vc -> issuer.baseUrl and verifier.baseUrl) uses
'PROD' which is non-standard; update the condition to detect production
correctly (e.g., compare to 'production' or perform a case-insensitive check) so
requireEnv('APP_URL') is used in real production deployments instead of falling
back to AGENT_HTTP_URL; modify the NODE_ENV checks around issuer and verifier
baseUrl to use the corrected comparison while keeping the existing ternary
structure and env helpers (requireEnv/AGENT_HTTP_URL) intact.
src/controllers/openid4vc/holder/holder.service.ts-120-123 (1)

120-123: ⚠️ Potential issue | 🟠 Major

Reuse the caller's selected credential configuration ids here.

The authorization step scopes the flow with credentialsToRequest, but this request asks for every credential_configuration_id in the offer. Multi-credential offers can therefore over-request or fail after a successful authorization step.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/holder/holder.service.ts` around lines 120 - 123,
The call to agentReq.agent.modules.openid4vc.holder.requestCredentials is
overriding the caller's requested credentials by always passing
resolvedCredentialOffer.credentialOfferPayload.credential_configuration_ids;
change this to prefer the caller's selected ids (e.g.,
options.credentialsToRequest or options.credentialConfigurationIds) and only
fall back to
resolvedCredentialOffer.credentialOfferPayload.credential_configuration_ids if
the caller did not provide them, so requestCredentials uses the same credentials
the authorization step scoped.
src/controllers/openid4vc/verifiers/verifier.Controller.ts-21-68 (1)

21-68: ⚠️ Potential issue | 🟠 Major

Wrap verifier-service failures with the shared error mapper.

These handlers return service promises directly instead of normalizing through ErrorHandlingService.handle. The new verifier endpoints will otherwise leak raw errors or generic 500s instead of the repo's existing HTTP responses.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/verifiers/verifier.Controller.ts` around lines 21 -
68, All controller methods (createVerifier, updateVerifierMetadata,
getVerifiersByQuery, getVerifier, deleteVerifier) currently return
verifierService promises directly and must be wrapped with the shared
ErrorHandlingService.handle to normalize errors; replace each direct call to
this.verifierService.* with a call to ErrorHandlingService.handle (or
this.errorHandlingService.handle if injected) passing a function that invokes
the service (e.g., () => this.verifierService.createVerifier(request, options))
and the request/context so that service failures are mapped into the repo's
standard HTTP responses.
src/utils/helpers.ts-160-166 (1)

160-166: ⚠️ Potential issue | 🟠 Major

Redact tokens and certificate chains from logs.

tokenResponse.data will typically contain the bearer token, and the later log dumps the full X.509 chain. That turns auth material and certificate subject data into log data.

Also applies to: 250-250

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/helpers.ts` around lines 160 - 166, The logs currently print
sensitive auth material (tokenResponse.data including access_token and X.509
chains); update the logging around tokenResponse (the console.log calls
referencing tokenResponse.status and tokenResponse.data, and the error log that
JSON.stringify tokenResponse.data) to avoid printing secrets: log only
non-sensitive metadata (e.g., tokenResponse.status and a masked summary) and
redact fields like access_token and any certificate chains (replace values with
"[REDACTED]" or omit them) before stringifying; apply the same redaction to the
other occurrence that logs tokenResponse.data (the later occurrence noted in the
review). Ensure the variable names to change are tokenResponse, token, and
label, and keep throwing the Error when token is missing.
src/controllers/openid4vc/holder/holder.Controller.ts-24-101 (1)

24-101: ⚠️ Potential issue | 🟠 Major

Normalize holder-service errors before returning.

Like the verifier controller, these endpoints skip ErrorHandlingService.handle, so bad offers/proof requests will return inconsistent errors compared with the rest of the API.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/holder/holder.Controller.ts` around lines 24 - 101,
The controller methods (e.g., getSdJwtCredentials, getMdocCredentials,
decodeMdocCredential, resolveCredOffer, requestAuthorizationForCredential,
requestCredential, resolveProofRequest, acceptProofRequest, decodeSdJwt, delete)
are directly returning holderService results and bypass
ErrorHandlingService.handle; update each method to catch thrown errors from
holderService calls and pass them to ErrorHandlingService.handle(request, error)
(matching the pattern used in the verifier controller) so responses are
normalized; ensure you import ErrorHandlingService if not already and apply the
try/catch→handle pattern to every method that calls holderService.
src/utils/helpers.ts-139-143 (1)

139-143: ⚠️ Potential issue | 🟠 Major

Set explicit timeouts on both trust-service calls.

Both axios.post calls use the default infinite timeout. A stuck token or match endpoint can hang the request path and exhaust connections under load.

Suggested fix
     tokenResponse = await axios.post<any>(
       tokenUrl,
       { clientId, clientSecret },
-      { headers: { 'Content-Type': 'application/json', accept: 'application/json' } },
+      {
+        timeout: 10000,
+        headers: { 'Content-Type': 'application/json', accept: 'application/json' },
+      },
     )
     const matchResponse = await axios.post<{ matched: boolean }>(
       matchUrl,
       { x509, ...(tenantId && { tenantId }) },
-      { headers: { 'Content-Type': 'application/json', accept: 'application/json', ...authHeaders } },
+      {
+        timeout: 10000,
+        headers: { 'Content-Type': 'application/json', accept: 'application/json', ...authHeaders },
+      },
     )

Also applies to: 189-193

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/helpers.ts` around lines 139 - 143, The two axios.post calls (the
one assigning tokenResponse and the other later for the match/verify request)
currently use the default infinite timeout; update both calls to include an
explicit timeout option (e.g., timeout: <ms>) in the axios config object so
requests cannot hang -- ideally use a shared constant or env var (e.g.,
TRUST_SERVICE_TIMEOUT) and merge it into the existing config that includes
headers (Content-Type/accept) so both the token request and the match request
use the same configurable timeout value.
src/controllers/agent/AgentController.ts-23-26 (1)

23-26: ⚠️ Potential issue | 🟠 Major

label now contains the correlation id, not the label.

contextCorrelationId is an internal correlation/tenant identifier. Returning it under the existing label field changes the /agent contract for clients that display or persist the human-readable agent label.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/agent/AgentController.ts` around lines 23 - 26, The response
is exposing the internal contextCorrelationId as the public "label" field;
change the mapping in AgentController so "label" returns the agent's
human-readable name (e.g., use request.agent.label) and do not return
request.agent.context.contextCorrelationId as the label; if request.agent.label
may be undefined, fall back to a non-sensitive field such as
request.agent.context.label or an empty string, and keep
request.agent.modules.didcomm.config.endpoints unchanged.
src/utils/helpers.ts-77-82 (1)

77-82: ⚠️ Potential issue | 🟠 Major

The validity window is anchored to today's day-of-month.

If this runs on March 27 with startFromCurrentMonth = false, a "3 year" cert becomes valid from January 27 and expires on January 27 three years later. That backdates the cert and shortens the effective validity by almost three months. Use the first day of the chosen month/year instead.

Suggested fix
-  const startDay = now.getUTCDate()
+  const startDay = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/helpers.ts` around lines 77 - 82, The code currently anchors the
validity window to today's day-of-month via startDay = now.getUTCDate(), which
backdates certificates; change startDay to 1 so the window begins on the first
day of the chosen month/year (keep startMonth logic: startFromCurrentMonth ?
now.getUTCMonth() : 0) and rebuild notBefore and notAfter using startYear,
startMonth, and startDay (first day of month) to ensure full expected validity.
src/utils/agent.ts-35-51 (1)

35-51: ⚠️ Potential issue | 🟠 Major

endpoints is accepted here but never stored on the agent.

After this change, downstream code reads request.agent.modules.didcomm.config.endpoints, but setupAgent no longer writes the incoming endpoints into any agent/module config. /agent and invitation creation can therefore return empty/undefined endpoints after initialization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/agent.ts` around lines 35 - 51, setupAgent currently accepts the
endpoints parameter but never writes it to the agent/module config, so
request.agent.modules.didcomm.config.endpoints ends up empty; update setupAgent
to persist the incoming endpoints (the endpoints array) into the agent
initialization config used by the DIDComm module (e.g., add endpoints to the
InitConfig or the specific didcomm module config created inside setupAgent) so
that request.agent.modules.didcomm.config.endpoints is populated after
initialization; ensure you reference the endpoints argument in setupAgent and
wire it into the InitConfig/didcomm config used by the agent.
src/utils/helpers.ts-100-114 (1)

100-114: ⚠️ Potential issue | 🟠 Major

Fail fast on unsupported curves.

Silently defaulting an unknown Curve | KeyAlgorithm to EC/P-256 can generate the wrong key metadata and produce invalid cert/JWK output. Throw here instead of coercing.

Suggested fix
   } else {
-    keyTypeInfo = {
-      kty: 'EC',
-      crv: 'P-256',
-    }
+    throw new Error(`Unsupported curve/key algorithm: ${String(key)}`)
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/helpers.ts` around lines 100 - 114, The current fallback silently
coerces unknown normalizedCurve to EC/P-256; instead detect unsupported curves
and throw a clear error. In the branch handling normalizedCurve/curveToKty (the
code that sets keyTypeInfo using kty/crv), replace the final else that assigns
{kty: 'EC', crv: 'P-256'} with a thrown Error that includes the received
normalizedCurve (and optionally original input) so callers fail fast when
curveToKty[normalizedCurve] is not 'OKP' or 'EC'. Keep the OKP and EC branches
as-is and ensure the thrown message references normalizedCurve and the function
name or context where keyTypeInfo is being set.
src/controllers/openid4vc/issuers/issuer.service.ts-29-40 (1)

29-40: ⚠️ Potential issue | 🟠 Major

Don't let a missing issuer module look like a successful call.

createIssuerAgent throws when openid4vc.issuer is absent, but these methods use optional chaining and can quietly return undefined/no-op instead. Keep the same explicit guard here so misconfiguration fails fast.

Also applies to: 44-45, 53-54

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/issuers/issuer.service.ts` around lines 29 - 40,
The getIssuersByQuery method (and the other methods using optional chaining)
currently uses optional chaining on agentReq.agent.modules.openid4vc.issuer
which can silently return undefined; change it to explicitly assert/throw if the
issuer module is missing (same pattern as createIssuerAgent) before calling
getIssuerByIssuerId or getAllIssuers so misconfiguration fails fast; update
getIssuersByQuery to fetch the issuer module into a local variable (e.g., const
issuer = agentReq.agent.modules.openid4vc.issuer) and throw a clear error if
!issuer, then call issuer.getIssuerByIssuerId(publicIssuerId) or
issuer.getAllIssuers(); apply the same explicit guard to the other methods in
this file that currently use optional chaining.
src/controllers/openid4vc/issuers/issuer.service.ts-47-50 (1)

47-50: ⚠️ Potential issue | 🟠 Major

Delete uses internal record id, inconsistent with other operations.

The deleteIssuer endpoint expects the internal record id (documented as "by record id" in line 83 of the controller), while getIssuer, updateIssuerMetadata, and other operations use the public publicIssuerId. Callers cannot consistently use the same identifier across operations. Either delete should accept publicIssuerId and resolve the internal id, or the controller contract should make the distinction explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/issuers/issuer.service.ts` around lines 47 - 50,
deleteIssuer currently deletes by internal record id while other methods use
publicIssuerId; change deleteIssuer (in issuer.service.ts) to accept a
publicIssuerId, query OpenId4VcIssuerRepository for the record (e.g., using a
method like findByPublicIssuerId or getByPublicIssuerId) to obtain the internal
id, handle a not-found case by throwing/returning an appropriate error, then
call deleteById with the resolved internal id; update the method signature and
any controller/docs so callers use publicIssuerId consistently (or alternatively
support both by detecting which form was passed and resolving accordingly).
src/controllers/x509/x509.service.ts-223-223 (1)

223-223: ⚠️ Potential issue | 🟠 Major

Security: Avoid logging seed/key material.

Logging the seed exposes sensitive cryptographic material that could be used to derive private keys. This is a security risk, especially in production environments.

🔒 Proposed fix to remove sensitive logging
-    agent.config.logger.debug(`createKey: got seed ${seed}`)
+    agent.config.logger.debug(`createKey: seed generated successfully`)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/x509/x509.service.ts` at line 223, The debug statement in
createKey logs the sensitive seed (agent.config.logger.debug(`createKey: got
seed ${seed}`)); remove or redact this logging so raw seed/key material is never
written to logs—either delete the logger.debug call or replace it with a
non-sensitive message (e.g., "createKey: seed received" without the value) and
ensure any references to 'seed' or derived key material are not interpolated
into logs.
src/utils/oid4vc-agent.ts-91-95 (1)

91-95: ⚠️ Potential issue | 🟠 Major

Replace the literal issuer placeholder before issuing SD-JWT-DC credentials.

issuer: 'ISSUER_HOST' will be emitted as-is unless another layer rewrites it. That produces credentials with an invalid iss value and breaks trust checks against your published issuer metadata.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/oid4vc-agent.ts` around lines 91 - 95, The issuer field currently
uses the literal placeholder 'ISSUER_HOST' in the issuer object (method: 'x5c',
x5c: ...), which must be replaced with the real issuer URL used for issuing
SD-JWT-DC credentials; change that property to read the actual issuer value from
configuration or the runtime OIDC/issuer metadata (e.g., an existing
issuerHost/oidcIssuer/config.issuer variable or process.env) and ensure it is a
fully-qualified HTTPS issuer string that matches your published issuer metadata.
src/utils/oid4vc-agent.ts-302-316 (1)

302-316: ⚠️ Potential issue | 🟠 Major

Harden the trust-list fetch path.

This external call has no timeout, and the response is only checked with Array.isArray before being cast to string[]. A stalled trust-list endpoint can hang request handling indefinitely, and non-string entries will slip through until certificate parsing fails later.

Suggested fix
-  const response = await fetch(trustListUrl)
+  const controller = new AbortController()
+  const timeout = setTimeout(() => controller.abort(), 10_000)
+  const response = await fetch(trustListUrl, { signal: controller.signal }).finally(() => clearTimeout(timeout))
@@
-  const data = await response.json()
+  const data: unknown = await response.json()
 
-  if (!Array.isArray(data) || data.length === 0) {
+  if (!Array.isArray(data) || data.length === 0 || !data.every((cert) => typeof cert === 'string')) {
     throw new Error('[getX509CertsByUrl] trust list is empty or invalid')
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/oid4vc-agent.ts` around lines 302 - 316, The trust-list fetch in
getX509CertsByUrl currently has no timeout and casts the parsed JSON to string[]
without validating entries; implement an AbortController with a configurable
timeout (use a local timeout constant) to abort the fetch to avoid hanging,
ensure you check response.ok as now, then parse JSON and validate that data is
an array and every element is a non-empty string (e.g., Array.isArray(data) &&
data.every(item => typeof item === 'string' && item.trim().length>0)), throw
descriptive errors if the fetch times out, the response is not ok, the JSON is
not an array, or contains non-string/empty entries, keep the
logger.info(`[getX509CertsByUrl] fetched certificates count: ${data.length}`)
after validation and return the validated string[].
src/utils/oid4vc-agent.ts-50-57 (1)

50-57: ⚠️ Potential issue | 🟠 Major

Use the configured DID key instead of always taking the first verification method.

If signerOptions.keyId points to a non-first key in the DID document, this mapper still emits didUrl = verificationMethod[0].id. The issued SD-JWT will then advertise the wrong issuer key and fail verification.

Suggested fix
-        // Set the first verificationMethod as backup, in case we won't find a match
-        if (didDocument.verificationMethod?.[0].id) {
-          issuerDidVerificationMethod = didDocument.verificationMethod?.[0].id
-        }
+        const verificationMethod = credential.signerOptions.keyId
+          ? didDocument.verificationMethod?.find((method) => method.id === credential.signerOptions.keyId)
+          : didDocument.verificationMethod?.[0]
+
+        issuerDidVerificationMethod = verificationMethod?.id
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/oid4vc-agent.ts` around lines 50 - 57, The code in the
SignerMethod.Did branch always picks verificationMethod[0].id which breaks cases
where credential.signerOptions.keyId points to a different key; update the logic
in the block that resolves the DID document (the code that calls
agentContext.dependencyManager.resolve(DidsApi) and didsApi.resolveDidDocument)
to search didDocument.verificationMethod for an entry whose id or fragment
matches credential.signerOptions.keyId and set issuerDidVerificationMethod to
that match, falling back to verificationMethod[0].id only if no matching keyId
is found; ensure you handle both full DID URL and fragment-only keyId formats
when comparing.
🟡 Minor comments (13)
src/controllers/anoncreds/endorser-transaction/EndorserTransactionController.ts-1-203 (1)

1-203: ⚠️ Potential issue | 🟡 Minor

Delete dead code instead of commenting it out.

The entire controller has been commented out rather than deleted. Evidence confirms this is unused code:

  • No test files reference EndorserTransactionController
  • No code imports or uses this controller
  • The /anoncreds/transactions endpoints are not documented in swagger.json (unlike other /anoncreds/ endpoints)
  • No TODO or explanation for the change

This creates maintenance burden with no benefit. Since these endpoints were never added to the public API spec, delete the entire EndorserTransactionController.ts file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/controllers/anoncreds/endorser-transaction/EndorserTransactionController.ts`
around lines 1 - 203, The file contains a fully commented-out
EndorserTransactionController (class EndorserTransactionController and its
methods endorserTransaction, didNymTransaction, writeSchemaAndCredDefOnLedger,
submitSchemaOnLedger, submitCredDefOnLedger) which is dead code; delete this
file entirely and remove any commented imports or unused symbols left in it, and
run a quick repo-wide search for EndorserTransactionController (and the endpoint
path '/anoncreds/transactions') to confirm there are no live references before
committing.
samples/sampleWithApp.ts-24-28 (1)

24-28: ⚠️ Potential issue | 🟡 Minor

Unused variable and malformed response string.

Two issues in this code segment:

  1. config (line 25) is now unused since the response no longer references config.label
  2. The response string has an errant comma: "Hello, agent initialized: , ${...}" — the : , sequence appears to be a copy-paste artifact
🔧 Suggested fix
   app.post('/greeting', jsonParser, (req, res) => {
-    const config = agent.dependencyManager.resolve(AgentConfig)
-
-    res.send(`Hello, agent initialized: , ${agent.isInitialized}!`)
+    res.send(`Hello, agent initialized: ${agent.isInitialized}!`)
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@samples/sampleWithApp.ts` around lines 24 - 28, The handler registered with
app.post('/greeting', jsonParser, ...) declares an unused local const config
from agent.dependencyManager.resolve(AgentConfig) and returns a malformed string
with an extra ",": remove the unused variable or actually use it (e.g., include
config.label) and fix the response template so it reads correctly (for example
"Hello, agent initialized: ${agent.isInitialized}" or "Hello, agent initialized:
${agent.isInitialized}, label: ${config.label}") while keeping app.post,
jsonParser, agent.dependencyManager.resolve(AgentConfig), config, and
agent.isInitialized referenced accurately.
Dockerfile-14-14 (1)

14-14: ⚠️ Potential issue | 🟡 Minor

Removing --frozen-lockfile may lead to inconsistent builds.

Without --frozen-lockfile, yarn install may update the lockfile if package.json and yarn.lock diverge, potentially causing non-reproducible builds in CI/CD pipelines.

🔧 Suggested fix
-RUN yarn install --network-timeout 600000
+RUN yarn install --frozen-lockfile --network-timeout 600000
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` at line 14, The Dockerfile's RUN invocation currently uses "yarn
install --network-timeout 600000" which allows yarn to modify yarn.lock and can
cause non-reproducible builds; restore the lockfile enforcement by using the
frozen-lockfile flag (e.g., run the existing RUN yarn install command with
--frozen-lockfile) so the build fails if package.json and yarn.lock diverge,
ensuring deterministic installs and CI consistency.
src/controllers/x509/crypto-util.ts-8-20 (1)

8-20: ⚠️ Potential issue | 🟡 Minor

Remove or export unused function pemToRawEcPrivateKey.

This function is defined but not exported, making it dead code. Either export it if it's intended for use, or remove it to avoid confusion.

Additionally, there are two issues:

  1. The function is marked async but contains no await statements.
  2. Line 17 uses a non-null assertion (!) on jwk.d without validation, unlike pemToRawEd25519PrivateKey which properly validates before using.
🛠️ If keeping the function, apply these fixes
-async function pemToRawEcPrivateKey(pem: string): Promise<string> {
+export function pemToRawEcPrivateKey(pem: string): string {
   const keyObj: KeyObject = createPrivateKey({
     key: pem,
     format: 'pem',
   })

-  // Extract raw private key (as Buffer)
-  const rawPrivateKey = keyObj.export({
+  const jwk = keyObj.export({
     format: 'jwk',
-  }).d!
+  })
+  if (!jwk.d) throw new Error('Not an EC private key')

-  return Buffer.from(rawPrivateKey, 'base64').toString('hex')
+  return Buffer.from(jwk.d, 'base64').toString('hex')
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/x509/crypto-util.ts` around lines 8 - 20, The function
pemToRawEcPrivateKey is unused and should be removed or exported; if you keep
it, remove the unnecessary async modifier, validate that keyObj.export({format:
'jwk'}).d exists (do not use the non-null assertion) and throw or return a clear
error like pemToRawEd25519PrivateKey does, and then export the function (add
export keyword) so it's reachable; locate and update the pemToRawEcPrivateKey
implementation and mirror the validation/error handling pattern used in
pemToRawEd25519PrivateKey.
src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts-115-118 (1)

115-118: ⚠️ Potential issue | 🟡 Minor

Fix formatting to comply with Prettier rules.

The error handling improvement is good, but the line formatting violates Prettier rules as flagged by ESLint.

🛠️ Proposed formatting fix
       if (registerCredentialDefinitionResult.credentialDefinitionState.state === CredentialEnum.Failed) {
-          const failureReason = registerCredentialDefinitionResult.credentialDefinitionState?.reason ?? 'Failed to register credential definition on ledger'
-          throw new InternalServerError(failureReason)
+        const failureReason =
+          registerCredentialDefinitionResult.credentialDefinitionState?.reason ??
+          'Failed to register credential definition on ledger'
+        throw new InternalServerError(failureReason)
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts` around
lines 115 - 118, The if-block in CredentialDefinitionController that checks
registerCredentialDefinitionResult.credentialDefinitionState.state ===
CredentialEnum.Failed needs to be reformatted to satisfy Prettier: break the
long conditional/assignment into properly indented lines, place the const
failureReason =
registerCredentialDefinitionResult.credentialDefinitionState?.reason ?? 'Failed
to register credential definition on ledger' on its own line, and put throw new
InternalServerError(failureReason) on the following line so the block follows
standard Prettier line length and indentation rules while keeping the same
variables and logic (registerCredentialDefinitionResult,
credentialDefinitionState, CredentialEnum.Failed, failureReason,
InternalServerError).
src/controllers/auth/AuthController.ts-26-43 (1)

26-43: ⚠️ Potential issue | 🟡 Minor

orgId path parameter is unused — either use it or remove it.

The orgId parameter is extracted from the URL path but never used in the request body or URL construction for the trust service call. This appears to be an oversight.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/auth/AuthController.ts` around lines 26 - 43, The getOrgToken
method currently accepts a Path parameter orgId that is never used; either
remove the orgId parameter from the method signature or include it in the trust
service request (e.g., add orgId to the request body or interpolate it into the
trustServiceTokenUrl) so the value is actually sent; update the signature
references to orgId and the OrgTokenRequest/OrgTokenResponse usage accordingly
(modify getOrgToken and any callers) to keep parameter and payload consistent.
src/controllers/openid4vc/issuers/issuer.Controller.ts-7-8 (1)

7-8: ⚠️ Potential issue | 🟡 Minor

The POST example shows the update payload.

createIssuer is annotated with OpenId4VcUpdateIssuerRecordOptionsExample, so the generated OpenAPI docs will advertise the wrong request body for this endpoint. Please switch this to a create-specific example.

Also applies to: 20-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/issuers/issuer.Controller.ts` around lines 7 - 8,
The POST handler createIssuer is annotated with the update-example constant
(OpenId4VcUpdateIssuerRecordOptionsExample), causing OpenAPI to show the wrong
request body; replace that import and its usage with the create-specific example
(e.g., OpenId4VcCreateIssuerRecordOptionsExample) and update the annotation on
the createIssuer method (and the other two occurrences around lines 20-22) so
the POST endpoint references the create example instead of the update example.
src/controllers/openid4vc/verifier-sessions/verification-sessions.Controller.ts-66-66 (1)

66-66: ⚠️ Potential issue | 🟡 Minor

Inconsistent route parameter syntax.

Lines 66 and 80 use /:verificationSessionId syntax, but TSOA typically uses {verificationSessionId} (as seen in issuance-sessions.Controller.ts at lines 40, 80, 96). This inconsistency could cause routing issues.

🐛 Proposed fix to use consistent TSOA syntax
-  `@Get`('/:verificationSessionId')
+  `@Get`('{verificationSessionId}')
   public async getVerificationSessionsById(
-  `@Get`('/response/:verificationSessionId')
+  `@Get`('/response/{verificationSessionId}')
   public async getVerifiedAuthorizationResponse(

Also applies to: 80-80

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/controllers/openid4vc/verifier-sessions/verification-sessions.Controller.ts`
at line 66, The route parameter syntax in verification-sessions.Controller.ts is
inconsistent with TSOA: replace the two occurrences of
`@Get`('/:verificationSessionId') with TSOA-style `@Get`('{verificationSessionId}')
to match issuance-sessions.Controller.ts; locate the decorators above the
methods handling verificationSessionId in the verification sessions controller
and update them so the route parameter braces use {verificationSessionId}
instead of /:verificationSessionId.
src/controllers/x509/x509.service.ts-24-24 (1)

24-24: ⚠️ Potential issue | 🟡 Minor

Class name should use PascalCase.

The class x509Service starts with lowercase, violating naming conventions. Static analysis also flags this at line 217. Rename to X509Service.

♻️ Proposed fix
-class x509Service {
+class X509Service {
-export const x509ServiceT = new x509Service()
+export const x509ServiceT = new X509Service()

Also applies to: 217-217

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/x509/x509.service.ts` at line 24, The class currently named
x509Service should be renamed to PascalCase X509Service; update the class
declaration from x509Service to X509Service and then update all references,
instantiations, type annotations, exports/imports, and any static member
accesses (search for x509Service and replace with X509Service) so consumers and
the default/named export match the new name and static analysis errors
disappear; ensure any export statement (e.g., export default or named export)
uses X509Service and run the tests/TS compile to catch remaining references.
src/controllers/x509/x509.service.ts-226-226 (1)

226-226: ⚠️ Potential issue | 🟡 Minor

Fix typo in error message.

"Unspported" should be "Unsupported".

📝 Proposed fix
-    if (!normalizedCurve) throw new Error('Unspported key type for method importKey')
+    if (!normalizedCurve) throw new Error('Unsupported key type for method importKey')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/x509/x509.service.ts` at line 226, In the importKey path
inside x509.service.ts (where normalizedCurve is checked), fix the typo in the
thrown Error message by changing "Unspported key type for method importKey" to
"Unsupported key type for method importKey" so the thrown Error from the
importKey method (reference: normalizedCurve, importKey) reads correctly.
src/controllers/openid4vc/issuance-sessions/issuance-sessions.service.ts-36-36 (1)

36-36: ⚠️ Potential issue | 🟡 Minor

Use strict equality operator.

Line 36 uses == (loose equality) instead of === (strict equality). This could lead to unexpected type coercion.

🐛 Proposed fix
-      if (cred.signerOptions.method == SignerMethod.Did && !cred.signerOptions.did) {
+      if (cred.signerOptions.method === SignerMethod.Did && !cred.signerOptions.did) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/issuance-sessions/issuance-sessions.service.ts` at
line 36, Replace loose equality with strict equality in the conditional that
checks the signer method: change the comparison of cred.signerOptions.method to
SignerMethod.Did from == to === so it uses strict equality; update the if
condition using the symbols cred.signerOptions.method and SignerMethod.Did
(inside the issuance sessions logic, e.g., IssuanceSessionsService) to prevent
type-coercion issues.
src/controllers/openid4vc/verifier-sessions/verification-sessions.service.ts-105-111 (1)

105-111: ⚠️ Potential issue | 🟡 Minor

Missing not-found error when session doesn't exist.

getVerificationSessionsById doesn't throw when the session is not found (unlike getVerifiedAuthorizationResponse at line 119-121 which does check). This could return undefined unexpectedly.

🛡️ Proposed fix to add not-found handling
   public async getVerificationSessionsById(agentReq: Req, verificationSessionId: string) {
     const verifier = agentReq.agent.modules.openid4vc.verifier
     if (!verifier) {
       throw new Error('OID4VC verifier module not initialized')
     }
-    return await verifier.getVerificationSessionById(verificationSessionId)
+    const session = await verifier.getVerificationSessionById(verificationSessionId)
+    if (!session) {
+      throw new Error(`Verification session with id ${verificationSessionId} not found`)
+    }
+    return session
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/verifier-sessions/verification-sessions.service.ts`
around lines 105 - 111, getVerificationSessionsById currently returns whatever
verifier.getVerificationSessionById yields and can return undefined; update it
to check the returned value and throw a not-found error when missing (mirror the
behavior in getVerifiedAuthorizationResponse). After calling
verifier.getVerificationSessionById(verificationSessionId) in
getVerificationSessionsById, if the result is falsy, throw a descriptive Error
like "Verification session not found" so callers don't receive undefined;
reference the verifier module and the getVerificationSessionById call to locate
where to add this check.
src/controllers/openid4vc/issuance-sessions/issuance-sessions.service.ts-78-84 (1)

78-84: ⚠️ Potential issue | 🟡 Minor

Missing not-found error handling.

getIssuanceSessionsById doesn't validate if the session exists before returning. This could return undefined to the caller unexpectedly.

🛡️ Proposed fix to add not-found handling
   public async getIssuanceSessionsById(agentReq: Req, sessionId: string) {
     const issuer = agentReq.agent.modules.openid4vc.issuer
     if (!issuer) {
       throw new Error('OID4VC issuer module not initialized')
     }
-    return issuer.getIssuanceSessionById(sessionId)
+    const session = await issuer.getIssuanceSessionById(sessionId)
+    if (!session) {
+      throw new NotFoundError(`Issuance session with id ${sessionId} not found`)
+    }
+    return session
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/issuance-sessions/issuance-sessions.service.ts`
around lines 78 - 84, The getIssuanceSessionsById function currently returns
whatever issuer.getIssuanceSessionById(sessionId) yields, which may be
undefined; update getIssuanceSessionsById to call
issuer.getIssuanceSessionById(sessionId), check the result, and if it's falsy
throw a clear not-found error (e.g., throw new Error('Issuance session not
found')) instead of returning undefined; keep the existing issuer module
initialization check using agentReq.agent.modules.openid4vc.issuer and reference
the symbols getIssuanceSessionsById and issuer.getIssuanceSessionById when
making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 726a93e9-5f60-4079-9eb8-c40ae6fdc9c2

📥 Commits

Reviewing files that changed from the base of the PR and between 104f72a and 9c0955c.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (73)
  • .env.demo
  • .env.sample
  • Dockerfile
  • package.json
  • patches/@credo-ts+anoncreds+0.5.3+001+fix: Extensible model confict in Anoncreds and Did.patch
  • patches/@credo-ts+core+0.5.15+001+message-type-for-messages.patch
  • patches/@credo-ts+core+0.5.15+003+added-prettyVc-in-JsonCredential-interface.patch
  • patches/@credo-ts+core+0.5.15+004+commenting validationPresentation to avoid abandoned issue.patch
  • patches/@credo-ts+core+0.5.15+005+credential-get-format-data.patch
  • patches/@credo-ts+core+0.6.0+001+fix: change version string type.patch
  • patches/@credo-ts+openid4vc+0.6.2.patch
  • patches/@credo-ts+tenants+0.5.3+001+cache-tenant-record-patch.patch
  • samples/cliConfig.json
  • samples/sample.ts
  • samples/sampleWithApp.ts
  • src/authentication.ts
  • src/cli.ts
  • src/cliAgent.ts
  • src/controllers/agent/AgentController.ts
  • src/controllers/anoncreds/cred-def/CredentialDefinitionController.ts
  • src/controllers/anoncreds/endorser-transaction/EndorserTransactionController.ts
  • src/controllers/anoncreds/schema/SchemaController.ts
  • src/controllers/auth/AuthController.ts
  • src/controllers/did/DidController.ts
  • src/controllers/didcomm/basic-messages/BasicMessageController.ts
  • src/controllers/didcomm/connections/ConnectionController.ts
  • src/controllers/didcomm/credentials/CredentialController.ts
  • src/controllers/didcomm/outofband/OutOfBandController.ts
  • src/controllers/didcomm/proofs/ProofController.ts
  • src/controllers/didcomm/question-answer/QuestionAnswerController.ts
  • src/controllers/examples.ts
  • src/controllers/openid4vc/examples/issuer.examples.ts
  • src/controllers/openid4vc/holder/credentialBindingResolver.ts
  • src/controllers/openid4vc/holder/holder.Controller.ts
  • src/controllers/openid4vc/holder/holder.service.ts
  • src/controllers/openid4vc/issuance-sessions/issuance-sessions.Controller.ts
  • src/controllers/openid4vc/issuance-sessions/issuance-sessions.service.ts
  • src/controllers/openid4vc/issuers/issuer.Controller.ts
  • src/controllers/openid4vc/issuers/issuer.service.ts
  • src/controllers/openid4vc/types/holder.types.ts
  • src/controllers/openid4vc/types/issuer.types.ts
  • src/controllers/openid4vc/types/verifier.types.ts
  • src/controllers/openid4vc/verifier-sessions/verification-sessions.Controller.ts
  • src/controllers/openid4vc/verifier-sessions/verification-sessions.service.ts
  • src/controllers/openid4vc/verifiers/verifier.Controller.ts
  • src/controllers/openid4vc/verifiers/verifier.service.ts
  • src/controllers/polygon/PolygonController.ts
  • src/controllers/types.ts
  • src/controllers/x509/crypto-util.ts
  • src/controllers/x509/x509.Controller.ts
  • src/controllers/x509/x509.service.ts
  • src/controllers/x509/x509.types.ts
  • src/enums/enum.ts
  • src/errorHandlingService.ts
  • src/events/BasicMessageEvents.ts
  • src/events/ConnectionEvents.ts
  • src/events/CredentialEvents.ts
  • src/events/ProofEvents.ts
  • src/events/ReuseConnectionEvents.ts
  • src/events/WebSocketEvents.ts
  • src/events/openId4VcIssuanceSessionEvents.ts
  • src/events/openId4VcVerificationSessionEvents.ts
  • src/index.ts
  • src/routes/routes.ts
  • src/routes/swagger.json
  • src/server.ts
  • src/types/request.d.ts
  • src/utils/agent.ts
  • src/utils/auth.ts
  • src/utils/constant.ts
  • src/utils/helpers.ts
  • src/utils/oid4vc-agent.ts
  • tsoa.json
💤 Files with no reviewable changes (6)
  • patches/@credo-ts+core+0.5.15+005+credential-get-format-data.patch
  • patches/@credo-ts+tenants+0.5.3+001+cache-tenant-record-patch.patch
  • patches/@credo-ts+core+0.5.15+003+added-prettyVc-in-JsonCredential-interface.patch
  • patches/@credo-ts+core+0.5.15+001+message-type-for-messages.patch
  • patches/@credo-ts+core+0.5.15+004+commenting validationPresentation to avoid abandoned issue.patch
  • patches/@credo-ts+anoncreds+0.5.3+001+fix: Extensible model confict in Anoncreds and Did.patch

Comment on lines +77 to +80
if (parsedCertificate) {
parsedCertificate.publicJwk.keyId = requestSigner.keyId
}
options.requestSigner.x5c = [parsedCertificate]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: parsedCertificate accessed outside X.509 branch causes runtime error for DID signers.

parsedCertificate is only defined inside the else branch (X.509 mode), but lines 77-80 execute unconditionally. When method === 'did', parsedCertificate is undefined, causing parsedCertificate.publicJwk to throw a TypeError.

🐛 Proposed fix to scope X.509-specific logic correctly
     } else {
       requestSigner = dto.requestSigner as OpenId4VcIssuerX5cOptions

       parsedCertificate = X509Service.parseCertificate(agentReq.agent.context, {
         encodedCertificate: requestSigner.x5c[0],
       })
       requestSigner.issuer = parsedCertificate.sanUriNames[0]
       requestSigner.clientIdPrefix = dto.requestSigner.clientIdPrefix ?? ClientIdPrefix.X509Hash
+      parsedCertificate.publicJwk.keyId = requestSigner.keyId
+      requestSigner.x5c = [parsedCertificate]
     }
     const options: any = {
       requestSigner,
       verifierId: dto.verifierId,
     }

     if (dto.responseMode === ResponseModeEnum.DC_API || dto.responseMode === ResponseModeEnum.DC_API_JWT) {
       options.expectedOrigins = dto.expectedOrigins
     }

     if (dto.responseMode) options.responseMode = dto.responseMode
     if (dto.presentationExchange) {
       // options.presentationExchange = dto.presentationExchange
       throw new Error('Presentation Exchange is not supported for now')
     }
-    if (parsedCertificate) {
-      parsedCertificate.publicJwk.keyId = requestSigner.keyId
-    }
-    options.requestSigner.x5c = [parsedCertificate]
     options.dcql = dto.dcql
     // }
     return (await verifier.createAuthorizationRequest(options)) as any
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/controllers/openid4vc/verifier-sessions/verification-sessions.service.ts`
around lines 77 - 80, The code accesses parsedCertificate and sets
options.requestSigner.x5c unconditionally which fails for DID signers; restrict
the X.509-specific logic by only touching parsedCertificate.publicJwk and
options.requestSigner.x5c when parsedCertificate is defined (i.e., inside the
X.509 branch or guarded by if (parsedCertificate) ), or alternatively check
method === 'x509' before assigning; update the block that sets
requestSigner.keyId and options.requestSigner.x5c so it only runs when
parsedCertificate is present to avoid TypeError for DID signers.

Comment on lines +1 to 5
import { Server } from 'ws'

export const sendWebSocketEvent = async (server: WebSocket.Server, data: unknown) => {
export const sendWebSocketEvent = async (server: Server, data: unknown) => {
server.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if WebSocket is imported elsewhere or if there's a global polyfill
# Expected: No other imports that would provide WebSocket globally

# Search for WebSocket imports in the codebase
rg -n "import.*WebSocket" --type=ts

# Check if there's a global declaration for WebSocket
rg -n "declare.*WebSocket" --type=ts

Repository: credebl/agent-controller

Length of output: 861


🏁 Script executed:

cat -n src/events/WebSocketEvents.ts

Repository: credebl/agent-controller

Length of output: 423


🏁 Script executed:

# Check the ws library exports and how it's used in the codebase
rg -A 3 "from 'ws'" src/ --type=ts | head -30

Repository: credebl/agent-controller

Length of output: 653


🌐 Web query:

ws npm library WebSocket export OPEN constant

💡 Result:

The 'ws' npm library (Node.js WebSocket implementation) defines WebSocket ready state constants including OPEN in its WebSocket class. These are set as static properties on the WebSocket constructor using Object.defineProperty. Key details: - Ready states array: ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'] (indices 0,1,2,3) - WebSocket.OPEN = 1 (readyStates.indexOf('OPEN')) - Defined in lib/websocket.js - lib/constants.js exists (503B) but primarily exports other constants (e.g., BINARY_TYPES); ready states use the local array. - Usage example: if (client.readyState === WebSocket.OPEN) { client.send(data); } - Official docs confirm: OPEN (1) - The connection is open and ready to communicate. No direct named export of a top-level 'OPEN' constant from the main module; access via imported WebSocket.OPEN after 'import WebSocket from "ws"' or '{ WebSocket } from "ws"'.

Citations:


Missing WebSocket import causes runtime error.

Line 5 references WebSocket.OPEN without importing WebSocket. This will fail at runtime with a ReferenceError in all Node.js environments.

🐛 Proposed fix
-import { Server } from 'ws'
+import WebSocket, { Server } from 'ws'
 
 export const sendWebSocketEvent = async (server: Server, data: unknown) => {
   server.clients.forEach((client) => {
     if (client.readyState === WebSocket.OPEN) {
📝 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
import { Server } from 'ws'
export const sendWebSocketEvent = async (server: WebSocket.Server, data: unknown) => {
export const sendWebSocketEvent = async (server: Server, data: unknown) => {
server.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
import WebSocket, { Server } from 'ws'
export const sendWebSocketEvent = async (server: Server, data: unknown) => {
server.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
🧰 Tools
🪛 ESLint

[error] 1-1: All imports in the declaration are only used as types. Use import type.

(@typescript-eslint/consistent-type-imports)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/events/WebSocketEvents.ts` around lines 1 - 5, The function
sendWebSocketEvent references WebSocket.OPEN but WebSocket is not imported,
causing a runtime ReferenceError; fix it by adding the WebSocket symbol from the
'ws' package to the top import (e.g., include WebSocket alongside Server in the
import statement) so the check client.readyState === WebSocket.OPEN resolves
correctly.

Comment on lines +149 to +163
httpInbound.app.get(
'/invitation',
async (req: { query: { d_m: any; c_i: any }; url: string }, res: { send: (arg0: any) => void }) => {
if (typeof req.query.d_m === 'string') {
const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url.replace('d_m=', 'c_i='))
res.send(invitation.toJSON())
}
if (typeof req.query.c_i === 'string') {
const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url)
res.send(invitation.toJSON())
} else {
const { outOfBandInvitation } = await agent.modules.didcomm.oob.createInvitation()

res.send(outOfBandInvitation.toUrl({ domain: endpoints + '/invitation' }))
}
})
res.send(outOfBandInvitation.toUrl({ domain: endpoints + '/invitation' }))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix the /invitation handler's control flow and URL construction.

For ?d_m=..., Line 154 sends a response and then falls into the later else, which sends a second response because the next branch isn't else if. Also, endpoints + '/invitation' stringifies the whole array and produces invalid URLs once multiple endpoints are configured.

Suggested fix
   httpInbound.app.get(
     '/invitation',
     async (req: { query: { d_m: any; c_i: any }; url: string }, res: { send: (arg0: any) => void }) => {
       if (typeof req.query.d_m === 'string') {
         const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url.replace('d_m=', 'c_i='))
-        res.send(invitation.toJSON())
-      }
-      if (typeof req.query.c_i === 'string') {
+        return res.send(invitation.toJSON())
+      } else if (typeof req.query.c_i === 'string') {
         const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url)
-        res.send(invitation.toJSON())
+        return res.send(invitation.toJSON())
       } else {
+        if (endpoints.length === 0) {
+          throw new Error('At least one endpoint is required')
+        }
         const { outOfBandInvitation } = await agent.modules.didcomm.oob.createInvitation()
-
-        res.send(outOfBandInvitation.toUrl({ domain: endpoints + '/invitation' }))
+        return res.send(outOfBandInvitation.toUrl({ domain: new URL('/invitation', endpoints[0]).toString() }))
       }
     },
   )
📝 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
httpInbound.app.get(
'/invitation',
async (req: { query: { d_m: any; c_i: any }; url: string }, res: { send: (arg0: any) => void }) => {
if (typeof req.query.d_m === 'string') {
const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url.replace('d_m=', 'c_i='))
res.send(invitation.toJSON())
}
if (typeof req.query.c_i === 'string') {
const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url)
res.send(invitation.toJSON())
} else {
const { outOfBandInvitation } = await agent.modules.didcomm.oob.createInvitation()
res.send(outOfBandInvitation.toUrl({ domain: endpoints + '/invitation' }))
}
})
res.send(outOfBandInvitation.toUrl({ domain: endpoints + '/invitation' }))
}
httpInbound.app.get(
'/invitation',
async (req: { query: { d_m: any; c_i: any }; url: string }, res: { send: (arg0: any) => void }) => {
if (typeof req.query.d_m === 'string') {
const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url.replace('d_m=', 'c_i='))
return res.send(invitation.toJSON())
} else if (typeof req.query.c_i === 'string') {
const invitation = await DidCommConnectionInvitationMessage.fromUrl(req.url)
return res.send(invitation.toJSON())
} else {
if (endpoints.length === 0) {
throw new Error('At least one endpoint is required')
}
const { outOfBandInvitation } = await agent.modules.didcomm.oob.createInvitation()
return res.send(outOfBandInvitation.toUrl({ domain: new URL('/invitation', endpoints[0]).toString() }))
}
},
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/agent.ts` around lines 149 - 163, The /invitation handler currently
uses two separate if blocks which can send multiple responses and builds an
invalid domain string from the endpoints array; change the control flow in
httpInbound.app.get to if (typeof req.query.d_m === 'string') { ... } else if
(typeof req.query.c_i === 'string') { ... } else { ... } so only one branch
sends a response, keep using DidCommConnectionInvitationMessage.fromUrl for the
d_m and c_i branches, and when creating the outOfBand invitation call
outOfBandInvitation.toUrl({ domain: Array.isArray(endpoints) ? endpoints[0] :
endpoints }) (or otherwise pick a single endpoint) instead of concatenating the
whole endpoints array.

Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
Signed-off-by: DeepakNemad <deepak.nemade@ayanworks.com>
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

5 participants