diff --git a/CHANGELOG.md b/CHANGELOG.md index aa4b184..41202e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [v1.0.5] - 2025-12-09 + +### Removed +- Remove own version of CSP handler + ## [v1.0.4] - 2025-11-26 ### Changed diff --git a/csp.js b/csp.js deleted file mode 100644 index d19782f..0000000 --- a/csp.js +++ /dev/null @@ -1,67 +0,0 @@ -import { readFile } from 'node:fs/promises'; -import { imports } from '@shgysk8zer0/importmap'; -import { useCSP as CSP } from '@aegisjsproject/http-utils/csp.js'; - -const pkg = JSON.parse(await readFile(process.cwd() + '/package.json', { encoding: 'utf8' })); - -export const importmap = JSON.stringify({ - imports: { - ...imports, - [pkg.name]: pkg.exports['.'].import, - [`${pkg.name}/`]: './', - } -}); - -const sri = async (input) => await Promise.resolve(input) - .then(json => new TextEncoder().encode(json)) - .then(bytes => crypto.subtle.digest('SHA-384', bytes)) - .then(hash => 'sha384-' + new Uint8Array(hash).toBase64()); - -export const integrity = await sri(importmap); - -const DEFAULT_SRC = ['\'self\'']; -const SCRIPT_SRC = ['\'self\'', 'https://unpkg.com/@shgysk8zer0/', 'https://unpkg.com/@kernvalley/', 'https://unpkg.com/@aegisjsproject/', `'${integrity}'`]; -const STYLE_SRC = ['\'self\'', 'https://unpkg.com/@agisjsproject/', 'blob:']; -const IMAGE_SRC = ['\'self\'', 'https://i.imgur.com/', 'https://secure.gravatar.com/avatar/', 'blob:', 'data:']; -const MEDIA_SRC = ['\'self\'', 'blob:']; -const CONNECT_SRC = ['\'self\'']; -const FONT_SRC = ['\'self\'']; -const FRAME_SRC = ['\'self\'', 'https://www.youtube-nocookie.com']; -const TRUSTED_TYPES = ['aegis-sanitizer#html']; - -export const addDefaultSrc = (...srcs) => DEFAULT_SRC.push(...srcs); -export const addScriptSrc = (...srcs) => SCRIPT_SRC.push(...srcs); -export const addStyleSrc = (...srcs) => STYLE_SRC.push(...srcs); -export const addImageSrc = (...srcs) => IMAGE_SRC.push(...srcs); -export const addMediaSrc = (...srcs) => MEDIA_SRC.push(...srcs); -export const addConnectSrc = (...srcs) => CONNECT_SRC.push(...srcs); -export const addFontSrc = (...srcs) => FONT_SRC.push(...srcs); -export const addFrameSrc = (...srcs) => FRAME_SRC.push(...srcs); -export const addTrustedType = (...policies) => TRUSTED_TYPES.push(...policies); - -export const getCSP = () => [ - 'default-src ' + DEFAULT_SRC.join(' '), - 'script-src ' + SCRIPT_SRC.join(' '), - 'style-src ' + STYLE_SRC.join(' '), - 'img-src ' + IMAGE_SRC.join(' '), - 'media-src ' + MEDIA_SRC.join(' '), - 'font-src ' + FONT_SRC.join(' '), - 'frame-src ' + FRAME_SRC.join(' '), - 'connect-src ' + CONNECT_SRC.join(' '), - 'tusted-types ' + TRUSTED_TYPES.join(' '), - 'require-trusted-types-for \'script\'', -].join('; '); - -export const useCSP = ({ ...rest } = {}) => CSP({ - 'default-src': DEFAULT_SRC, - 'script-src': SCRIPT_SRC, - 'style-src': STYLE_SRC, - 'img-src': IMAGE_SRC, - 'media-src': MEDIA_SRC, - 'font-src': FONT_SRC, - 'frame-src': FRAME_SRC, - 'connect-src': CONNECT_SRC, - 'tusted-types': TRUSTED_TYPES, - 'require-trusted-types-for': '\'script\'', - ...rest -}); diff --git a/home.js b/home.js index fcff65b..c538a6b 100644 --- a/home.js +++ b/home.js @@ -1,6 +1,8 @@ import { readFile } from 'node:fs/promises'; -import { imports } from '@shgysk8zer0/importmap'; -import { importmap, integrity } from './csp.js'; +import { Importmap, imports, scopes } from '@shgysk8zer0/importmap'; +const importmap = new Importmap({ imports, scopes }); +await importmap.importLocalPackage(); +const integrity = await importmap.getIntegrity(); const NO_MAP = ['controller', 'socket', 'reject', 'signal', 'resolve']; diff --git a/http.config.js b/http.config.js index 3d0b5d7..c2abf5d 100644 --- a/http.config.js +++ b/http.config.js @@ -1,6 +1,12 @@ import home from '@aegisjsproject/dev-server'; import favicon from '@aegisjsproject/dev-server/favicon'; -import { useCSP } from './csp.js'; +import { Importmap, imports, scopes } from '@shgysk8zer0/importmap'; + +const importmap = new Importmap({ imports, scopes }); +await importmap.importLocalPackage(); +const integrity = await importmap.getIntegrity(); + +const csp = `default-src 'none'; script-src ${imports['@shgysk8zer0/polyfills']} '${integrity}'; style-src 'self'; img-src 'self'; require-trusted-types-for 'script';`; export default { open: true, @@ -8,5 +14,12 @@ export default { '/': home, '/favicon.svg': favicon, }, - responsePostprocessors: [useCSP()], + responsePostprocessors: [ + (response, { request }) => { + if (request.destination === 'document') { + response.headers.set('Content-Type', 'text/html'); + response.headers.set('Content-Security-Policy', csp); + } + } + ], }; diff --git a/package-lock.json b/package-lock.json index 047202c..29fd26a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@aegisjsproject/dev-server", - "version": "1.0.4", + "version": "1.0.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@aegisjsproject/dev-server", - "version": "1.0.4", + "version": "1.0.5", "funding": [ { "type": "librepay", @@ -20,10 +20,9 @@ "license": "MIT", "dependencies": { "@shgysk8zer0/http-server": "^1.1.1", - "@shgysk8zer0/importmap": "^1.4.88" + "@shgysk8zer0/importmap": "^1.5.1" }, "devDependencies": { - "@aegisjsproject/http-utils": "^1.0.0", "@shgysk8zer0/eslint-config": "^1.0.4", "eslint": "^9.39.1" }, @@ -31,25 +30,6 @@ "node": ">=24.10.0" } }, - "node_modules/@aegisjsproject/http-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@aegisjsproject/http-utils/-/http-utils-1.0.1.tgz", - "integrity": "sha512-qQTo3ZVJri5puWj4Rv+F/rBh59kVqKNjR6zJ5JKtyGb6BLZaRGi6u32LKwY/oQ7Hb7YpKcpdWxxB7jys36UPiA==", - "dev": true, - "funding": [ - { - "type": "librepay", - "url": "https://liberapay.com/shgysk8zer0" - }, - { - "type": "github", - "url": "https://github.com/sponsors/shgysk8zer0" - } - ], - "engines": { - "node": ">=24.10.0" - } - }, "node_modules/@aegisjsproject/sanitizer": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@aegisjsproject/sanitizer/-/sanitizer-0.2.1.tgz", @@ -743,9 +723,10 @@ } }, "node_modules/@shgysk8zer0/importmap": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@shgysk8zer0/importmap/-/importmap-1.5.0.tgz", - "integrity": "sha512-JPHuqc5Qzqfg/5And17hjy8lFWz7JfE2R2m58mxbMpDgdt0Y78dye4kzD+XFOWgyYM2u99ZruX/TXSXF5jQunA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@shgysk8zer0/importmap/-/importmap-1.5.1.tgz", + "integrity": "sha512-sxHyY2THBsN3i/TZOXYqkMuUErESvg9KlY+LirX0tuD+JG6Cfq+AU3EJ2vNcwnXc5DdpGEoQ41u+OkdXxq2i7Q==", + "license": "MIT", "dependencies": { "@shgysk8zer0/npm-utils": "^1.1.3", "@shgysk8zer0/polyfills": "^0.5.1", @@ -755,7 +736,7 @@ "importmap-utils": "cli.mjs" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.10.0" } }, "node_modules/@shgysk8zer0/importmap/node_modules/commander": { @@ -826,6 +807,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1006,6 +988,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -1612,6 +1595,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -1767,12 +1751,6 @@ } }, "dependencies": { - "@aegisjsproject/http-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@aegisjsproject/http-utils/-/http-utils-1.0.1.tgz", - "integrity": "sha512-qQTo3ZVJri5puWj4Rv+F/rBh59kVqKNjR6zJ5JKtyGb6BLZaRGi6u32LKwY/oQ7Hb7YpKcpdWxxB7jys36UPiA==", - "dev": true - }, "@aegisjsproject/sanitizer": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@aegisjsproject/sanitizer/-/sanitizer-0.2.1.tgz", @@ -2137,9 +2115,9 @@ } }, "@shgysk8zer0/importmap": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@shgysk8zer0/importmap/-/importmap-1.5.0.tgz", - "integrity": "sha512-JPHuqc5Qzqfg/5And17hjy8lFWz7JfE2R2m58mxbMpDgdt0Y78dye4kzD+XFOWgyYM2u99ZruX/TXSXF5jQunA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@shgysk8zer0/importmap/-/importmap-1.5.1.tgz", + "integrity": "sha512-sxHyY2THBsN3i/TZOXYqkMuUErESvg9KlY+LirX0tuD+JG6Cfq+AU3EJ2vNcwnXc5DdpGEoQ41u+OkdXxq2i7Q==", "requires": { "@shgysk8zer0/npm-utils": "^1.1.3", "@shgysk8zer0/polyfills": "^0.5.1", @@ -2193,7 +2171,8 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -2322,6 +2301,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -2756,6 +2736,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, + "peer": true, "requires": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", diff --git a/package.json b/package.json index bef0b5f..80f1fb9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@aegisjsproject/dev-server", - "version": "1.0.4", + "version": "1.0.5", "description": "Dev server setup for `@shgysk8zer0/http-server`", "keywords": [ "dev-server", @@ -66,12 +66,11 @@ }, "homepage": "https://github.com/AegisJSProject/dev-server#readme", "devDependencies": { - "@aegisjsproject/http-utils": "^1.0.0", "@shgysk8zer0/eslint-config": "^1.0.4", "eslint": "^9.39.1" }, "dependencies": { "@shgysk8zer0/http-server": "^1.1.1", - "@shgysk8zer0/importmap": "^1.4.88" + "@shgysk8zer0/importmap": "^1.5.1" } }