Skip to content

Commit eafc16d

Browse files
authored
Merge pull request #3 from AegisJSProject/feature/csp-config
Add customizable CSP module and update usage
2 parents c1e5174 + 8a54ac6 commit eafc16d

File tree

5 files changed

+64
-25
lines changed

5 files changed

+64
-25
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [v1.0.1] - 22025-11-21
11+
12+
### Added
13+
- Add methods and module to customize CSP
14+
1015
## [v1.0.0] - 2025-11-21
1116

1217
Initial Release

csp.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { readFile } from 'node:fs/promises';
2+
import { imports } from '@shgysk8zer0/importmap';
3+
4+
const pkg = JSON.parse(await readFile(process.cwd() + '/package.json', { encoding: 'utf8' }));
5+
6+
export const importmap = JSON.stringify({
7+
imports: {
8+
...imports,
9+
[pkg.name]: pkg.exports['.'].import,
10+
[`${pkg.name}/`]: './',
11+
}
12+
});
13+
14+
const sri = async (input) => await Promise.resolve(input)
15+
.then(json => new TextEncoder().encode(json))
16+
.then(bytes => crypto.subtle.digest('SHA-384', bytes))
17+
.then(hash => 'sha384-' + new Uint8Array(hash).toBase64());
18+
19+
export const integrity = await sri(importmap);
20+
21+
const DEFAULT_SRC = ['\'self\''];
22+
const SCRIPT_SRC = ['\'self\'', 'https://unpkg.com/@shgysk8zer0/', 'https://unpkg.com/@kernvalley/', 'https://unpkg.com/@aegisjsproject/', `'${integrity}'`];
23+
const STYLE_SRC = ['\'self\'', 'https://unpkg.com/@agisjsproject/', 'blob:'];
24+
const IMAGE_SRC = ['\'self\'', 'https://i.imgur.com/', 'https://secure.gravatar.com/avatar/', 'blob:', 'data:'];
25+
const MEDIA_SRC = ['\'self\'', 'blob:'];
26+
const CONNECT_SRC = ['\'self\''];
27+
const FONT_SRC = ['\'self\''];
28+
const FRAME_SRC = ['\'self\'', 'https://www.youtube-nocookie.com'];
29+
const TRUSTED_TYPES = ['aegis-sanitizer#html'];
30+
31+
export const addDefaultSrc = (...srcs) => DEFAULT_SRC.push(...srcs);
32+
export const addScriptSrc = (...srcs) => SCRIPT_SRC.push(...srcs);
33+
export const addStyleSrc = (...srcs) => STYLE_SRC.push(...srcs);
34+
export const addImageSrc = (...srcs) => IMAGE_SRC.push(...srcs);
35+
export const addMediaSrc = (...srcs) => MEDIA_SRC.push(...srcs);
36+
export const addConnectSrc = (...srcs) => CONNECT_SRC.push(...srcs);
37+
export const addFontSrc = (...srcs) => FONT_SRC.push(...srcs);
38+
export const addFrameSrc = (...srcs) => FRAME_SRC.push(...srcs);
39+
export const addTrustedType = (...policies) => TRUSTED_TYPES.push(...policies);
40+
41+
export const getCSP = () => [
42+
'default-src ' + DEFAULT_SRC.join(' '),
43+
'script-src ' + SCRIPT_SRC.join(' '),
44+
'style-src ' + STYLE_SRC.join(' '),
45+
'image-src ' + IMAGE_SRC.join(' '),
46+
'media-src ' + MEDIA_SRC.join(' '),
47+
'font-src ' + FONT_SRC.join(' '),
48+
'frame-src ' + FRAME_SRC.join(' '),
49+
'connect-src ' + CONNECT_SRC.join(' '),
50+
'tusted-types ' + TRUSTED_TYPES.join(' '),
51+
'require-trusted-types-for \'script\'',
52+
].join('; ');

home.js

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,6 @@
11
import { readFile } from 'node:fs/promises';
22
import { imports } from '@shgysk8zer0/importmap';
3-
4-
const pkg = JSON.parse(await readFile(process.cwd() + '/package.json', { encoding: 'utf8' }));
5-
6-
const importmap = JSON.stringify({
7-
imports: {
8-
...imports,
9-
[pkg.name]: pkg.exports['.'].import,
10-
[`${pkg.name}/`]: './',
11-
}
12-
});
13-
14-
const sri = async (input) => await Promise.resolve(input)
15-
.then(json => new TextEncoder().encode(json))
16-
.then(bytes => crypto.subtle.digest('SHA-384', bytes))
17-
.then(hash => 'sha384-' + new Uint8Array(hash).toBase64());
18-
19-
const integrity = await sri(importmap);
20-
21-
const CSP = `default-src 'self'; style-src 'self' https://unpkg.com/@agisjsproject/ blob:; script-src 'self' https://unpkg.com/@shgysk8zer0/ https://unpkg.com/@kernvalley/ https://unpkg.com/@aegisjsproject/ '${integrity}'; image-src 'self' https://i.imgur.com/ https://secure.gravatar.com/avatar/ blob: data:; media-src 'self' blob:; frame-src https://www.youtube-nocookie.com; trusted-types aegis-sanitizer#html aegis-router#html; require-trusted-types-for 'script';`;
3+
import { getCSP, importmap, integrity } from './csp.js';
224

235
export default async (req) => {
246
const doc = await readFile(process.cwd() + '/index.html', { encoding: 'utf8' });
@@ -42,7 +24,7 @@ export default async (req) => {
4224
{
4325
headers: {
4426
'Content-Type': 'text/html',
45-
'Content-Security-Policy': CSP,
27+
'Content-Security-Policy': getCSP(),
4628
}
4729
}
4830
);

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@aegisjsproject/dev-server",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "Dev server setup for `@shgysk8zer0/http-server`",
55
"keywords": [
66
"dev-server",

0 commit comments

Comments
 (0)