@networkpro/web 1.12.8 → 1.13.0
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/CHANGELOG.md +64 -1
- package/README.md +8 -8
- package/cspell.json +1 -0
- package/eslint.config.mjs +48 -48
- package/jsconfig.template.jsonc +3 -1
- package/netlify/edge-functions/csp-report.js +31 -31
- package/package.json +6 -6
- package/playwright.config.js +14 -14
- package/postcss.config.mjs +1 -1
- package/scripts/auditScripts.js +16 -16
- package/scripts/bundleCss.js +5 -5
- package/scripts/checkEnv.js +6 -6
- package/scripts/checkNode.js +10 -10
- package/scripts/checkVersions.js +6 -6
- package/scripts/flattenHeaders.js +13 -13
- package/scripts/generateTest.js +5 -5
- package/scripts/openReport.js +3 -3
- package/scripts/validateHeaders.js +13 -13
- package/src/hooks.client.ts +1 -1
- package/src/hooks.server.js +31 -31
- package/src/lib/components/Badges.svelte +9 -9
- package/src/lib/components/CodeBlock.svelte +13 -0
- package/src/lib/components/ContainerSection.svelte +1 -1
- package/src/lib/components/FullWidthSection.svelte +3 -3
- package/src/lib/components/LegalNav.svelte +6 -6
- package/src/lib/components/Logo.svelte +9 -9
- package/src/lib/components/MetaTags.svelte +3 -3
- package/src/lib/components/PWAInstallButton.svelte +4 -4
- package/src/lib/components/RedirectPage.svelte +4 -4
- package/src/lib/components/SocialMedia.svelte +16 -16
- package/src/lib/components/foss/FossItemContent.svelte +18 -18
- package/src/lib/components/layout/Footer.svelte +17 -17
- package/src/lib/components/layout/HeaderDefault.svelte +16 -16
- package/src/lib/components/layout/HeaderHome.svelte +14 -14
- package/src/lib/images.js +34 -34
- package/src/lib/index.js +15 -15
- package/src/lib/meta.js +29 -29
- package/src/lib/pages/AboutContent.svelte +24 -24
- package/src/lib/pages/FossContent.svelte +12 -12
- package/src/lib/pages/HomeContent.svelte +6 -6
- package/src/lib/pages/LicenseContent.svelte +38 -38
- package/src/lib/pages/PGPContent.svelte +61 -29
- package/src/lib/pages/PrivacyContent.svelte +39 -39
- package/src/lib/pages/PrivacyDashboard.svelte +12 -12
- package/src/lib/pages/TermsConditionsContent.svelte +28 -28
- package/src/lib/pages/TermsUseContent.svelte +26 -26
- package/src/lib/registerServiceWorker.js +25 -25
- package/src/lib/stores/posthog.js +13 -13
- package/src/lib/stores/trackingPreferences.js +19 -19
- package/src/lib/styles/css/default.css +5 -1
- package/src/lib/styles/global.min.css +1 -1
- package/src/lib/unregisterServiceWorker.js +1 -1
- package/src/lib/utils/purify.js +4 -4
- package/src/lib/utils/utm.js +2 -2
- package/src/routes/+error.svelte +4 -4
- package/src/routes/+layout.js +6 -6
- package/src/routes/+layout.svelte +29 -29
- package/src/routes/+page.server.js +2 -2
- package/src/routes/+page.svelte +9 -9
- package/src/routes/about/+page.server.js +2 -2
- package/src/routes/about/+page.svelte +7 -7
- package/src/routes/api/mock-csp/+server.js +3 -3
- package/src/routes/consultation/+page.svelte +5 -5
- package/src/routes/contact/+page.svelte +5 -5
- package/src/routes/foss-spotlight/+page.server.js +2 -2
- package/src/routes/foss-spotlight/+page.svelte +7 -7
- package/src/routes/license/+page.server.js +2 -2
- package/src/routes/license/+page.svelte +7 -7
- package/src/routes/pgp/+page.server.js +2 -2
- package/src/routes/pgp/+page.svelte +7 -7
- package/src/routes/pgp/[key]/+server.js +9 -9
- package/src/routes/privacy/+page.server.js +2 -2
- package/src/routes/privacy/+page.svelte +7 -7
- package/src/routes/privacy-dashboard/+page.server.js +2 -2
- package/src/routes/privacy-dashboard/+page.svelte +8 -8
- package/src/routes/privacy-rights/+page.svelte +5 -5
- package/src/routes/status/+page.server.js +2 -2
- package/src/routes/terms-conditions/+page.server.js +2 -2
- package/src/routes/terms-conditions/+page.svelte +7 -7
- package/src/routes/terms-of-use/+page.server.js +2 -2
- package/src/routes/terms-of-use/+page.svelte +7 -7
- package/src/service-worker.js +86 -85
- package/static/disableSw.js +2 -2
- package/static/img/powered-by-proton.svg +1 -0
- package/static/offline.html +7 -7
- package/static/sitemap.xml +64 -4
- package/stylelint.config.js +56 -56
- package/svelte.config.js +6 -6
- package/tests/e2e/app.spec.js +25 -25
- package/tests/e2e/mobile.spec.js +18 -18
- package/tests/e2e/shared/helpers.js +4 -4
- package/tests/internal/auditCoverage.test.js +24 -24
- package/tests/unit/checkEnv.test.js +10 -10
- package/tests/unit/checkVersions.test.js +4 -4
- package/tests/unit/csp-report.test.js +24 -24
- package/tests/unit/demo.test.js +3 -3
- package/tests/unit/lib/utils/purify.test.js +12 -12
- package/tests/unit/routes/page.svelte.test.js +10 -10
- package/tests/unit/unregisterServiceWorker.test.js +5 -5
- package/tests/unit/utm.test.js +13 -13
- package/vite.config.js +5 -5
- package/vitest-setup-client.js +4 -4
- package/vitest.config.client.js +15 -15
- package/vitest.config.server.js +13 -13
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,67 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## [1.13.0] - 2025-06-11
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Introduced `/pgp` route to publish OpenPGP contact information, download links, and QR codes
|
|
30
|
+
- Added `.well-known/humans.txt` to document project authorship
|
|
31
|
+
- Added `.well-known/security.txt` to define the official security contact and vulnerability disclosure policy
|
|
32
|
+
- Linked OpenPGP keys to external directories for validation (e.g. keys.openpgp.org)
|
|
33
|
+
- Added new GitHub Actions workflow: `check-security-txt-expiry.yml` to monitor `security.txt` expiration
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Enforced `"singleQuote": true` in `.prettierrc` and formatted the codebase using Prettier
|
|
38
|
+
- Updated `src/service-worker.js` to exclude `security.txt.asc` from caching
|
|
39
|
+
- CSP policy updated to allow `clipboard-write` for improved UX on PGP fingerprint buttons
|
|
40
|
+
- Clarified that addresses under the `s.neteng.pro` domain are powered by Proton Mail and support native E2EE
|
|
41
|
+
- Revised `SECURITY.md` and `security.txt` with accurate Proton Mail usage notes and PGP policy references
|
|
42
|
+
|
|
43
|
+
### Removed
|
|
44
|
+
|
|
45
|
+
- Legacy reference to a "coming soon" PGP section in `SECURITY.md` (now live and linked)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## [1.12.9] - 2025-06-11
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- Added `check-security-txt-expiry.yml` workflow to check `.well-known/security.txt` expiration and warn if close to expiring
|
|
54
|
+
- Added `humans.txt` and `security.txt` to `.well-known/` directory
|
|
55
|
+
- Added `src/lib/components/CodeBlock.svelte` component for improved inline formatting control
|
|
56
|
+
- Updated sitemap.xml to include `.well-known/` routes and the `/pgp` route
|
|
57
|
+
- Added link to OpenPGP results for `security@s.neteng.pro` on the `/pgp` route
|
|
58
|
+
- Added support for copy-to-clipboard feedback on PGP fingerprint buttons
|
|
59
|
+
- Added detached signature (`security.txt.asc`) for `.well-known/security.txt`, signed with the `security@s.neteng.pro` PGP key
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- Version bump to `v1.12.9` in `package.json`
|
|
64
|
+
- Corrected the name of `dnt-policy.txt` from `dnt-policy-1.0.txt`
|
|
65
|
+
- Updated `src/service-worker.js` to:
|
|
66
|
+
- Reflect correct `.well-known/dnt-policy.txt` reference
|
|
67
|
+
- Exclude `.well-known/security.txt.asc` from caching
|
|
68
|
+
- Applied line breaks to comment header in `jsconfig.template.jsonc` to fix formatting
|
|
69
|
+
- Minor revision to spreadsheet display and fingerprint formatting for improved mobile responsiveness
|
|
70
|
+
- Revised `.github/SECURITY.md`:
|
|
71
|
+
- Removed note about “PGP section coming soon to the wiki” (now live)
|
|
72
|
+
- Clarified Proton Mail use for `s.neteng.pro` addresses, while preserving support guidance for others
|
|
73
|
+
- Streamlined vulnerability reporting section for clarity and correctness
|
|
74
|
+
- Updated Content Security Policy (CSP) header to allow `clipboard-write` permission
|
|
75
|
+
- Added Proton Mail usage note to `/pgp` route UI for `s.neteng.pro` domain only
|
|
76
|
+
- Added equivalent Proton Mail usage comment to `.well-known/security.txt`
|
|
77
|
+
- Upgraded dependencies:
|
|
78
|
+
- `@eslint/compat` `^1.2.9` → `^1.3.0`
|
|
79
|
+
- `eslint-plugin-jsdoc` `^50.7.1` → `^50.8.0`
|
|
80
|
+
- `postcss` `^8.5.4` → `^8.5.5`
|
|
81
|
+
- `posthog-js` `^1.250.1` → `^1.250.2`
|
|
82
|
+
- `svelte` `5.33.19` → `5.34.1`
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
25
86
|
## [1.12.8] - 2025-06-11
|
|
26
87
|
|
|
27
88
|
### Added
|
|
@@ -249,7 +310,9 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
249
310
|
|
|
250
311
|
<!-- Link references -->
|
|
251
312
|
|
|
252
|
-
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.
|
|
313
|
+
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.13.0...HEAD
|
|
314
|
+
[1.13.0]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.0
|
|
315
|
+
[1.12.9]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.9
|
|
253
316
|
[1.12.8]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.8
|
|
254
317
|
[1.12.7]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.7
|
|
255
318
|
[1.12.6]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.6
|
package/README.md
CHANGED
|
@@ -221,12 +221,12 @@ This script runs `scripts/checkNode.js`, which compares your current Node.js and
|
|
|
221
221
|
**_Node Version Check (snippet from `scripts/checkNode.js`)_**
|
|
222
222
|
|
|
223
223
|
```javascript
|
|
224
|
-
const semver = require(
|
|
225
|
-
const { engines } = require(
|
|
224
|
+
const semver = require('semver');
|
|
225
|
+
const { engines } = require('../package.json');
|
|
226
226
|
|
|
227
227
|
const requiredNode = engines.node;
|
|
228
228
|
const requiredNpm = engines.npm;
|
|
229
|
-
const isPostInstall = process.env.npm_lifecycle_event ===
|
|
229
|
+
const isPostInstall = process.env.npm_lifecycle_event === 'postinstall';
|
|
230
230
|
|
|
231
231
|
let hasError = false;
|
|
232
232
|
|
|
@@ -236,8 +236,8 @@ if (!semver.satisfies(process.version, requiredNode)) {
|
|
|
236
236
|
if (!isPostInstall) hasError = true;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
const npmVersion = require(
|
|
240
|
-
.execSync(
|
|
239
|
+
const npmVersion = require('child_process')
|
|
240
|
+
.execSync('npm -v')
|
|
241
241
|
.toString()
|
|
242
242
|
.trim();
|
|
243
243
|
|
|
@@ -248,7 +248,7 @@ if (!semver.satisfies(npmVersion, requiredNpm)) {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
if (!hasError) {
|
|
251
|
-
console.log(
|
|
251
|
+
console.log('✅ Node and npm versions are valid.');
|
|
252
252
|
} else {
|
|
253
253
|
process.exit(1);
|
|
254
254
|
}
|
|
@@ -343,7 +343,7 @@ It unregisters **all active service worker registrations** and logs the result.
|
|
|
343
343
|
Located at `static/disableSw.js`, this file sets a global flag if the URL contains the `?nosw` query parameter:
|
|
344
344
|
|
|
345
345
|
```js
|
|
346
|
-
if (location.search.includes(
|
|
346
|
+
if (location.search.includes('nosw')) {
|
|
347
347
|
window.__DISABLE_SW__ = true;
|
|
348
348
|
}
|
|
349
349
|
```
|
|
@@ -365,7 +365,7 @@ https://netwk.pro/?nosw
|
|
|
365
365
|
To register the service worker conditionally, call the function from client code:
|
|
366
366
|
|
|
367
367
|
```js
|
|
368
|
-
import { registerServiceWorker } from
|
|
368
|
+
import { registerServiceWorker } from '$lib/registerServiceWorker.js';
|
|
369
369
|
|
|
370
370
|
registerServiceWorker();
|
|
371
371
|
```
|
package/cspell.json
CHANGED
package/eslint.config.mjs
CHANGED
|
@@ -6,57 +6,57 @@ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
|
6
6
|
This file is part of Network Pro.
|
|
7
7
|
========================================================================= */
|
|
8
8
|
|
|
9
|
-
import js from
|
|
10
|
-
import eslintConfigPrettier from
|
|
11
|
-
import jsdocPlugin from
|
|
12
|
-
import sveltePlugin from
|
|
13
|
-
import globals from
|
|
14
|
-
import svelteParser from
|
|
9
|
+
import js from '@eslint/js'; // Provides ESLint core rules and recommended config
|
|
10
|
+
import eslintConfigPrettier from 'eslint-config-prettier'; // Prettier config to disable conflicting ESLint rules
|
|
11
|
+
import jsdocPlugin from 'eslint-plugin-jsdoc'; // JSDoc plugin
|
|
12
|
+
import sveltePlugin from 'eslint-plugin-svelte'; // Svelte plugin
|
|
13
|
+
import globals from 'globals';
|
|
14
|
+
import svelteParser from 'svelte-eslint-parser'; // Svelte parser
|
|
15
15
|
|
|
16
16
|
const GLOBALS = {
|
|
17
17
|
...globals.browser,
|
|
18
18
|
...globals.node,
|
|
19
|
-
self:
|
|
20
|
-
location:
|
|
21
|
-
indexedDB:
|
|
19
|
+
self: 'readonly',
|
|
20
|
+
location: 'readonly',
|
|
21
|
+
indexedDB: 'readonly',
|
|
22
22
|
...globals.vitest, // Add Vitest globals for test functions like afterEach, describe, etc.
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
// Define general ESLint rules (non-Svelte-specific)
|
|
26
26
|
const ESLINT_RULES = {
|
|
27
|
-
indent:
|
|
28
|
-
quotes:
|
|
29
|
-
semi:
|
|
27
|
+
indent: 'off', // Turn off the 'indent' rule, managed by Prettier
|
|
28
|
+
quotes: 'off', // Turn off the 'quotes' rule, managed by Prettier
|
|
29
|
+
semi: 'off', // Turn off the 'semi' rule, managed by Prettier
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
export default [
|
|
33
33
|
// Global ignores
|
|
34
34
|
{
|
|
35
35
|
ignores: [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
'.*', // Hidden files
|
|
37
|
+
'*.xml', // XML files
|
|
38
|
+
'**/.cache/**', // Cache directories
|
|
39
|
+
'**/.vscode/**', // VSCode-specific files
|
|
40
|
+
'**/coverage/**', // Coverage reports
|
|
41
|
+
'**/build/**', // Distribution files
|
|
42
|
+
'package.json', // NPM package manifest
|
|
43
|
+
'package-lock.json', // NPM lockfile
|
|
44
|
+
'**/playwright-report/**', // Playwright report files
|
|
45
|
+
'node_modules/', // Node.js dependencies
|
|
46
|
+
'**/test-results/**', // Test results
|
|
47
|
+
'.vite/', // Vite-specific cache directory
|
|
48
|
+
'*.lock', // Lock files
|
|
49
|
+
'.env*', // Environment files
|
|
50
50
|
],
|
|
51
51
|
},
|
|
52
52
|
|
|
53
53
|
// General JavaScript/Node.js configuration
|
|
54
54
|
{
|
|
55
|
-
files: [
|
|
55
|
+
files: ['**/*.mjs', '**/*.js'],
|
|
56
56
|
languageOptions: {
|
|
57
57
|
globals: GLOBALS,
|
|
58
|
-
ecmaVersion:
|
|
59
|
-
sourceType:
|
|
58
|
+
ecmaVersion: 'latest',
|
|
59
|
+
sourceType: 'module',
|
|
60
60
|
},
|
|
61
61
|
plugins: {
|
|
62
62
|
jsdoc: jsdocPlugin, // Include JSDoc plugin
|
|
@@ -65,21 +65,21 @@ export default [
|
|
|
65
65
|
...js.configs.recommended.rules, // ESLint's core recommended rules (scoped)
|
|
66
66
|
...eslintConfigPrettier.rules, // Prettier config to disable conflicting ESLint rules (scoped)
|
|
67
67
|
...ESLINT_RULES, // Additional custom rules
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }], // Ignore unused variables starting with an underscore
|
|
69
|
+
'jsdoc/check-alignment': 'warn', // Ensure JSDoc block tags are aligned
|
|
70
|
+
'jsdoc/check-param-names': 'warn', // Checks parameter names in JSDoc
|
|
71
71
|
// Updated rule to allow the @updated tag
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
'jsdoc/check-tag-names': [
|
|
73
|
+
'warn',
|
|
74
74
|
{
|
|
75
|
-
definedTags: [
|
|
75
|
+
definedTags: ['updated'],
|
|
76
76
|
},
|
|
77
77
|
],
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
'jsdoc/check-types': 'warn', // Checks if types in JSDoc are defined correctly
|
|
79
|
+
'jsdoc/require-param': 'warn', // Requires @param in JSDoc
|
|
80
|
+
'jsdoc/require-returns': 'warn', // Requires @returns in JSDoc
|
|
81
|
+
'jsdoc/require-jsdoc': [
|
|
82
|
+
'warn',
|
|
83
83
|
{
|
|
84
84
|
publicOnly: true,
|
|
85
85
|
require: {
|
|
@@ -94,33 +94,33 @@ export default [
|
|
|
94
94
|
|
|
95
95
|
// Svelte-specific configuration
|
|
96
96
|
{
|
|
97
|
-
files: [
|
|
97
|
+
files: ['**/*.svelte'],
|
|
98
98
|
plugins: { svelte: sveltePlugin }, // Use imported Svelte plugin
|
|
99
99
|
languageOptions: {
|
|
100
100
|
parser: svelteParser, // Use imported Svelte parser
|
|
101
101
|
globals: GLOBALS, // Your global variables
|
|
102
|
-
ecmaVersion:
|
|
103
|
-
sourceType:
|
|
102
|
+
ecmaVersion: 'latest', // Use "latest" for Svelte to leverage modern features
|
|
103
|
+
sourceType: 'module',
|
|
104
104
|
},
|
|
105
105
|
rules: {
|
|
106
106
|
...sveltePlugin.configs.recommended.rules, // Svelte recommended rules
|
|
107
107
|
...sveltePlugin.configs.prettier.rules, // Prettier compatibility for Svelte
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
'svelte/no-at-html-tags': 'warn', // Warn on use of @html (security risk)
|
|
109
|
+
'svelte/require-optimized-style-attribute': 'warn', // Recommend optimized style attributes
|
|
110
110
|
},
|
|
111
111
|
},
|
|
112
112
|
|
|
113
113
|
// Vitest-specific configuration
|
|
114
114
|
{
|
|
115
|
-
files: [
|
|
115
|
+
files: ['**/*.test.js', '**/*.spec.js', '**/vitest-setup-client.js'], // Test-related files
|
|
116
116
|
languageOptions: {
|
|
117
117
|
globals: {
|
|
118
118
|
...GLOBALS,
|
|
119
|
-
afterEach:
|
|
119
|
+
afterEach: 'readonly', // Explicitly declare afterEach as a global
|
|
120
120
|
},
|
|
121
121
|
},
|
|
122
122
|
rules: {
|
|
123
|
-
|
|
123
|
+
'no-undef': 'off', // Turn off no-undef for test globals
|
|
124
124
|
},
|
|
125
125
|
},
|
|
126
126
|
];
|
package/jsconfig.template.jsonc
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/* =========================================================================
|
|
2
2
|
jsconfig.template.jsonc
|
|
3
3
|
|
|
4
|
-
NOTE: This file is for reference only and is not actively used by SvelteKit or
|
|
4
|
+
NOTE: This file is for reference only and is not actively used by SvelteKit or
|
|
5
|
+
tooling. SvelteKit uses the jsconfig.json file without comments for actual
|
|
6
|
+
configuration.
|
|
5
7
|
|
|
6
8
|
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
7
9
|
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
@@ -27,29 +27,29 @@ This file is part of Network Pro.
|
|
|
27
27
|
* @returns {Promise<Response>} HTTP Response with status 204 or 405
|
|
28
28
|
*/
|
|
29
29
|
export default async (request, _context) => {
|
|
30
|
-
if (request.method !==
|
|
31
|
-
return new Response(
|
|
30
|
+
if (request.method !== 'POST') {
|
|
31
|
+
return new Response('Method Not Allowed', { status: 405 });
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
try {
|
|
35
35
|
const body = await request.json();
|
|
36
|
-
const report = body[
|
|
36
|
+
const report = body['csp-report'];
|
|
37
37
|
|
|
38
38
|
// Ignore if report is missing or malformed
|
|
39
|
-
if (!report || typeof report !==
|
|
39
|
+
if (!report || typeof report !== 'object') {
|
|
40
40
|
return new Response(null, { status: 204 });
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const violated = report[
|
|
44
|
-
const blockedUri = report[
|
|
43
|
+
const violated = report['violated-directive'] ?? '';
|
|
44
|
+
const blockedUri = report['blocked-uri'] ?? '';
|
|
45
45
|
|
|
46
46
|
// Filter: Skip img-src violations and empty URIs
|
|
47
47
|
const ignored = [
|
|
48
|
-
violated.startsWith(
|
|
49
|
-
blockedUri ===
|
|
50
|
-
blockedUri ===
|
|
51
|
-
blockedUri.startsWith(
|
|
52
|
-
blockedUri.startsWith(
|
|
48
|
+
violated.startsWith('img-src'),
|
|
49
|
+
blockedUri === '',
|
|
50
|
+
blockedUri === 'about',
|
|
51
|
+
blockedUri.startsWith('chrome-extension://'),
|
|
52
|
+
blockedUri.startsWith('moz-extension://'),
|
|
53
53
|
].some(Boolean);
|
|
54
54
|
|
|
55
55
|
if (ignored) {
|
|
@@ -60,15 +60,15 @@ export default async (request, _context) => {
|
|
|
60
60
|
await sendToNtfy(violated, blockedUri, report);
|
|
61
61
|
|
|
62
62
|
// Log useful violations
|
|
63
|
-
console.log(
|
|
63
|
+
console.log('[CSP-Edge] Violation:', {
|
|
64
64
|
directive: violated,
|
|
65
65
|
uri: blockedUri,
|
|
66
|
-
referrer: report[
|
|
67
|
-
source: report[
|
|
68
|
-
line: report[
|
|
66
|
+
referrer: report['referrer'],
|
|
67
|
+
source: report['source-file'],
|
|
68
|
+
line: report['line-number'],
|
|
69
69
|
});
|
|
70
70
|
} catch (err) {
|
|
71
|
-
console.warn(
|
|
71
|
+
console.warn('[CSP-Edge] Failed to parse CSP report:', err.message);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return new Response(null, { status: 204 });
|
|
@@ -87,13 +87,13 @@ const VIOLATION_TTL_MS = 60_000;
|
|
|
87
87
|
*/
|
|
88
88
|
async function sendToNtfy(violated, blockedUri, report) {
|
|
89
89
|
const highRiskDirectives = [
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
'script-src',
|
|
91
|
+
'form-action',
|
|
92
|
+
'frame-ancestors',
|
|
93
|
+
'base-uri',
|
|
94
94
|
];
|
|
95
95
|
|
|
96
|
-
const directiveKey = violated.split(
|
|
96
|
+
const directiveKey = violated.split(' ')[0]; // strip fallback values or sources
|
|
97
97
|
const isHighRisk = highRiskDirectives.includes(directiveKey);
|
|
98
98
|
console.log(`[CSP-Edge] Checking directive: ${directiveKey}`);
|
|
99
99
|
if (!isHighRisk) return;
|
|
@@ -120,23 +120,23 @@ async function sendToNtfy(violated, blockedUri, report) {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
const topicUrl =
|
|
123
|
+
const topicUrl = 'https://ntfy.neteng.pro/csp-alerts';
|
|
124
124
|
|
|
125
125
|
const message = [
|
|
126
126
|
`🚨 CSP Violation Detected`,
|
|
127
127
|
`Directive: ${violated}`,
|
|
128
128
|
`Blocked URI: ${blockedUri}`,
|
|
129
|
-
`Referrer: ${report.referrer ||
|
|
130
|
-
`Source: ${report[
|
|
131
|
-
`Line: ${report[
|
|
132
|
-
].join(
|
|
129
|
+
`Referrer: ${report.referrer || 'N/A'}`,
|
|
130
|
+
`Source: ${report['source-file'] || 'N/A'}`,
|
|
131
|
+
`Line: ${report['line-number'] || 'N/A'}`,
|
|
132
|
+
].join('\n');
|
|
133
133
|
|
|
134
134
|
await fetch(topicUrl, {
|
|
135
|
-
method:
|
|
135
|
+
method: 'POST',
|
|
136
136
|
headers: {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
'Content-Type': 'text/plain',
|
|
138
|
+
'X-Title': 'High-Risk CSP Violation',
|
|
139
|
+
'X-Priority': '5',
|
|
140
140
|
},
|
|
141
141
|
body: message,
|
|
142
142
|
});
|
|
@@ -147,5 +147,5 @@ async function sendToNtfy(violated, blockedUri, report) {
|
|
|
147
147
|
* This sets the endpoint route to /api/csp-report
|
|
148
148
|
*/
|
|
149
149
|
export const config = {
|
|
150
|
-
path:
|
|
150
|
+
path: '/api/csp-report',
|
|
151
151
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@networkpro/web",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.13.0",
|
|
5
5
|
"description": "Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro Strategies",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"advisory",
|
|
@@ -80,12 +80,12 @@
|
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"dompurify": "^3.2.6",
|
|
83
|
-
"posthog-js": "^1.250.
|
|
83
|
+
"posthog-js": "^1.250.2",
|
|
84
84
|
"semver": "^7.7.2",
|
|
85
|
-
"svelte": "5.
|
|
85
|
+
"svelte": "5.34.1"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@eslint/compat": "^1.
|
|
88
|
+
"@eslint/compat": "^1.3.0",
|
|
89
89
|
"@eslint/js": "^9.28.0",
|
|
90
90
|
"@lhci/cli": "^0.15.0",
|
|
91
91
|
"@playwright/test": "^1.53.0",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"browserslist": "^4.25.0",
|
|
100
100
|
"eslint": "^9.28.0",
|
|
101
101
|
"eslint-config-prettier": "^10.1.5",
|
|
102
|
-
"eslint-plugin-jsdoc": "^50.
|
|
102
|
+
"eslint-plugin-jsdoc": "^50.8.0",
|
|
103
103
|
"eslint-plugin-svelte": "^3.9.2",
|
|
104
104
|
"globals": "^16.2.0",
|
|
105
105
|
"jsdom": "^26.1.0",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"markdownlint-cli2": "^0.18.1",
|
|
109
109
|
"mdsvex": "^0.12.6",
|
|
110
110
|
"playwright": "^1.53.0",
|
|
111
|
-
"postcss": "^8.5.
|
|
111
|
+
"postcss": "^8.5.5",
|
|
112
112
|
"prettier": "^3.5.3",
|
|
113
113
|
"prettier-plugin-svelte": "^3.4.0",
|
|
114
114
|
"stylelint": "^16.20.0",
|
package/playwright.config.js
CHANGED
|
@@ -7,14 +7,14 @@ This file is part of Network Pro.
|
|
|
7
7
|
========================================================================== */
|
|
8
8
|
|
|
9
9
|
// @ts-check
|
|
10
|
-
import { defineConfig, devices } from
|
|
10
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @see https://playwright.dev/docs/test-configuration
|
|
14
14
|
*/
|
|
15
15
|
export default defineConfig({
|
|
16
|
-
testDir:
|
|
17
|
-
testMatch:
|
|
16
|
+
testDir: './tests/e2e',
|
|
17
|
+
testMatch: '*.spec.js',
|
|
18
18
|
|
|
19
19
|
/* Run tests in files in parallel */
|
|
20
20
|
fullyParallel: true,
|
|
@@ -29,12 +29,12 @@ export default defineConfig({
|
|
|
29
29
|
workers: process.env.CI ? 1 : undefined,
|
|
30
30
|
|
|
31
31
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
32
|
-
reporter:
|
|
32
|
+
reporter: 'html',
|
|
33
33
|
|
|
34
34
|
/* Shared settings for all projects */
|
|
35
35
|
use: {
|
|
36
|
-
baseURL:
|
|
37
|
-
trace:
|
|
36
|
+
baseURL: 'http://localhost:4173?nosw', // Update to use preview server URL
|
|
37
|
+
trace: 'on-first-retry',
|
|
38
38
|
timeout: 60000, // Default action timeout of 60 seconds for each step
|
|
39
39
|
navigationTimeout: 60000, // Timeout for navigation operations
|
|
40
40
|
},
|
|
@@ -43,16 +43,16 @@ export default defineConfig({
|
|
|
43
43
|
projects: [
|
|
44
44
|
// Desktop Browsers
|
|
45
45
|
{
|
|
46
|
-
name:
|
|
46
|
+
name: 'chromium',
|
|
47
47
|
use: {
|
|
48
|
-
browserName:
|
|
48
|
+
browserName: 'chromium', // Use Chromium browser
|
|
49
49
|
headless: true, // Enable true headless mode
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
|
-
name:
|
|
53
|
+
name: 'firefox',
|
|
54
54
|
use: {
|
|
55
|
-
...devices[
|
|
55
|
+
...devices['Desktop Firefox'], // Use default Firefox settings
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
// FIXME: Webkit and Safari consistently failing, disabled for now
|
|
@@ -65,9 +65,9 @@ export default defineConfig({
|
|
|
65
65
|
|
|
66
66
|
// Mobile Browsers
|
|
67
67
|
{
|
|
68
|
-
name:
|
|
68
|
+
name: 'Mobile Chrome',
|
|
69
69
|
use: {
|
|
70
|
-
...devices[
|
|
70
|
+
...devices['Galaxy S9+'], // Use the Galaxy S9+ device profile
|
|
71
71
|
headless: true, // Enable true headless mode
|
|
72
72
|
},
|
|
73
73
|
},
|
|
@@ -82,8 +82,8 @@ export default defineConfig({
|
|
|
82
82
|
|
|
83
83
|
/* Run your local preview server before starting the tests */
|
|
84
84
|
webServer: {
|
|
85
|
-
command:
|
|
86
|
-
url:
|
|
85
|
+
command: 'npm run preview', // Use preview server
|
|
86
|
+
url: 'http://localhost:4173?nosw', // Match the preview server URL
|
|
87
87
|
reuseExistingServer: !process.env.CI,
|
|
88
88
|
timeout: 60 * 1000, // wait up to 60 seconds for preview to be ready
|
|
89
89
|
},
|
package/postcss.config.mjs
CHANGED
|
@@ -6,7 +6,7 @@ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
|
6
6
|
This file is part of Network Pro.
|
|
7
7
|
========================================================================== */
|
|
8
8
|
|
|
9
|
-
import autoprefixer from
|
|
9
|
+
import autoprefixer from 'autoprefixer';
|
|
10
10
|
|
|
11
11
|
export default {
|
|
12
12
|
plugins: [
|
package/scripts/auditScripts.js
CHANGED
|
@@ -15,16 +15,16 @@ This file is part of Network Pro.
|
|
|
15
15
|
* @updated 2025-05-21
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import fs from
|
|
19
|
-
import path from
|
|
18
|
+
import fs from 'fs';
|
|
19
|
+
import path from 'path';
|
|
20
20
|
|
|
21
|
-
const scriptsDir = path.resolve(
|
|
22
|
-
const testsDir = path.resolve(
|
|
21
|
+
const scriptsDir = path.resolve('./scripts');
|
|
22
|
+
const testsDir = path.resolve('./tests');
|
|
23
23
|
|
|
24
24
|
// Scripts intentionally excluded from test coverage
|
|
25
25
|
const allowList = new Set([
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
'checkNode.js',
|
|
27
|
+
'auditScripts.js', // itself
|
|
28
28
|
]);
|
|
29
29
|
|
|
30
30
|
// Recursively gather all test files
|
|
@@ -38,10 +38,10 @@ function getAllTestFiles(dir) {
|
|
|
38
38
|
files.push(...getAllTestFiles(fullPath));
|
|
39
39
|
} else if (
|
|
40
40
|
entry.isFile() &&
|
|
41
|
-
(entry.name.endsWith(
|
|
42
|
-
entry.name.endsWith(
|
|
43
|
-
entry.name.endsWith(
|
|
44
|
-
entry.name.endsWith(
|
|
41
|
+
(entry.name.endsWith('.test.js') ||
|
|
42
|
+
entry.name.endsWith('.spec.js') ||
|
|
43
|
+
entry.name.endsWith('.test.mjs') ||
|
|
44
|
+
entry.name.endsWith('.spec.mjs'))
|
|
45
45
|
) {
|
|
46
46
|
files.push(fullPath);
|
|
47
47
|
}
|
|
@@ -56,17 +56,17 @@ const testedModules = new Set(
|
|
|
56
56
|
testFiles.map((filePath) =>
|
|
57
57
|
path
|
|
58
58
|
.basename(filePath)
|
|
59
|
-
.replace(/\.test\.js$|\.spec\.js$|\.test\.mjs$|\.spec\.mjs$/,
|
|
59
|
+
.replace(/\.test\.js$|\.spec\.js$|\.test\.mjs$|\.spec\.mjs$/, ''),
|
|
60
60
|
),
|
|
61
61
|
);
|
|
62
62
|
|
|
63
63
|
// Gather all scripts (.js and .mjs)
|
|
64
64
|
const scriptFiles = fs
|
|
65
65
|
.readdirSync(scriptsDir)
|
|
66
|
-
.filter((file) => file.endsWith(
|
|
66
|
+
.filter((file) => file.endsWith('.js') || file.endsWith('.mjs'));
|
|
67
67
|
|
|
68
68
|
const untested = scriptFiles.filter((file) => {
|
|
69
|
-
const base = file.replace(/\.(js|mjs)$/,
|
|
69
|
+
const base = file.replace(/\.(js|mjs)$/, '');
|
|
70
70
|
return !allowList.has(file) && !testedModules.has(base);
|
|
71
71
|
});
|
|
72
72
|
|
|
@@ -75,7 +75,7 @@ const pathRelative = (file) =>
|
|
|
75
75
|
|
|
76
76
|
// Output results
|
|
77
77
|
if (untested.length) {
|
|
78
|
-
console.warn(
|
|
78
|
+
console.warn('\n⚠ Untested script files detected:\n');
|
|
79
79
|
|
|
80
80
|
untested.forEach((file) => {
|
|
81
81
|
const filePath = pathRelative(file);
|
|
@@ -87,9 +87,9 @@ if (untested.length) {
|
|
|
87
87
|
console.warn(
|
|
88
88
|
`\nAdd a corresponding test file in /tests (e.g., ${untested[0].replace(
|
|
89
89
|
/\.(js|mjs)$/,
|
|
90
|
-
|
|
90
|
+
'.test.js',
|
|
91
91
|
)})`,
|
|
92
92
|
);
|
|
93
93
|
} else {
|
|
94
|
-
console.log(
|
|
94
|
+
console.log('✅ All script files have corresponding tests.');
|
|
95
95
|
}
|