Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fastify-helmet

Package Overview
Dependencies
Maintainers
13
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify-helmet - npm Package Compare versions

Comparing version 5.2.0 to 5.3.0

11

index.d.ts
import { FastifyPluginCallback } from "fastify";
import helmet = require("helmet");
type FastifyHelmetOptions = Parameters<typeof helmet>[0];
declare module 'fastify' {
interface FastifyReply {
cspNonce: {
script: string
style: string
}
}
}
type FastifyHelmetOptions = Parameters<typeof helmet>[0] & { enableCSPNonces?: boolean };
export const fastifyHelmet: FastifyPluginCallback<NonNullable<FastifyHelmetOptions>>;
export default fastifyHelmet;

@@ -5,4 +5,9 @@ 'use strict'

const helmet = require('helmet')
const crypto = require('crypto')
module.exports = fp(function (app, options, next) {
const enableCSPNonces = options.enableCSPNonces
// clear options as helmet will throw when any options is "true"
options.enableCSPNonces = undefined
const middleware = helmet(options)

@@ -14,2 +19,30 @@

if (enableCSPNonces) {
// outside onRequest hooks so that it can be reused in every route
const cspDirectives = options.contentSecurityPolicy ? options.contentSecurityPolicy.directives : helmet.contentSecurityPolicy.getDefaultDirectives()
const cspReportOnly = options.contentSecurityPolicy ? options.contentSecurityPolicy.reportOnly : undefined
app.decorateReply('cspNonce', null)
app.addHook('onRequest', function (req, reply, next) {
// create csp nonce
reply.cspNonce = {
script: crypto.randomBytes(16).toString('hex'),
style: crypto.randomBytes(16).toString('hex')
}
// push nonce to csp
// allow both script-src or scriptSrc syntax
const scriptKey = Array.isArray(cspDirectives['script-src']) ? 'script-src' : 'scriptSrc'
cspDirectives[scriptKey] = Array.isArray(cspDirectives.scriptSrc) ? cspDirectives.scriptSrc : []
cspDirectives[scriptKey].push('nonce-' + reply.cspNonce.script)
// allow both style-src or styleSrc syntax
const styleKey = Array.isArray(cspDirectives['style-src']) ? 'style-src' : 'styleSrc'
cspDirectives[styleKey] = Array.isArray(cspDirectives.styleSrc) ? cspDirectives.styleSrc : []
cspDirectives[styleKey].push('nonce-' + reply.cspNonce.style)
const cspMiddleware = helmet.contentSecurityPolicy({ directives: cspDirectives, reportOnly: cspReportOnly })
cspMiddleware(req.raw, reply.raw, next)
})
}
next()

@@ -16,0 +49,0 @@ }, {

@@ -0,3 +1,4 @@

import fastify from "fastify";
import { expectType } from "tsd";
import fastifyHelmet from ".";
import fastify from "fastify";

@@ -57,1 +58,19 @@ const app = fastify();

});
app.register(fastifyHelmet, { enableCSPNonces: true });
app.register(fastifyHelmet, {
enableCSPNonces: true,
contentSecurityPolicy: {
directives: {
'directive-1': ['foo', 'bar']
},
reportOnly: true
},
});
app.get('/', function(request, reply) {
expectType<{
script: string
style: string
}>(reply.cspNonce)
})

7

package.json
{
"name": "fastify-helmet",
"version": "5.2.0",
"version": "5.3.0",
"description": "Important security headers for Fastify",
"main": "index.js",
"scripts": {
"typescript": "tsd",
"lint": "standard",
"lint:fix": "standard --fix",
"test": "standard | snazzy && tap test.js && npm run typescript"
"test": "standard | snazzy && tap test.js && npm run typescript",
"test:ci": "standard | snazzy && tap test.js --coverage-report=lcovonly && npm run typescript",
"typescript": "tsd"
},

@@ -12,0 +13,0 @@ "repository": {

# fastify-helmet
[![npm version](https://img.shields.io/npm/v/fastify-helmet)](https://www.npmjs.com/package/fastify-helmet)
![CI workflow](https://github.com/fastify/fastify-helmet/workflows/CI%20workflow/badge.svg)
[![Known Vulnerabilities](https://snyk.io/test/github/fastify/fastify-helmet/badge.svg)](https://snyk.io/test/github/fastify/fastify-helmet)
[![Coverage Status](https://coveralls.io/repos/github/fastify/fastify-helmet/badge.svg?branch=master)](https://coveralls.io/github/fastify/fastify-helmet?branch=master)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/) ![CI
workflow](https://github.com/fastify/fastify-helmet/workflows/CI%20workflow/badge.svg)
Important security headers for Fastify. It is a tiny wrapper around
[helmet](http://npm.im/helmet).
[helmet](https://npm.im/helmet).

@@ -33,2 +35,77 @@ ## Install

### Content-Security-Policy Nonce
`fastify-helmet` provide a simple way for `csp nonces generation`. You can enable
this behavior by passing `{ enableCSPNonces: true }` into the options. Then, you can
retrieve the `nonces` through `reply.cspNonce`.
Note: This feature is implemented inside this module. It is not a valid option or
supported by helmet. If you need to use helmet feature only for csp nonce you
can follow the example [here](#example---generate-by-helmet).
#### Example - Generate by options
```js
fastify.register(
helmet,
// enable csp nonces generation with default content-security-policy option
{ enableCSPNonces: true }
)
fastify.register(
helmet,
// customize content security policy with nonce generation
{
enableCSPNonces: true,
contentSecurityPolicy: {
directives: {
...
}
}
}
)
fastify.get('/', function(request, reply) {
// retrieve script nonce
reply.cspNonce.script
// retrieve style nonce
reply.cspNonce.style
})
```
#### Example - Generate by helmet
```js
fastify.register(
helmet,
{
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: [
function (req, res) {
// "res" here is actually "reply.raw" in fastify
res.scriptNonce = crypto.randomBytes(16).toString('hex')
}
],
styleSrc: [
function (req, res) {
// "res" here is actually "reply.raw" in fastify
res.styleNonce = crypto.randomBytes(16).toString('hex')
}
]
}
}
}
)
fastify.get('/', function(request, reply) {
// you can access the generated nonce by "reply.raw"
reply.raw.scriptNonce
reply.raw.styleNonce
})
```
## How it works

@@ -35,0 +112,0 @@

@@ -137,1 +137,65 @@ 'use strict'

})
test('auto generate nonce pre request', async (t) => {
t.plan(7)
const fastify = Fastify()
fastify.register(helmet, {
enableCSPNonces: true
})
fastify.get('/', (request, reply) => {
t.ok(reply.cspNonce)
reply.send(reply.cspNonce)
})
let cspCache, res
try {
res = await fastify.inject({ method: 'GET', url: '/' })
cspCache = res.json()
t.ok(cspCache.script)
t.ok(cspCache.style)
res = await fastify.inject({ method: 'GET', url: '/' })
const newCsp = res.json()
t.notEqual(cspCache, newCsp)
t.ok(cspCache.script)
t.ok(cspCache.style)
} catch (err) {
t.error(err)
}
})
test('allow merging options for enableCSPNonces', async (t) => {
t.plan(4)
const fastify = Fastify()
fastify.register(helmet, {
enableCSPNonces: true,
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'"]
}
}
})
fastify.get('/', (request, reply) => {
t.ok(reply.cspNonce)
reply.send(reply.cspNonce)
})
try {
const res = await fastify.inject({ method: 'GET', url: '/' })
const cspCache = res.json()
t.ok(cspCache.script)
t.ok(cspCache.style)
t.includes(res.headers, {
'content-security-policy': `default-src 'self';script-src 'self' nonce-${cspCache.script};style-src 'self' nonce-${cspCache.style}`
})
} catch (err) {
t.error(err)
}
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc