Upgrading Helmet to v4.5.0 and needing equivalent type to IHelmetContentSecurityPolicyDirectives

286 Views Asked by At

Just amending the dependencies used in a NodeJS/ Typescript application and have hit a snag with the Helmet change from version "3.23.2" to “4.5.0”.

I've removed the dependency "@types/helmet": "0.0.47" from the package.json file.

A compilation results in the following semantic errors:

src/loaders/security.ts(2,18): error TS2305: Module '"helmet"' has no exported member 'IHelmetContentSecurityPolicyDirectives'.
src/options.ts(1,10): error TS2305: Module '"helmet"' has no exported member 'IHelmetContentSecurityPolicyDirectives'.

options.ts includes:

import { IHelmetContentSecurityPolicyDirectives } from 'helmet';

export interface Options {
  redirectUrl: string;
  mountPath: string;
  serviceName?: string;
  views?: string | string[];
  csp?: IHelmetContentSecurityPolicyDirectives;
  i18n?: I18nOptions;
}

security.ts is defined as:

import { Application } from 'express';
import helmet, { IHelmetContentSecurityPolicyDirectives } from 'helmet';
import logger from '../lib/logger';

const configureSecurity = (app: Application, csp: IHelmetContentSecurityPolicyDirectives | undefined): void => {
  logger.info('Configuring Security using Helmet');
  const defaultSrc = (csp && csp.defaultSrc) || [];
  const styleSrc = (csp && csp.styleSrc) || [];
  const scriptSrc = (csp && csp.scriptSrc) || [];
  app.use(helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: [...defaultSrc, "'self'"],
        styleSrc: [...styleSrc, "'self'"],
        scriptSrc: [
          ...scriptSrc,
          "'self'",
          "'sha256-+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'",
          "'sha256-+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'",
        ],
      },
    },
  }));
};

export default configureSecurity;

I can't work out what to use instead of IHelmetContentSecurityPolicyDirectives for the csp type.

1

There are 1 best solutions below

0
On BEST ANSWER

Maintainer of Helmet here.

Helmet v3 did not have official TypeScript definitions and Helmet v4 does. In short, you're seeing this problem because the community-made types for Helmet v3 don't map cleanly to the official types in Helmet v4.

You're looking for an alternative to IHelmetContentSecurityPolicyDirectives. Here's a snippet from Helmet's official type definitions for the Content Security Policy module:

export interface ContentSecurityPolicyOptions {
  directives?: Record<
    string,
    | Iterable<ContentSecurityPolicyDirectiveValue>
    | typeof dangerouslyDisableDefaultSrc
  >;
  reportOnly?: boolean;
}

The directives key of ContentSecurityPolicyOptions is the "reincarnation" of the old IHelmetContentSecurityPolicyDirectives.

I see two options:

  1. Define the type yourself, and then use it. For example:

    type CspDirectiveValue =
      | string
      | ((req: IncomingMessage, res: ServerResponse) => string);
    
    type CspDirectives = Record<string, Iterable<CspDirectiveValue>>;
    

    You can then use CspDirectives in place of the old IHelmetContentSecurityPolicyDirectives type.

  2. Rework your code a bit.

    You could update the Options interface to take all of Helmet's options:

    import helmet from 'helmet';
    
    export interface Options {
      // ...
      helmetOptions: Parameters<typeof helmet>[0];
      // ...
    }
    

    You can then use it in configureSecurity:

    const configureSecurity = (app: Application, helmetOptions: Parameters<typeof helmet>[0]): void => {
      // ...
      app.use(helmetOptions);
    };
    

    Your actual code might vary a bit.