honojs / hono

Web framework built on Web Standards
https://hono.dev
MIT License
18.49k stars 521 forks source link

Validate signed cookie throws on malformed URI #1906

Open eduardvercaemer opened 8 months ago

eduardvercaemer commented 8 months ago

What version of Hono are you using?

3.12.0

What runtime/platform is your app running on?

Cloudflare Workers

What steps can reproduce the bug?

  1. Call await getSignedCookie on some cookie.
  2. Then send a request where the cookie signature has an invalid URI encoding (e.g. remove a character from a sequence such as %3D -> %3)
  3. The function throws instead of returning false as expected of invalid signatures.

What is the expected behavior?

The function should return false.

What do you see instead?

The function throws.

Additional information

That's it.

yusukebe commented 8 months ago

Hi @eduardvercaemer !

Please give us a minimum reproducible code example so that we can debug easily.

ifritzler commented 7 months ago

Hello everyone, perhaps this code example illustrates an error scenario by deliberately crafting a malformed cookie to trigger the error. Although I believe the execution example is for Cloudflare Workers, I think it's also applicable to Node.js. I'm not sure in what scenarios a modified cookie like this would occur. Nevertheless, the server does not break or crash; it simply returns a status 500 error, which should be handled from the controller. Perhaps this is a misguided opinion—please enlighten me! 😄

@eduardvercaemer isn't it?

import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import { getSignedCookie, setSignedCookie } from 'hono/cookie'

const app = new Hono()

const cookieSecret = 'supersecret'

// FIRST EXECUTE THIS ENDPOINT TO SET THE COOKIE
app.get('/', async (c) => {
  await setSignedCookie(c, 'signed', 'signed value', cookieSecret)
  return c.text('Creating the signed cookie!')
})

// SECONDLY EXECUTE THIS TO FAKE THE MALFORMED COOKIE AND SEE THE ERROR
app.get('/issue', async (c) => {

  // Simulating a scenario where the cookie is malformed upon reception from the client
  const regex = /signed=([^;]+)/;
  const match = c.req.headers.get('Cookie')?.match(regex);

  if(match && match.length >= 1) {
    // Modifying the URI encoding to simulate potential manipulation by the client
    match[0] = match[0].replace('%20', '%2') + ';'
    c.req.headers.set('Cookie', match[0])
  }
  // Checking if the cookie should be invalid due to tampering
  const shouldBeFalse = await getSignedCookie(c, cookieSecret, 'signed')
  console.log(shouldBeFalse) // This would never be executed due to the error and the HTTP status code 500 response 
  return c.text('Issue with the cookie')
})

const port = 3000
console.log(`Server is running on port ${port}`)

serve({
  fetch: app.fetch,
  port
})

And the error:

URIError: URI malformed
    at decodeURIComponent (<anonymous>)
    at <anonymous> (c:\Users\ilan\Desktop\hono-projects\issue-1906\node_modules\hono\dist\cjs\utils\cookie.js:65:49)
    at Array.reduce (<anonymous>)
    at parse (c:\Users\ilan\Desktop\hono-projects\issue-1906\node_modules\hono\dist\cjs\utils\cookie.js:53:16)
    at parseSigned (c:\Users\ilan\Desktop\hono-projects\issue-1906\node_modules\hono\dist\cjs\utils\cookie.js:72:45)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at getSignedCookie (c:\Users\ilan\Desktop\hono-projects\issue-1906\node_modules\hono\dist\cjs\helper\cookie\index.js:47:18)
    at Array.<anonymous> (c:\Users\ilan\Desktop\hono-projects\issue-1906\src\index.ts:29:25)
    at responseViaResponseObject (c:\Users\ilan\Desktop\hono-projects\issue-1906\node_modules\@hono\node-server\dist\index.js:295:11)