Skip to content

fix(jwt): prevent memory leak by avoiding mutation of options object#4759

Open
EdamAme-x wants to merge 6 commits intohonojs:mainfrom
EdamAme-x:fix/jwks-keys-growth
Open

fix(jwt): prevent memory leak by avoiding mutation of options object#4759
EdamAme-x wants to merge 6 commits intohonojs:mainfrom
EdamAme-x:fix/jwks-keys-growth

Conversation

@EdamAme-x
Copy link
Contributor

@EdamAme-x EdamAme-x commented Feb 23, 2026

The current implementation mutates the keys in the options object, which causes a memory leak.

The author should do the following, if applicable

  • Add tests
  • Run tests
  • bun run format:fix && bun run lint:fix to format the code

@EdamAme-x EdamAme-x changed the title fix(jwt): memory leak fix(jwt): prevent memory leak by avoiding mutation of options object Feb 23, 2026
@codecov
Copy link

codecov bot commented Feb 23, 2026

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.47%. Comparing base (df97e5f) to head (c6cbb4e).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
src/utils/jwt/jwt.ts 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4759      +/-   ##
==========================================
- Coverage   91.48%   91.47%   -0.01%     
==========================================
  Files         177      177              
  Lines       11551    11550       -1     
  Branches     3353     3353              
==========================================
- Hits        10567    10565       -2     
- Misses        983      984       +1     
  Partials        1        1              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@usualoma
Copy link
Member

Hi @EdamAme-x
Thanks for creating the pull request!

As you pointed out, I also think changing the value of the options passed as an argument is a bug that should be fixed. Thank you for noticing this important detail.

By the way, since a linear search is ultimately performed as follows, and the first found .kid key is used as a result, I think it's better to omit mergeJwkKeys and use the following approach to reduce the amount of code. What do you think?

verifyKeys.find((key) => key.kid === header.kid)
diff --git i/src/utils/jwt/jwt.ts w/src/utils/jwt/jwt.ts
index 16ba0209..1f2872f7 100644
--- i/src/utils/jwt/jwt.ts
+++ w/src/utils/jwt/jwt.ts
@@ -188,26 +188,6 @@ const symmetricAlgorithms: SymmetricAlgorithm[] = [
   AlgorithmTypes.HS512,
 ]
 
-const mergeJwkKeys = (
-  existingKeys: readonly HonoJsonWebKey[],
-  fetchedKeys: readonly HonoJsonWebKey[]
-): HonoJsonWebKey[] => {
-  const mergedKeys: HonoJsonWebKey[] = []
-  const seenKids = new Set<string>()
-
-  for (const key of [...existingKeys, ...fetchedKeys]) {
-    if (typeof key.kid === 'string') {
-      if (seenKids.has(key.kid)) {
-        continue
-      }
-      seenKids.add(key.kid)
-    }
-    mergedKeys.push(key)
-  }
-
-  return mergedKeys
-}
-
 export const verifyWithJwks = async (
   token: string,
   options: {
@@ -239,7 +219,7 @@ export const verifyWithJwks = async (
     throw new JwtAlgorithmNotAllowed(header.alg, options.allowedAlgorithms)
   }
 
-  let verifyKeys = options.keys ? [...options.keys] : undefined
+  const verifyKeys = options.keys ? [...options.keys] : []
 
   if (options.jwks_uri) {
     const response = await fetch(options.jwks_uri, init)
@@ -253,7 +233,7 @@ export const verifyWithJwks = async (
     if (!Array.isArray(data.keys)) {
       throw new Error('invalid JWKS response. "keys" field is not an array')
     }
-    verifyKeys = mergeJwkKeys(verifyKeys ?? [], data.keys as HonoJsonWebKey[])
+    verifyKeys.push(...data.keys as HonoJsonWebKey[])
   } else if (!verifyKeys) {
     throw new Error('verifyWithJwks requires options for either "keys" or "jwks_uri" or both')
   }

@EdamAme-x
Copy link
Contributor Author

I think so! thanks you!

@usualoma
Copy link
Member

Hi @EdamAme-x
Thank you. LGTM!

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.

2 participants