diff --git a/.gitignore b/.gitignore index 24c2617..f123e97 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,13 @@ repomix-output.* private/ # Deploy script - holds server/target details, never shipped. /scripts/deploy.sh + +# --- Syncthing artifacts ------------------------------------- +# The whole Khemul folder is synced between machines via Syncthing; never track +# its housekeeping files or conflict copies. +.stfolder/ +.stignore +.stversions/ +.syncthing.*.tmp +~syncthing~*.tmp +*.sync-conflict-* diff --git a/CHANGELOG.md b/CHANGELOG.md index c3761ab..5325c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.3.1] - 2026-07-24 + +### Security + +- **Bumped `immutable` 5.1.6 -> 5.1.9** to clear two high-severity + denial-of-service advisories (GHSA-v56q-mh7h-f735, GHSA-xvcm-6775-5m9r). + `immutable` is a transitive **dev** dependency pulled in by `sass` and only + runs during the build, never in the shipped app - so the advisories were not + exploitable against users - but this clears the alerts. + ### Changed - **Relicensed from PolyForm Noncommercial 1.0.0 to MIT + Commons Clause.** @@ -15,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 modification, and free redistribution, and forbid only selling the software (per the Commons Clause). Updated `LICENSE`, `package.json`, the README badge and license note, and CONTRIBUTING. +- **Updated dependencies** - `lucide-static` 1.24.0 -> 1.26.0 (Lucide icon set), + plus build and CI tooling (`happy-dom`, `sass`, `actions/checkout`). ## [1.3.0] - 2026-06-25 @@ -56,5 +68,6 @@ describes the app as it stands at that release. - **Touch support** - drag to pan, pinch to zoom, and long-press for context menus on tablets. -[Unreleased]: https://github.com/BrainInBlack/NetGraph/compare/v1.3.0...HEAD +[Unreleased]: https://github.com/BrainInBlack/NetGraph/compare/v1.3.1...HEAD +[1.3.1]: https://github.com/BrainInBlack/NetGraph/compare/v1.3.0...v1.3.1 [1.3.0]: https://github.com/BrainInBlack/NetGraph/releases/tag/v1.3.0 diff --git a/package-lock.json b/package-lock.json index e420a02..88a80ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "netgraph", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "netgraph", - "version": "1.3.0", + "version": "1.3.1", "license": "SEE LICENSE IN LICENSE", "dependencies": { "lucide-static": "^1.26.0" diff --git a/package.json b/package.json index 8f3a3be..aee2871 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "netgraph", "private": true, - "version": "1.3.0", + "version": "1.3.1", "description": "Browser-based local network visualizer - map your home or lab network, stored entirely in localStorage with no backend.", "license": "SEE LICENSE IN LICENSE", "author": "BrainInBlack ", diff --git a/src/ts/svg-sanitizer.ts b/src/ts/svg-sanitizer.ts index 03f4460..938b7cd 100644 --- a/src/ts/svg-sanitizer.ts +++ b/src/ts/svg-sanitizer.ts @@ -36,14 +36,13 @@ export const MAX_SVG_LENGTH = 64 * 1024; export function sanitizeSvg(text: string): string | null { if (text.length > MAX_SVG_LENGTH) return null; - // CodeQL flags this parse as `js/xss-through-dom` ("DOM text reinterpreted as - // HTML"). It is a false positive: this is the sanitizer's own entry point. - // The untrusted string is parsed here, then the tree is scrubbed against an - // allow-list of tags and attributes and walked over all child nodes (dropping - // CDATA, comments, and processing instructions, see the mXSS note below) - // before `root.outerHTML` is returned. Nothing reaches the DOM unsanitized. - // The alert is dismissed as a false positive in GitHub code scanning; keep - // this comment so the reasoning is visible at the source. + // A static analyzer may flag this parse as DOM-based XSS ("DOM text + // reinterpreted as HTML"). It is a false positive: this is the sanitizer's own + // entry point. The untrusted string is parsed here, then the tree is scrubbed + // against an allow-list of tags and attributes and walked over all child nodes + // (dropping CDATA, comments, and processing instructions, see the mXSS note + // below) before `root.outerHTML` is returned. Nothing reaches the DOM + // unsanitized. const doc = new DOMParser().parseFromString(text, 'image/svg+xml'); const root = doc.querySelector('svg'); if (!root || doc.querySelector('parsererror')) return null;