# koa-helmet is a thin adapter that puts helmet headers on Koa

> koa-helmet wraps the helmet middleware collection so its security headers can be applied in a Koa v2 or v3 application. It has no direct dependencies, ships both CommonJS and ES module builds with matching type declarations, and its own release line stalled in December 2025.

**venables/koa-helmet** — Important security headers for koa

- Repository: https://github.com/venables/koa-helmet
- Stars: 637 · Forks: 41
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/venables-koa-helmet

## An adapter, not a reimplementation

koa-helmet is a wrapper for helmet that works with koa, for Koa v2 and v3. Its purpose is stated plainly: it provides important security headers to make your app more secure by default.

That word wrapper matters, because it determines almost everything else about the project. The security logic, the header set, the defaults and the configuration options all come from helmet, and this package handles the part that differs between the two frameworks, which is how a middleware that sets headers on a Node response object is invoked from a Koa application.

The packaging reflects that. The readme states the package has zero direct dependencies, with peerDependencies of koa and helmet. So helmet is not bundled, it is declared as something your project must provide, and the version you install is the version whose behaviour you get. The peer range in the package metadata accepts helmet 6, 7 or 8.

For a reader, that means there is very little code here to review. The value is convenience and correct wiring, and the risk is that a breaking change in helmet reaches you through a peer dependency rather than through a dependency you control.

## Two packages to install

Installation takes both the adapter and the library it wraps:

```sh
npm i koa-helmet helmet

# or:

bun add koa-helmet helmet
```

The readme offers the Bun route alongside npm, which is a small signal about the audience, since the package is published as a modern dual format package rather than a CommonJS only one.

Because helmet is a peer dependency, this is the point where a version mismatch shows up. If your project already depends on helmet, npm will check the new install against the existing one and warn when the ranges do not overlap, which is the mechanism that stops two incompatible copies of helmet ending up in the tree.

Nothing else is required. There is no configuration file, no framework plugin registration and no environment variable to set.

## The same eleven middleware functions as helmet

Usage is the same as helmet, and the readme spells out the equivalence by showing the aggregate call and its expansion. helmet() as a single middleware is equivalent to eleven individual ones:

```js
// This...
app.use(helmet());

// ...is equivalent to this:
app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());
```

Two observations. First, because the API is identical, everything the helmet documentation says about configuring a content security policy or a referrer policy applies here, and the readme points at the helmet documentation for that.

Second, the individual form is the one to reach for when you need to adjust one header set and leave the rest at their defaults. Mounting eleven middlewares in a fixed order gives you that granularity, since each of them is configured independently, and the order in the list above is the order helmet itself uses.

## A minimal Koa application with the middleware mounted

The example in the readme is a complete Koa application:

```js
import Koa from "koa";
import helmet from "koa-helmet";

const app = new Koa();

app.use(helmet());

app.use((ctx) => {
  ctx.body = "Hello World";
});

app.listen(4000);
```

The shape is the familiar Koa one, a middleware chain, and the helmet call sits in front of the response handler so the headers are set on the way out.

One detail in that example is worth a second look. The response middleware takes only the context argument and does not call next, which matches the older Koa style of writing middleware, and it means the example does not show the two argument form. If you copy it into a Koa v3 application and then add another middleware after it, that middleware will not run, because the chain stops at the first middleware that does not call next. The fix is small, but it is the kind of thing that is easier to fix before you copy the example than after.

The example also shows the package being used from an ES module import, which matches the module field in the package metadata.

## CommonJS, ES modules and two type declaration files

The package metadata is worth reading because it shows the shape of the published artifact. The version is 9.0.0, the type field is commonjs, the main entry is the CommonJS build at dist/index.cjs and the module field points at the ES module build at dist/index.mjs.

The exports map is the interesting part, because it publishes two separate type declaration files rather than one shared one:

```json
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.mts",
        "default": "./dist/index.mjs"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    }
  },
```

The .d.mts and .d.cts extensions are the TypeScript convention for declarations that belong to the ES module and CommonJS resolution modes respectively, and shipping both avoids the well known problem where a single .d.ts is interpreted under the wrong module resolution and produces type errors for consumers.

Only the dist directory is published, so the source and the tests are not part of the tarball. The build is done with tsdown, invoked as tsdown src/index.ts with the esm and cjs formats, declarations enabled and a clean step, which is why the published layout is a build artifact rather than the TypeScript sources.

## One check command runs the whole pipeline

The testing section offers a single entry point. To run the test and lint suite, run npm check. The readme also lists the individual steps, which are npm run test, npm run lint and npm run format:check.

Looking at the scripts in the package metadata, the check command is a chain: format:check, then lint, then typecheck, then build, then test. The individual tools are oxfmt for formatting, oxlint for linting, tsc with the noEmit flag for type checking, and vitest for the tests. There is also a fix script that formats and applies lint fixes.

Two other scripts matter for a project that publishes this package. The changeset script runs the changesets CLI, and the repository has a .changeset/ directory, which is the mechanism behind the version numbers you see on npm. The prepublishOnly script runs the build, so the published artifact is always rebuilt from source at publish time.

The typecheck step deserves attention for a security header package. A mistake in the adapter that surfaced as a wrong header name or a missing option would not fail loudly at runtime, it would just quietly send the wrong header, and a type check is what catches that before release.

## The test matrix spans Koa 2, Koa 3 and three helmet majors

The devDependencies show how the compatibility claim is actually tested. The koa versions are installed under aliases, koa-2 pointing at koa 2.13 and koa-3 pointing at koa 3, and the helmet versions are aliased too, with helmet-7 resolving to helmet 7 and helmet-8 to helmet 8. The peer dependency range accepts helmet 6, 7 and 8, so three majors of the underlying library are covered by the suite.

The test framework is vitest, and the HTTP assertions use supertest with its type definitions, which is the usual way to check what headers a server actually sent.

The repository also carries an examples/ directory with a CommonJS example and an ES module example, which exist to check that both published entry points work under a real consumer's module resolution rather than only inside the test suite.

The tooling is deliberately small and modern. Formatting and linting are done by oxfmt and oxlint rather than prettier and eslint, and there is an oxlint-tsgolint dependency alongside them. The package also carries a publint dependency, which is the tool that checks whether a published package's entry points and type files are actually resolvable, and the reason the exports map is as careful as it is.

## Version support split across branches, and a slow release line

The versioning policy is stated in two lines. koa-helmet 2.x and later, on the main branch, supports koa 2.x and 3.x, while koa-helmet 1.x, on a separate koa-1 branch, supports koa 0.x and 1.x.

So the framework support is a branch decision rather than a version range. If you are still on Koa 1, this package is not for you, and no release of the current line will change that.

The release history shows a burst of activity late in 2025, with v8.0.2 on 2025-12-10, v8.0.3 on 2025-12-16 and v9.0.0 on 2025-12-28, the last of them a major bump on the Koa 2 and 3 support line. Since then the last push was on 2026-04-10, and the repository is not archived. The project is not abandoned, but the published line has not moved in months, so pin a version and expect to verify behaviour against the helmet major you install.

The licence is MIT, with the text in the LICENSE file, so there is no copyleft obligation on applications that use it, and the project carries the usual community files including CONTRIBUTING.md, a CHANGELOG.md and a code of conduct through the GitHub configuration.

## Conclusion

Adopt koa-helmet if your Koa application needs the standard set of security headers and you would rather not write the adapter yourself, since it exposes the same eleven helmet middleware functions and keeps helmet as a peer dependency you control. Skip it if you need Koa 0.x or 1.x, since those are only supported by the separate koa-1 branch, or if you are on a helmet major your peer range does not allow. Before you adopt it, check the peer dependency range against the helmet version you want, run npm check to exercise the format, lint, typecheck, build and test steps together, and note that the last push was on 2026-04-10, so the package is not moving quickly.

## FAQ

### What does koa-helmet do?

It is a wrapper for helmet that works with koa v2 and v3, providing the security headers to make an app more secure by default. Usage is the same as helmet, and it offers the same eleven security middleware functions.

### How do I install koa-helmet?

Install both the adapter and the library it wraps, with npm i koa-helmet helmet, or bun add koa-helmet helmet. The package has zero direct dependencies, and koa and helmet are peer dependencies, so helmet is not bundled and your project controls the version.

### Which Koa versions does koa-helmet support?

koa-helmet 2.x and later on the main branch supports koa 2.x and 3.x. Support for koa 0.x and koa 1.x is in the 1.x line, which lives on the separate koa-1 branch, and the readme points there for older applications.

### How do I run the koa-helmet tests and checks?

Run npm check to run the format check, lint, typecheck, build and test steps together, or run npm run test, npm run lint and npm run format:check individually. The test framework is vitest with supertest for the HTTP assertions, and the suite covers koa 2, koa 3 and helmet versions 7 and 8 through aliased devDependencies.

### Can I configure individual security headers with koa-helmet?

Yes. The single helmet() call is equivalent to mounting the eleven middleware functions individually, from contentSecurityPolicy through xssFilter, and each of them can be configured on its own. Configuration details are in the helmet documentation the readme links to.

## Sources

- [Issues](https://github.com/venables/koa-helmet/issues)
- [License: MIT](https://github.com/venables/koa-helmet/blob/main/LICENSE)
- [README](https://github.com/venables/koa-helmet/blob/main/README.md)
- [Releases](https://github.com/venables/koa-helmet/releases)
- [venables/koa-helmet on GitHub](https://github.com/venables/koa-helmet)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/venables-koa-helmet
