@networkpro/web 1.15.0 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.node-version +1 -1
- package/.nvmrc +1 -1
- package/CHANGELOG.md +37 -1
- package/netlify.toml +0 -5
- package/package.json +12 -12
- package/src/app.html +1 -1
- package/src/hooks.server.js +20 -1
- package/static/sitemap.xml +4 -4
- package/netlify/edge-functions/csp-report.js +0 -160
- package/tests/unit/server/csp-report.test.js +0 -81
package/.node-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
24.
|
|
1
|
+
24.4.0
|
package/.nvmrc
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
24.
|
|
1
|
+
24.4.0
|
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,41 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## [1.15.1] - 2025-07-12
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Added `Report-To` header in `src/hooks.server.js` to support modern CSP reporting
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Bumped project version to `1.15.1`
|
|
34
|
+
- Updated CSP report URL in `src/hooks.server.js` to use external endpoint
|
|
35
|
+
- Updated `sitemap.xml` to reflect latest site structure
|
|
36
|
+
- Updated `.node-version` and `.nvmrc` to `v24.4.0`
|
|
37
|
+
- Cleaned up `netlify.toml`:
|
|
38
|
+
- Removed `[[edge_functions]]` block
|
|
39
|
+
- Confirmed `ENV_MODE` remains for internal tooling
|
|
40
|
+
- Updated to latest versions:
|
|
41
|
+
- `@eslint/js` to `^9.31.0`
|
|
42
|
+
- `@playwright/test` to `^1.54.1`
|
|
43
|
+
- `@sveltejs/kit` to `2.22.5`
|
|
44
|
+
- `@sveltejs/vite-plugin-svelte` to `6.0.0`
|
|
45
|
+
- `eslint` to `^9.31.0`
|
|
46
|
+
- `eslint-plugin-jsdoc` to `^51.3.4`
|
|
47
|
+
- `playwright` to `^1.54.1`
|
|
48
|
+
- `posthog-js` to `^1.257.0`
|
|
49
|
+
- `stylelint` to `^16.21.1`
|
|
50
|
+
- `svelte` to `5.35.6`
|
|
51
|
+
- `vite` to `7.0.4`
|
|
52
|
+
|
|
53
|
+
### Removed
|
|
54
|
+
|
|
55
|
+
- Deleted `/netlify/edge-functions/` and `csp-report.js` (CSP report handling is now in its own project)
|
|
56
|
+
- Removed `tests/unit/server/csp-report.test.js` from project, as CSP endpoint has been relocated
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
25
60
|
## [1.15.0] - 2025-07-01
|
|
26
61
|
|
|
27
62
|
### Added
|
|
@@ -615,7 +650,8 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
615
650
|
|
|
616
651
|
<!-- Link references -->
|
|
617
652
|
|
|
618
|
-
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.15.
|
|
653
|
+
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.15.1...HEAD
|
|
654
|
+
[1.15.1]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.15.1
|
|
619
655
|
[1.15.0]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.15.0
|
|
620
656
|
[1.14.2]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.14.2
|
|
621
657
|
[1.14.1]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.14.1
|
package/netlify.toml
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
command = "npm run build"
|
|
3
3
|
|
|
4
4
|
[build.environment]
|
|
5
|
-
NODE_VERSION = "22"
|
|
6
5
|
ENV_MODE = "prod"
|
|
7
6
|
|
|
8
7
|
[dev]
|
|
@@ -10,10 +9,6 @@
|
|
|
10
9
|
targetPort = 5173
|
|
11
10
|
port = 8888
|
|
12
11
|
|
|
13
|
-
[[edge_functions]]
|
|
14
|
-
path = "/api/csp-report"
|
|
15
|
-
function = "csp-report"
|
|
16
|
-
|
|
17
12
|
[[plugins]]
|
|
18
13
|
package = "netlify-plugin-submit-sitemap"
|
|
19
14
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@networkpro/web",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.15.
|
|
4
|
+
"version": "1.15.1",
|
|
5
5
|
"description": "Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro Strategies",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"advisory",
|
|
@@ -79,26 +79,26 @@
|
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
81
|
"dompurify": "^3.2.6",
|
|
82
|
-
"posthog-js": "^1.
|
|
82
|
+
"posthog-js": "^1.257.0",
|
|
83
83
|
"semver": "^7.7.2",
|
|
84
|
-
"svelte": "5.
|
|
84
|
+
"svelte": "5.35.6"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@eslint/compat": "^1.3.1",
|
|
88
|
-
"@eslint/js": "^9.
|
|
88
|
+
"@eslint/js": "^9.31.0",
|
|
89
89
|
"@lhci/cli": "^0.15.1",
|
|
90
|
-
"@playwright/test": "^1.
|
|
90
|
+
"@playwright/test": "^1.54.1",
|
|
91
91
|
"@sveltejs/adapter-netlify": "^5.0.2",
|
|
92
|
-
"@sveltejs/kit": "2.22.
|
|
93
|
-
"@sveltejs/vite-plugin-svelte": "
|
|
92
|
+
"@sveltejs/kit": "2.22.5",
|
|
93
|
+
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
|
94
94
|
"@testing-library/jest-dom": "^6.6.3",
|
|
95
95
|
"@testing-library/svelte": "^5.2.8",
|
|
96
96
|
"@vitest/coverage-v8": "^3.2.4",
|
|
97
97
|
"autoprefixer": "^10.4.21",
|
|
98
98
|
"browserslist": "^4.25.1",
|
|
99
|
-
"eslint": "^9.
|
|
99
|
+
"eslint": "^9.31.0",
|
|
100
100
|
"eslint-config-prettier": "^10.1.5",
|
|
101
|
-
"eslint-plugin-jsdoc": "^51.3.
|
|
101
|
+
"eslint-plugin-jsdoc": "^51.3.4",
|
|
102
102
|
"eslint-plugin-svelte": "^3.10.1",
|
|
103
103
|
"globals": "^16.3.0",
|
|
104
104
|
"jsdom": "^26.1.0",
|
|
@@ -106,11 +106,11 @@
|
|
|
106
106
|
"markdownlint": "^0.38.0",
|
|
107
107
|
"markdownlint-cli2": "^0.18.1",
|
|
108
108
|
"mdsvex": "^0.12.6",
|
|
109
|
-
"playwright": "^1.
|
|
109
|
+
"playwright": "^1.54.1",
|
|
110
110
|
"postcss": "^8.5.6",
|
|
111
111
|
"prettier": "^3.6.2",
|
|
112
112
|
"prettier-plugin-svelte": "^3.4.0",
|
|
113
|
-
"stylelint": "^16.21.
|
|
113
|
+
"stylelint": "^16.21.1",
|
|
114
114
|
"stylelint-config-html": "^1.1.0",
|
|
115
115
|
"stylelint-config-recommended": "^16.0.0",
|
|
116
116
|
"stylelint-order": "^7.0.0",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"svelte-eslint-parser": "^1.2.0",
|
|
119
119
|
"svelte-preprocess": "^6.0.3",
|
|
120
120
|
"typescript": "^5.8.3",
|
|
121
|
-
"vite": "
|
|
121
|
+
"vite": "^7.0.4",
|
|
122
122
|
"vite-plugin-lightningcss": "^0.0.5",
|
|
123
123
|
"vite-tsconfig-paths": "^5.1.4",
|
|
124
124
|
"vitest": "^3.2.4"
|
package/src/app.html
CHANGED
package/src/hooks.server.js
CHANGED
|
@@ -25,7 +25,10 @@ export async function handle({ event, resolve }) {
|
|
|
25
25
|
console.log('[CSP Debug] ENV_MODE:', process.env.ENV_MODE);
|
|
26
26
|
|
|
27
27
|
// Determine report URI
|
|
28
|
-
const reportUri =
|
|
28
|
+
const reportUri =
|
|
29
|
+
isProdEnvironment && !isTestEnvironment
|
|
30
|
+
? 'https://csp.netwk.pro/.netlify/functions/csp-report'
|
|
31
|
+
: '/api/mock-csp';
|
|
29
32
|
|
|
30
33
|
// Construct base policy
|
|
31
34
|
const cspDirectives = [
|
|
@@ -40,7 +43,9 @@ export async function handle({ event, resolve }) {
|
|
|
40
43
|
"object-src 'none';",
|
|
41
44
|
"frame-ancestors 'none';",
|
|
42
45
|
'upgrade-insecure-requests;',
|
|
46
|
+
// Report CSP violations to external endpoint hosted at csp.netwk.pro
|
|
43
47
|
`report-uri ${reportUri};`,
|
|
48
|
+
'report-to csp-endpoint;',
|
|
44
49
|
];
|
|
45
50
|
|
|
46
51
|
// Loosen up CSP for test environments
|
|
@@ -54,6 +59,20 @@ export async function handle({ event, resolve }) {
|
|
|
54
59
|
cspDirectives[5] = "connect-src 'self';";
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
response.headers.set(
|
|
63
|
+
'Report-To',
|
|
64
|
+
JSON.stringify({
|
|
65
|
+
group: 'csp-endpoint',
|
|
66
|
+
max_age: 10886400, // 18 weeks
|
|
67
|
+
endpoints: [
|
|
68
|
+
{
|
|
69
|
+
url: 'https://csp.netwk.pro/.netlify/functions/csp-report',
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
include_subdomains: true,
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
|
|
57
76
|
response.headers.set('Content-Security-Policy', cspDirectives.join(' '));
|
|
58
77
|
|
|
59
78
|
// Set other security headers
|
package/static/sitemap.xml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!-- Sitemap last updated on 2025
|
|
2
|
+
<!-- Sitemap last updated on July 12, 2025 -->
|
|
3
3
|
|
|
4
4
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<loc>https://netwk.pro</loc>
|
|
9
9
|
|
|
10
|
-
<lastmod>2025-
|
|
10
|
+
<lastmod>2025-07-12</lastmod>
|
|
11
11
|
|
|
12
12
|
<changefreq>weekly</changefreq>
|
|
13
13
|
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
<loc>https://netwk.pro/privacy-dashboard</loc>
|
|
45
45
|
|
|
46
|
-
<lastmod>2025-
|
|
46
|
+
<lastmod>2025-06-30</lastmod>
|
|
47
47
|
|
|
48
48
|
<changefreq>monthly</changefreq>
|
|
49
49
|
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
|
|
56
56
|
<loc>https://netwk.pro/privacy</loc>
|
|
57
57
|
|
|
58
|
-
<lastmod>2025-06-
|
|
58
|
+
<lastmod>2025-06-30</lastmod>
|
|
59
59
|
|
|
60
60
|
<changefreq>monthly</changefreq>
|
|
61
61
|
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
/* ==========================================================================
|
|
2
|
-
edge-functions/csp-report.js
|
|
3
|
-
|
|
4
|
-
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
|
-
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
6
|
-
This file is part of Network Pro.
|
|
7
|
-
========================================================================== */
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @file csp-report.js
|
|
11
|
-
* @description Netlify Edge Function to handle CSP violation reports.
|
|
12
|
-
*
|
|
13
|
-
* Accepts POST requests to /api/csp-report and logs relevant CSP reports.
|
|
14
|
-
* Filters out common low-value reports (e.g., img-src) to reduce invocation
|
|
15
|
-
* cost. Alerts on high-risk violations via ntfy topic.
|
|
16
|
-
*
|
|
17
|
-
* @module netlify/edge-functions
|
|
18
|
-
* @author SunDevil311
|
|
19
|
-
* @updated 2025-05-31
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Netlify Edge Function entry point for CSP reporting.
|
|
24
|
-
*
|
|
25
|
-
* @param {Request} request - The incoming HTTP request object
|
|
26
|
-
* @param {import('@netlify/edge-functions').Context} _context - The Netlify Edge Function context (unused)
|
|
27
|
-
* @returns {Promise<Response>} HTTP Response with status 204 or 405
|
|
28
|
-
*/
|
|
29
|
-
export default async (request, _context) => {
|
|
30
|
-
if (request.method !== 'POST') {
|
|
31
|
-
return new Response('Method Not Allowed', { status: 405 });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const body = await request.json();
|
|
36
|
-
const report = body['csp-report'];
|
|
37
|
-
|
|
38
|
-
// Ignore if report is missing or malformed
|
|
39
|
-
if (!report || typeof report !== 'object') {
|
|
40
|
-
return new Response(null, { status: 204 });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const violated = report['violated-directive'] ?? '';
|
|
44
|
-
const blockedUri = report['blocked-uri'] ?? '';
|
|
45
|
-
|
|
46
|
-
// Filter: Skip noisy or unactionable reports
|
|
47
|
-
const ignored = [
|
|
48
|
-
violated.startsWith('img-src'),
|
|
49
|
-
blockedUri === '',
|
|
50
|
-
blockedUri === 'eval',
|
|
51
|
-
blockedUri === 'about',
|
|
52
|
-
blockedUri.startsWith('chrome-extension://'),
|
|
53
|
-
blockedUri.startsWith('moz-extension://'),
|
|
54
|
-
!report['source-file'],
|
|
55
|
-
!report['document-uri'],
|
|
56
|
-
].some(Boolean);
|
|
57
|
-
|
|
58
|
-
if (ignored) {
|
|
59
|
-
console.log('[CSP-Edge] Ignored low-value violation:', {
|
|
60
|
-
directive: violated,
|
|
61
|
-
uri: blockedUri,
|
|
62
|
-
});
|
|
63
|
-
return new Response(null, { status: 204 });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Send alert for high-risk directives
|
|
67
|
-
await sendToNtfy(violated, blockedUri, report);
|
|
68
|
-
|
|
69
|
-
// Log useful violations
|
|
70
|
-
console.log('[CSP-Edge] Violation:', {
|
|
71
|
-
directive: violated,
|
|
72
|
-
uri: blockedUri,
|
|
73
|
-
referrer: report['referrer'],
|
|
74
|
-
source: report['source-file'],
|
|
75
|
-
line: report['line-number'],
|
|
76
|
-
});
|
|
77
|
-
} catch (err) {
|
|
78
|
-
console.warn('[CSP-Edge] Failed to parse CSP report:', err.message);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return new Response(null, { status: 204 });
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const recentViolations = new Map();
|
|
85
|
-
const VIOLATION_TTL_MS = 60_000;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Sends a high-priority alert to your ntfy topic for high-risk CSP violations.
|
|
89
|
-
* Applies rate-limiting to avoid sending duplicate alerts within 60 seconds.
|
|
90
|
-
*
|
|
91
|
-
* @param {string} violated - The violated CSP directive
|
|
92
|
-
* @param {string} blockedUri - The URI that was blocked
|
|
93
|
-
* @param {Record<string, any>} report - The full CSP report object
|
|
94
|
-
*/
|
|
95
|
-
async function sendToNtfy(violated, blockedUri, report) {
|
|
96
|
-
const highRiskDirectives = [
|
|
97
|
-
'script-src',
|
|
98
|
-
'form-action',
|
|
99
|
-
'frame-ancestors',
|
|
100
|
-
'base-uri',
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
const directiveKey = violated.split(' ')[0]; // strip fallback values or sources
|
|
104
|
-
const isHighRisk = highRiskDirectives.includes(directiveKey);
|
|
105
|
-
console.log(
|
|
106
|
-
`[CSP-Edge] Directive ${directiveKey} is ${isHighRisk ? '' : 'not '}high-risk`,
|
|
107
|
-
);
|
|
108
|
-
if (!isHighRisk) return;
|
|
109
|
-
|
|
110
|
-
const key = `${violated}|${blockedUri}`;
|
|
111
|
-
const now = Date.now();
|
|
112
|
-
|
|
113
|
-
// Skip and log if violation was reported recently
|
|
114
|
-
if (
|
|
115
|
-
recentViolations.has(key) &&
|
|
116
|
-
now - recentViolations.get(key) < VIOLATION_TTL_MS
|
|
117
|
-
) {
|
|
118
|
-
console.log(`[CSP-Edge] Skipped duplicate alert for ${key}`);
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Record the current timestamp
|
|
123
|
-
recentViolations.set(key, now);
|
|
124
|
-
|
|
125
|
-
// Cleanup old entries (memory-safe for low volume)
|
|
126
|
-
for (const [k, t] of recentViolations.entries()) {
|
|
127
|
-
if (now - t > VIOLATION_TTL_MS) {
|
|
128
|
-
recentViolations.delete(k);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const topicUrl = 'https://ntfy.neteng.pro/csp-alerts';
|
|
133
|
-
|
|
134
|
-
const message = [
|
|
135
|
-
`🚨 CSP Violation Detected`,
|
|
136
|
-
`Directive: ${violated}`,
|
|
137
|
-
`Blocked URI: ${blockedUri}`,
|
|
138
|
-
`Referrer: ${report.referrer || 'N/A'}`,
|
|
139
|
-
`Source: ${report['source-file'] || 'N/A'}`,
|
|
140
|
-
`Line: ${report['line-number'] || 'N/A'}`,
|
|
141
|
-
].join('\n');
|
|
142
|
-
|
|
143
|
-
await fetch(topicUrl, {
|
|
144
|
-
method: 'POST',
|
|
145
|
-
headers: {
|
|
146
|
-
'Content-Type': 'text/plain',
|
|
147
|
-
'X-Title': 'High-Risk CSP Violation',
|
|
148
|
-
'X-Priority': '5',
|
|
149
|
-
},
|
|
150
|
-
body: message,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Configuration block for the Edge Function.
|
|
156
|
-
* This sets the endpoint route to /api/csp-report
|
|
157
|
-
*/
|
|
158
|
-
export const config = {
|
|
159
|
-
path: '/api/csp-report',
|
|
160
|
-
};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/* ==========================================================================
|
|
2
|
-
tests/unit/server/csp-report.test.js
|
|
3
|
-
|
|
4
|
-
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
|
-
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
6
|
-
This file is part of Network Pro.
|
|
7
|
-
========================================================================== */
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Tests the edge-functions/csp-report.js CSP reporting endpoint
|
|
11
|
-
*
|
|
12
|
-
* @module tests/unit
|
|
13
|
-
* @author SunDevil311
|
|
14
|
-
* @updated 2025-05-31
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/** @file Unit tests for edge-functions/csp-report.js using Vitest */
|
|
18
|
-
/** @typedef {import('vitest').TestContext} TestContext */
|
|
19
|
-
|
|
20
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
21
|
-
import handler from '../../../netlify/edge-functions/csp-report.js';
|
|
22
|
-
|
|
23
|
-
// 🧪 Mock fetch used by sendToNtfy inside the Edge Function
|
|
24
|
-
global.fetch = vi.fn(() =>
|
|
25
|
-
Promise.resolve({ ok: true, status: 200, text: () => 'OK' }),
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
describe('csp-report.js', () => {
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
vi.clearAllMocks();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should handle a valid CSP report', async () => {
|
|
34
|
-
const req = new Request('http://localhost/api/csp-report', {
|
|
35
|
-
method: 'POST',
|
|
36
|
-
headers: { 'Content-Type': 'application/json' },
|
|
37
|
-
body: JSON.stringify({
|
|
38
|
-
'csp-report': {
|
|
39
|
-
'document-uri': 'https://example.com',
|
|
40
|
-
'violated-directive': 'script-src',
|
|
41
|
-
'blocked-uri': 'https://malicious.site',
|
|
42
|
-
},
|
|
43
|
-
}),
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const res = await handler(req, {});
|
|
47
|
-
expect(res.status).toBe(204);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should reject non-POST requests', async () => {
|
|
51
|
-
const req = new Request('http://localhost/api/csp-report', {
|
|
52
|
-
method: 'GET',
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const res = await handler(req, {});
|
|
56
|
-
const text = await res.text();
|
|
57
|
-
expect(res.status).toBe(405);
|
|
58
|
-
expect(text).toContain('Method Not Allowed');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should handle malformed JSON', async () => {
|
|
62
|
-
const badJson = '{ invalid json }';
|
|
63
|
-
const req = new Request('http://localhost/api/csp-report', {
|
|
64
|
-
method: 'POST',
|
|
65
|
-
headers: { 'Content-Type': 'application/json' },
|
|
66
|
-
body: badJson,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const res = await handler(req, {});
|
|
70
|
-
expect(res.status).toBe(204); // The current handler swallows errors silently
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should handle missing body', async () => {
|
|
74
|
-
const req = new Request('http://localhost/api/csp-report', {
|
|
75
|
-
method: 'POST',
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const res = await handler(req, {});
|
|
79
|
-
expect(res.status).toBe(204); // No body is also treated silently
|
|
80
|
-
});
|
|
81
|
-
});
|