npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

cf-hardhat

v0.2.3

Published

HTTP security middleware to protect serverless Workers and Functions

Downloads

193

Readme

CF Hardhat

cf-hardhat provides middlewares that protect serverless Workers and Pages on Cloudflare by adding security headers to HTTP responses.

Modules

  • Content Security Policy (CSP) middleware (cf-hardhat/csp)
  • Cross-Origin Resource Sharing (CORS) Access-Control Middleware (cf-hardhat/cors)
  • HTTP Strict Transport Security (HSTS) middleware (cf-hardhat/hsts)

Installation

npm install --save-dev cf-hardhat

Basic Usage

import {getCspMiddleware} from "cf-hardhat/csp";
import {getCorsMiddleware} from "cf-hardhat/cors";
import {getHstsMiddleware} from "cf-hardhat/hsts";

export const onRequest = [
    // Each returns a PagesFunction
    getCspMiddleware(),
    getCorsMiddleware(),
    getHstsMiddleware()
];

Content-Security-Policy Middleware

The factory function getCspMiddleware returns a PagesFunction that generates a Content-Security-Policy header and adds it to the response.

Features:

  • Use nonces inscript-src and style-src directives
  • Specify how nonces are inserted into your pages, or automatically inject them
  • Define directives that depend on environment variables

Usage

The CspOptions include policies configuration. Policies may be defined as an array of strings, or as a function that resolves to a string, given a context with env.

// In functions/_middleware.ts:
import {getCspMiddleware} from "cf-hardhat/csp";

// Using the default options
const cspMiddleware = getCspMiddleware();

// Populate directives from Environment variables
let cspOpts: CspOptions = {
    policies: {
        ... 
        'frame-src': ["'self'", "https:"],
        'frame-ancestors': (context) => `${context.env.ALLOWED_FRAME_ANCESTORS}`,
        ... 
    }
};
const cspMiddleware = getCspMiddleware(cspOpts);

export const onRequest = [
    // ... other PagesFunctions
    cspMiddleware
];

Nonce Callback

If using nonces, a function can be passed and called with the nonce to return a PagesFunction that injects the nonce into the page.

If specifying a callback to inject the nonce, one should use a templating engine (like mustache or ejs) and add placeholders to HTML templates:

<script type="text/javascript" src="trusted.js" nonce="{{nonce}}"></script>
<link rel="stylesheet" href="style.css" nonce="{{nonce}}"/>

For example,

// In functions/_middleware.ts:
import {CspOptions, getCspMiddleware} from "cf-hardhat/csp";
import Mustache from "mustache";

const cspOpts: CspOptions = {
    policies: {...},
    nonce: { 
        // Specify which CSP directives should declare a nonce
        directives: ['script-src'], // default: script-src, style-src

        // Specify how nonces are injected:
        callback: (nonce: string) => {
            return async (context) => {
                let response = await context.next();
                let contentType = response.headers.get("content-type");
                if (contentType?.startsWith("text/html")) {
                    let template = await response.text();
                    // Insert via HTML templating engine, such as mustache
                    let rendered = Mustache.render(template, {
                        nonce: nonce
                    });
                    return new Response(rendered, {
                        status: 200,
                        headers: {
                            ...response.headers.entries(),
                        }
                    });
                } else {
                    return response;
                }
            }
        }
    }
};

If a page includes dynamically-rendered content, using a templating engine provides the benefits:

  • Templating allows one to insert the nonce before or at the same time as rendering dynamic content. This prevents nonces from being inserted into XSS payloads that result from rendering the content. (E.g. if content includes <script nonce="{{nonce}}">)
  • Output is safely encoded for HTML by default, mitigating persisted XSS attacks. (E.g. <script> is rendered as &lt;script&gt;)

If that seems overly complicated, there's good news! A more convenient alternative exists: autoInjectTags.

Automatically Inject Nonces

autoInjectTags can be defined to automatically insert nonces into all specified tags present in the page.

{
...
    nonce: {
        autoInjectTags: ["script", "link", "style"]
    }
}

For static web pages, this option may not be any less secure than defining a nonce callback. See Caveats below, as well as this CSP Demo, which demonstrates the effects of automatically injecting nonces ("MODERATE" mode) versus defining a nonce callback using a templating engine ("STRICT" mode).

What's the point of all this nonce sense?

Allowing all inline scripts may be a security risk; however, disallowing all inline scripts can be inconvenient and excessively strict for some threat models. Using nonces (or hashes), a Content Security Policy can allow certain scripts and styles to load, provided they have the right value.

The script-src directive of a Content-Security-Policy header specifies which scripts may be loaded. If a nonce (a one-time, randomly-generated value) is used:

Content-Security-Policy: script-src 'nonce-{randomBase64Value}' ;

Then only script elements having a nonce attribute with the same randomBase64Value may load:

<!-- can load: -->
<script nonce="randomBase64Value">
    ...
</script>

<!-- can't load: -->
<script nonce="wrongBase64Value">
    ...
</script>

Caveats

Isn't it a risk to automatically inject nonces into all script tags?

Generally, yes. According to OWASP:

Don't create a middleware that replaces all script tags with "script nonce=..." because attacker-injected scripts will then get the nonces as well. You need an actual HTML templating engine to use nonces.

If an attacker's script is injected into an HTML response before it passes through the cf-hardhat CSP middleware with autoInjectTags enabled, the malicious script element would indeed get a valid nonce and be allowed to run by the browser.

How could an unwanted script get into a page before passing through the middleware?

This could happen if a persisted XSS payload is used unsanitized to dynamically build a web page. To mitigate this risk, any application accepting untrusted input should always validate and/or sanitize input server-side, and any application rendering untrusted content should always encode output to ensure it remains content and doesn't become code.

If proper output encoding and input sanitization are employed, the risk of using autoInjectTags may be acceptable. See this CSP Demo to compare various strategies and their effects on security.

Applications should apply defense in depth according to a threat model.

See more at Mozilla Developer docs

Cross-Origin Resource Sharing (CORS) Middleware

This middleware sets headers that control how a site may be accessed - notably, which origins may access a site.

Features

  • Respond to Preflight OPTIONS requests with CORS headers and 204 No Content
  • Add CORS headers to responses

Usage

import {getCorsMiddleware} from "cf-hardhat/cors";
// Use default values
const corsMiddleware = getCorsMiddleware();
// or provide custom:
const corsMiddleware = getCorsMiddleware({
    'access-control-allow-origin': ['https://example.com'], 
    'access-control-allow-methods': ['GET', 'POST'],
    'access-control-allow-headers': ['X-Requested-By']
});

export const onRequest = [
    // ... other PagesFunctions
    corsMiddleware
];

HTTP Strict Transport Security

This middleware adds the Strict-Transport-Security header to responses, which tells the browser "only load this site (and subdomains) over encrypted HTTPS"

import { getHstsMiddleware } from "cf-hardhat/hsts";

const hstsMiddleware = getHstsMiddleware();
// Using defaults, resulting header is:
// Strict-Transport-Security: max-age=31536000, includeSubdomains
export const onRequest = [
    // ... other PagesFunctions
    hstsMiddleware
];