From 2f02df4910f74f5ca1aa22246a62a05cb8ee619f Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Sun, 8 Feb 2026 14:15:23 +0100 Subject: [PATCH] security: encrypt NaCl keypair at rest with AES-GCM and harden PoW captcha signature with HMAC-SHA256 --- js/components/pages/page-listing.js | 6 +- js/components/pow-captcha.js | 5 +- js/components/search-box.js | 2 +- js/services/auth.js | 5 ++ js/services/crypto.js | 111 +++++++++++++++++++++++----- js/services/pow-captcha.js | 67 ++++++++++++----- 6 files changed, 151 insertions(+), 45 deletions(-) diff --git a/js/components/pages/page-listing.js b/js/components/pages/page-listing.js index f1843de..f54e735 100644 --- a/js/components/pages/page-listing.js +++ b/js/components/pages/page-listing.js @@ -635,11 +635,7 @@ class PageListing extends HTMLElement { formatDescription(text) { if (!text) return '' - return text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/\n/g, '
') + return escapeHTML(text).replace(/\n/g, '
') } } diff --git a/js/components/pow-captcha.js b/js/components/pow-captcha.js index f1fcdba..666fa45 100644 --- a/js/components/pow-captcha.js +++ b/js/components/pow-captcha.js @@ -53,7 +53,7 @@ export class PowCaptcha extends HTMLElement { this.render() try { - const { challenge, difficulty, timestamp, signature } = await generateChallenge() + const { challenge, difficulty, timestamp, signature, source } = await generateChallenge() const result = await solveChallenge(challenge, difficulty) @@ -62,7 +62,8 @@ export class PowCaptcha extends HTMLElement { difficulty, nonce: result.nonce, signature, - timestamp + timestamp, + source } const verification = await verifySolution(solution) diff --git a/js/components/search-box.js b/js/components/search-box.js index cf3796a..c304be5 100644 --- a/js/components/search-box.js +++ b/js/components/search-box.js @@ -207,7 +207,7 @@ class SearchBox extends HTMLElement { badges.push(/* html */`