Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⬆️ Update dependency hono to v3.11.7 [SECURITY] #45

Merged
merged 1 commit into from
Jan 11, 2024

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Jan 3, 2024

Mend Renovate

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
hono (source) 3.2.7 -> 3.11.7 age adoption passing confidence

GitHub Vulnerability Alerts

CVE-2023-50710

Impact

The clients may override named path parameter values from previous requests if the application is using TrieRouter. So, there is a risk that a privileged user may use unintended parameters when deleting REST API resources.

TrieRouter is used either explicitly or when the application matches a pattern that is not supported by the default RegExpRouter.

The code to reproduce it. The server side application:

import { Hono } from 'hono'
import { TrieRouter } from 'hono/router/trie-router'

const wait = async (ms: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

const app = new Hono({ router: new TrieRouter() })

app.use('*', async (c, next) => {
  await wait(Math.random() * 200)
  return next()
})

app.get('/modules/:id/versions/:version', async (c) => {
  const id = c.req.param('id')
  const version = c.req.param('version')

  console.log('path', c.req.path)
  console.log('version', version)

  return c.json({
    id,
    version,
  })
})

export default app

The client code which makes requests to the server application:

const examples = [
  'http://localhost:8787/modules/first/versions/first',
  'http://localhost:8787/modules/second/versions/second',
  'http://localhost:8787/modules/third/versions/third',
]

const test = () => {
  for (const example of examples) {
    fetch(example)
      .then((response) => response.json())
      .then((data) => {
        const splitted = example.split('/')
        const expected = splitted[splitted.length - 1]

        if (expected !== data.version) {
          console.error(`Error: exprected ${expected} but got ${data.version} - url was ${example}`)
        }
      })
  }
}

test()

The results:

Error: exprected second but got third - url was http://localhost:8787/modules/second/versions/second
Error: exprected first but got third - url was http://localhost:8787/modules/first/versions/first

Patches

"v3.11.7" includes the change to fix this issue.

Workarounds

Don't use TrieRouter directly.

// DON'T USE TrieRouter
import { TrieRouter } from 'hono/router/trie-router'
const app = new Hono({ router: new TrieRouter() })

References

Router options on the Hono website: https://hono.dev/api/hono#router-option


Release Notes

honojs/hono (hono)

v3.11.7

Compare Source

Security Update

This release includes a security patch that fixes the vulnerability in TrieRouter.

If you are using the default preset or hono/quick, or specifying the router as TrieRouter, you must upgrade to this version 3.11.7 immediately.

How to upgrade

For Deno

Just increment the version specifier to v3.11.7.

import { Hono } from 'https://deno.land/x/hono@v3.11.7/mod.ts'
import { serveStatic } from 'https://deno.land/x/hono@v3.11.7/middleware.ts'
For Node.js

Upgrade the hono package via npm:

npm install hono

// OR

yarn add hono

// OR

pnpm up hono

You may not update the hono package with npm update, so please use npm install.

The vulnerability detail

The clients may override named path parameter values from previous requests if the application is using TrieRouter. So, there is a risk that a privileged user may use unintended parameters when deleting REST API resources.

TrieRouter is used either explicitly or when the application matches a pattern that is not supported by the default RegExpRouter.

The advisory: GHSA-f6gv-hh8j-q8vq

Our Approach to Security

If you discover such a vulnerability, please contact us immediately. We will respond immediately; we have enabled GitHub's private vulnerability reporting feature, so please use that.

https://github.com/honojs/hono/security/advisories

Thanks.


Full Changelog: honojs/hono@v3.11.6...v3.11.7

v3.11.6

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.11.5...v3.11.6

v3.11.5

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.11.4...v3.11.5

v3.11.4

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.11.3...v3.11.4

v3.11.3

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.11.2...v3.11.3

v3.11.2

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.11.1...v3.11.2

v3.11.1

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.11.0...v3.11.1

v3.11.0

Compare Source

Hono v3.11.0 is now available! Let's take a look at the new features.

ErrorBoundary

This release introduces the new JSX component ErrorBoundary. It allows you to catch errors in child components.

For instance, in the example below, it will display the content specified in fallback if an error occurs.

import { ErrorBoundary } from 'hono/jsx'

// ...

function SyncComponent() {
  throw new Error('Error')
  return <div>Hello</div>
}

app.get('/sync', async (c) => {
  return c.html(
    <html>
      <body>
        <ErrorBoundary fallback={<div>Out of Service</div>}>
          <SyncComponent />
        </ErrorBoundary>
      </body>
    </html>
  )
})

ErrorBoundary can be used with asynchronous components and Suspense as well.

async function AsyncComponent() {
  await new Promise((resolve) => setTimeout(resolve, 2000))
  throw new Error('Error')
  return <div>Hello</div>
}

app.get('/with-suspense', async (c) => {
  return c.html(
    <html>
      <body>
        <ErrorBoundary fallback={<div>Out of Service</div>}>
          <Suspense fallback={<div>Loading...</div>}>
            <AsyncComponent />
          </Suspense>
        </ErrorBoundary>
      </body>
    </html>
  )
})

Thanks to @​usualoma!

createFactory() and createHandlers()

The Factory helper now provides createFactory(), which creates an instance of the Factory class.

import { createFactory } from 'hono/factory'

const factory = createFactory()

createHandlers() in a Factory class instance assists in defining handlers.

import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'

// ...

const factory = createFactory<Env>()

const middleware = factory.createMiddleware(async (c, next) => {
  c.set('foo', 'bar')
  await next()
})

const handlers = factory.createHandlers(logger(), middleware, (c) => {
  return c.json(c.var.foo)
})

app.get('/api', ...handlers)

Dev Helper

Dev Helper is now available.

Instead of using app.showRoutes(), the showRoutes() function exported from hono/dev will display the registered routes in your console.

Consider an application like the following:

import { showRoutes } from 'hono/dev'

// ...

const app = new Hono().basePath('/v1')

app.get('/posts', (c) => {
  // ...
})

app.get('/posts/:id', (c) => {
  // ...
})

app.post('/posts', (c) => {
  // ...
})

showRoutes(app)

When this application starts, the routes will be displayed in your console as follows:

GET   /v1/posts
GET   /v1/posts/:id
POST  /v1/posts

Thanks to @​usualoma!

app.showRoutes has been deprecated.

c.json() supports RPC

c.json() now supports RPC, meaning you no longer need to use c.jsonT() for RPC-mode.

SS

c.jsonT() has been deprecated.

Thanks to @​usualoma!

c.req.routePath

You can retrieve the registered path within the handler as shown below:

app.get('/posts/:id', (c) => {
  return c.json({ path: c.req.routePath })
})

If you access /posts/123, it will return /posts/:id:

{ "path": "/posts/:id" }

Thanks to @​usualoma!

Other new features

All Updates

New Contributors

Full Changelog: honojs/hono@v3.10.5...v3.11.0

v3.10.5

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.10.4...v3.10.5

v3.10.4

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.10.3...v3.10.4

v3.10.3

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.10.2...v3.10.3

v3.10.2

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.10.1...v3.10.2

v3.10.1

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.10.0...v3.10.1

v3.10.0

Compare Source

Hono v3.10.0 is now available! Let's explore the new features.

Support for Async Components in JSX

Hono's JSX now supports Async Components. You can use async/await in your components.

const fetchData = async () => {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos/1')
  return res.json<{ title: string }>()
}

const Component = async () => {
  const data = await fetchData()
  return <div>{data.title}</div>
}

app.get('/', (c) => {
  return c.html(
    <html>
      <body>
        <h1>Hono v3.10.0</h1>
        <Component />
      </body>
    </html>
  )
})

Thanks, @​usualoma!

Introduction of Suspense and renderToReadableStream()

With the Async Component, as shown above, it will await until fetch is completed. But now, if you want to render HTML before that, you can use Suspense.

When you use Suspense with renderToReadableStream(), it initially renders the content in fallback. After the Promise in Suspense is resolved, the real content is rendered.

import { renderToReadableStream, Suspense } from 'hono/jsx/streaming'

// ...

app.get('/', (c) => {
  const stream = renderToReadableStream(
    <html>
      <body>
        <h1>Hono v3.10.0</h1>
        <Suspense fallback={<div>loading...</div>}>
          <Component />
        </Suspense>
      </body>
    </html>
  )
  return c.body(stream, {
    headers: {
      'Content-Type': 'text/html; charset=UTF-8',
      'Transfer-Encoding': 'chunked'
    }
  })
})

If you make Component sleep for 2 seconds, the result will be as follows:

Area.mp4

Thanks, @​usualoma!

JSX Renderer Middleware Now Supports stream

The JSX Renderer Middleware now supports stream, allowing you to use Suspense with it. You can return streaming responses without renderToReadableStream() and without writing header values such as Transfer-Encoding: chunked.

import { jsxRenderer } from 'hono/jsx-renderer'

// ...

app.get(
  '*',
  jsxRenderer(
    ({ children }) => {
      return (
        <html>
          <body>
            <h1>Hono v3.10.0</h1>
            {children}
          </body>
        </html>
      )
    },
    {
      stream: true
    }
  )
)

app.get('/', (c) => {
  return c.render(
    <Suspense fallback={<div>loading...</div>}>
      <Component />
    </Suspense>
  )
})

Thanks, @​usualoma!

AWS Lambda Adapter Now Supports Streaming Response

The streamHandle is now available in the AWS Lambda adapter. With this, AWS Lambda can handle streaming responses.

import { Hono } from 'hono'
import { streamHandle } from 'hono/aws-lambda'

const app = new Hono()

app.get('/stream', async (c) => {
  return c.streamText(async (stream) => {
    for (let i = 0; i < 3; i++) {
      await stream.writeln(`${i}`)
      await stream.sleep(1)
    }
  })
})

const handler = streamHandle(app)

Thanks, @​watany-dev!

Support @jsx precompile for Deno

Now, Hono's JSX supports the precompile feature for Deno. To enable it, write deno.json as follows.

{
  "compilerOptions": {
    "jsx": "precompile",
    "jsxImportSource": "hono/jsx"
  },
  "imports": {
    "hono/jsx/jsx-runtime": "https://deno.land/x/hono@v3.10.0/jsx/jsx-runtime.ts"
  }
}

Thanks, @​usualoma!

Ecosystem

The ecosystem is evolving. Today, we introduce one framework using Hono.

  • Ree.js https://ree.js.org/ - Ree.js is a library that makes web development faster and easier by providing features such as URL Imports, JSX support, and server-side rendering.

All Updates

New Contributors

Full Changelog: honojs/hono@v3.9.2...v3.10.0

v3.9.2

Compare Source

Security Update for Windows

This release includes a security patch that fixes the vulnerability for serveStatic on Windows OS. If you run a Hono app on Windows with Deno or Node.js, you must upgrade to this version 3.9.2 immediately.

Note: You don't need upgrade it right now if you run it on Cloudflare, Deno on Linux/Unix/macOS, Deno Deploy, Bun, or Node.js on Linux/Unix/macOS.

How to upgrade

For Deno

Just increment the version specifier to v3.9.2.

import { Hono } from 'https://deno.land/x/hono@v3.9.2/mod.ts'
import { serveStatic } from 'https://deno.land/x/hono@v3.9.2/middleware.ts'
For Node.js

Upgrade the hono package via npm:

npm install hono

// OR

yarn add hono

// OR

pnpm up hono

You may not update the hono package with npm update, so please use npm install.

Our Approach to Security

If you discover such a vulnerability, please contact us immediately. We will respond immediately; we have enabled GitHub's private vulnerability reporting feature, so please use that.

https://github.com/honojs/hono/security/advisories

Thanks.

What's Changed

Full Changelog: honojs/hono@v3.9.1...v3.9.2

v3.9.1

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.9.0...v3.9.1

v3.9.0

Compare Source

Release Notes

Hono v3.9.0 is out now! Let's take a look at what's new.

Improving the Developer Experience for JSX

Now we have the types for JSX.

Type definitions for JSX intrinsic elements are available. So, you can write your JSX with type annotation.

Screenshot 2023-10-27 at 16 03 54 Screenshot 2023-10-27 at 16 04 30

You can also override the definitions to add your custom elements and attributes.

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'my-custom-element': Hono.HTMLAttributes & {
        'x-event'?: 'click' | 'scroll'
      }
    }
  }
}

Clerk Middleware

Now Clerk Middleware is available! You can use Clerk for authentication in your application.

import { clerkMiddleware, getAuth } from '@&#8203;hono/clerk-auth'
import { Hono } from 'hono'

const app = new Hono()

app.use('*', clerkMiddleware())
app.get('/', (c) => {
  const auth = getAuth(c)

  if (!auth?.userId) {
    return c.json({
      message: 'You are not logged in.'
    })
  }

  return c.json({
    message: 'You are logged in!',
    userId: auth.userId
  })
})

export default app

Thanks @​octoper!

New Starter Template for Cloudflare Pages

The Cloudflare Pages starter template is now Vite-based! You can develop truly full-stack applications quickly and fast thanks to Vite's HMR.

SC

It uses Hono's original dev-server provided by @​hono/vite-dev-server. And uses @​hono/vite-cloudflare-pages for building the application. The config file is very neat.

import { defineConfig } from 'vite'
import devServer from '@&#8203;hono/vite-dev-server'
import pages from '@&#8203;hono/vite-cloudflare-pages'

export default defineConfig({
  plugins: [
    pages(),
    devServer({
      entry: 'src/index.tsx'
    })
  ]
})

You can use it with the create hono command:

npm create hono@latest

Ecosystem

The ecosystem has evolved. We introduce two products for Hono and one framework using Hono. Try them!

All Updates

v3.8.4

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.8.3...v3.8.4

v3.8.3

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.8.2...v3.8.3

v3.8.2

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.8.1...v3.8.2

v3.8.1

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.8.0...v3.8.1

v3.8.0

Compare Source

Hono v3.8.0 is out now! Let's take a look at the new features.

JSX Context API

The new feature for JSX. By using useContext(), you can share data globally across any level of the Component tree without passing values through props.

import type { FC } from 'hono/jsx'
import { createContext, useContext } from 'hono/jsx'

const themes = {
  light: {
    color: '#&#8203;000000',
    background: '#eeeeee'
  },
  dark: {
    color: '#ffffff',
    background: '#&#8203;222222'
  }
}

const ThemeContext = createContext(themes.light)

const Button: FC = () => {
  const theme = useContext(ThemeContext)
  return <button style={theme}>Push!</button>
}

const Toolbar: FC = () => {
  return (
    <div>
      <Button />
    </div>
  )
}

app.get('/', (c) => {
  return c.html(
    <div>
      <ThemeContext.Provider value={themes.dark}>
        <Toolbar />
      </ThemeContext.Provider>
    </div>
  )
})

Thanks @​usualoma!

JSX Renderer Middleware

JSX Renderer Middleware allows you to set up the layout when rendering JSX with the c.render() function, without the need for using c.setRenderer(). Additionally, it enables access to instances of Context within components through the use of useRequestContext().

import { Hono } from 'hono'
import { jsxRenderer, useRequestContext } from 'hono/jsx-renderer'

const app = new Hono()

const RequestUrlBadge: FC = () => {
  const c = useRequestContext()
  return <b>{c.req.url}</b>
}

app.get(
  '/page/*',
  jsxRenderer(({ children }) => {
    return (
      <html>
        <body>
          <nav>Menu</nav>
          <div>{children}</div>
        </body>
      </html>
    )
  })
)

app.get('/page/about', (c) => {
  return c.render(
    <>
      <h1>About me!</h1>
      <div>
        You are accessing: <RequestUrlBadge />
      </div>
    </>
  )
})

Thanks @​usualoma!

Streaming Helper

The streaming Helper provides a method to extend c.stream(). streamSSE() allows you to stream Server-Sent Events (SSE) seamlessly.

import { Hono } from 'hono'
import { streamSSE } from 'hono/streaming'

const app = new Hono()

app.get('/sse', async (c) => {
  return streamSSE(c, async (stream) => {
    while (true) {
      const message = `It is ${new Date().toISOString()}`
      await stream.writeSSE({ data: message })
      await stream.sleep(1000)
    }
  })
})

Thanks @​watany-dev!

Factory Helper

The Factory Helper provides useful functions for creating Hono's components such as Middleware. Sometimes it's difficult to set the proper TypeScript types, but this helper facilitates that.

createMiddleware() that is added this version will create your custom middleware.

import { Hono } from 'hono'
import { createMiddleware } from 'hono/factory'

const messageMiddleware = createMiddleware(async (c, next) => {
  await next()
  c.res.headers.set('X-Message', 'Good morning!')
})

Thanks @​arunavabasu-03 for helping!

parseBody() supports multi values

Now, c.req.parseBody() supports multi values.

If the key is foo[], it will be (string | File)[].

const body = await c.req.parseBody()
body['foo[]']

And, you can use the all option.

const body = await c.req.parseBody({ all: true })
body['foo']

Thanks @​sor4chi!

Improve path matching in the router

Improved the path matching in the router. Previously, for instance, a Duplicate param name error would be thrown if there were parameters with the same name, type, url, as shown below:

app.get('/:type/:url', (c) => {
  return c.text(`type: ${c.req.param('type')}, url: ${c.req.param('url')}`)
})

app.get('/foo/:type/:url', (c) => {
  return c.text(`foo type: ${c.req.param('type')}, url: ${c.req.param('url')}`)
})

With this improvement, the error is no longer thrown, and the correct parameter values can be obtained in each handler.

Thanks @​usualoma!

All Updates

New Contributors

Full Changelog: honojs/hono@v3.7.6...v3.8.0

v3.7.6

Compare Source

What's Changed

New Contributors

Full Changelog: honojs/hono@v3.7.5...v3.7.6

v3.7.5

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.7.4...v3.7.5

v3.7.4

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.7.3...v3.7.4

v3.7.3

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.7.2...v3.7.3

v3.7.2

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.7.1...v3.7.2

v3.7.1

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.7.0...v3.7.1

v3.7.0

Compare Source

Hono v3.7.0 is out now! Let's take a look at the new features.

c.stream() and c.streamText()

We added the awaited functionality related to streaming. c.stream() and c.streamText().

You can easily create HTTP Streaming endpoints with them.

app.get('/', (c) => {
  return c.streamText(async (stream) => {
    stream.writeln('Hello!')
    await stream.sleep(1000)
    stream.writeln('Hono!')
  })
})

You know Streaming works well with AI. With streamText() you can write your ChatGPT Gateway in elegant code.

app.post('/api', async (c) => {
  const body = await c.req.json<{ message: string }>()

  const openai = new OpenAI({ apiKey: c.env.OPENAI_API_KEY })
  const chatStream = await openai.chat.completions.create({
    messages: PROMPT(body.message),
    model: 'gpt-3.5-turbo',
    stream: true
  })

  return c.streamText(async (stream) => {
    for await (const message of chatStream) {
      await stream.write(message.choices[0]?.delta.content ?? '')
    }
  })
})

This application can display streamed data from OpenAI's API in a flowing manner.

Screen.Recording.2023-09-21.at.11.11.36.mov

Thanks, @​sor4chi and @​geelen !

Testing Helper

With testClient in Testing Helper you can easily write your tests. The object returned by this function is the hc client, so you can define your request with the editor completion.

import { testClient } from 'hono/testing'

it('test', async() => {
  const app = new Hono().get('/search', (c) => c.jsonT({ hello: 'world' }))
  const res = await testClient(app).search.$get()

  expect(await res.json()).toEqual({ hello: 'world' })
})
sc.mov

Thanks, @​hagishi !

JWT helper

We uses JWT functions internally, but now they are exported as JWT Helper. You can import and use them.

import { decode, sign, verify } from 'hono/jwt'

Thanks, @​julianpoma !

All Updates

New Contributors

Full Changelog: honojs/hono@v3.6.3...v3.7.0

v3.6.3

Compare Source

What's Changed

Full Changelog: honojs/hono@v3.6.2...v3.6.3

v3.6.2

Compare Source

What's Changed
New Contributors

Full Changelog: honojs/hono@v3.6.1...v3.6.2

v3.6.1

Compare Source

This release includes tiny features and bug fixes.

What's Changed

@renovate renovate bot assigned InkoHX Jan 3, 2024
@InkoHX InkoHX merged commit 21f83ec into main Jan 11, 2024
6 checks passed
@renovate renovate bot deleted the renovate/npm-hono-vulnerability branch January 11, 2024 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant