diff --git a/packages/techdocs-common/src/stages/publish/helpers.test.ts b/packages/techdocs-common/src/stages/publish/helpers.test.ts index 1fae66f3d2..ae872be016 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.test.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.test.ts @@ -20,7 +20,7 @@ import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; describe('getHeadersForFileExtension', () => { const correctMapOfExtensions = [ - ['.html', 'text/html; charset=utf-8'], + ['.html', 'text/plain; charset=utf-8'], ['.css', 'text/css; charset=utf-8'], ['.png', 'image/png'], ['.jpg', 'image/jpeg'], diff --git a/packages/techdocs-common/src/stages/publish/helpers.ts b/packages/techdocs-common/src/stages/publish/helpers.ts index 138ec611e0..63568699c7 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.ts @@ -28,10 +28,18 @@ export type responseHeadersType = { export const getHeadersForFileExtension = ( fileExtension: string, ): responseHeadersType => { - return { + const headerType = { 'Content-Type': mime.contentType(fileExtension) || 'text/plain; charset=utf-8', - } as responseHeadersType; + }; + + // Prevent sanitization bypass by preventing browers from directly rendering + // the contents of HTML files kept in storage. + if (headerType['Content-Type'].match(/html/)) { + headerType['Content-Type'] = 'text/plain; charset=utf-8'; + } + + return headerType; }; /** diff --git a/packages/techdocs-common/src/stages/publish/local.ts b/packages/techdocs-common/src/stages/publish/local.ts index e09473cf60..036053627b 100644 --- a/packages/techdocs-common/src/stages/publish/local.ts +++ b/packages/techdocs-common/src/stages/publish/local.ts @@ -31,6 +31,7 @@ import { ReadinessResponse, TechDocsMetadata, } from './types'; +import { getHeadersForFileExtension } from './helpers'; // TODO: Use a more persistent storage than node_modules or /tmp directory. // Make it configurable with techdocs.publisher.local.publishDirectory @@ -132,7 +133,16 @@ export class LocalPublish implements PublisherBase { } docsRouter(): express.Handler { - return express.static(staticDocsDir); + return express.static(staticDocsDir, { + // Handle content-type header the same as all other publishers. + setHeaders: (res, filePath) => { + const fileExtension = path.extname(filePath); + const { 'Content-Type': header } = getHeadersForFileExtension( + fileExtension, + ); + res.setHeader('Content-Type', header); + }, + }); } async hasDocsBeenGenerated(entity: Entity): Promise {