feat: add captcha-backed forum security hardening

This commit is contained in:
2026-03-17 16:06:28 +01:00
parent 980a15f66e
commit b3fc889452
40 changed files with 2849 additions and 108 deletions

View File

@@ -0,0 +1,65 @@
async function sha256Hex(value) {
if (!window.crypto?.subtle) {
return ''
}
const encoded = new TextEncoder().encode(value)
const digest = await window.crypto.subtle.digest('SHA-256', encoded)
return Array.from(new Uint8Array(digest))
.map((part) => part.toString(16).padStart(2, '0'))
.join('')
}
function readWebglVendor() {
try {
const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
if (!gl) {
return 'no-webgl'
}
const extension = gl.getExtension('WEBGL_debug_renderer_info')
if (!extension) {
return 'webgl-hidden'
}
return [
gl.getParameter(extension.UNMASKED_VENDOR_WEBGL),
gl.getParameter(extension.UNMASKED_RENDERER_WEBGL),
].join(':')
} catch {
return 'webgl-error'
}
}
export async function buildBotFingerprint() {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'unknown'
const screenSize = typeof window.screen !== 'undefined'
? `${window.screen.width}x${window.screen.height}x${window.devicePixelRatio || 1}`
: 'no-screen'
const payload = [
navigator.userAgent || 'unknown-ua',
navigator.language || 'unknown-language',
navigator.platform || 'unknown-platform',
timezone,
screenSize,
readWebglVendor(),
].join('|')
return sha256Hex(payload)
}
export async function populateBotFingerprint(form) {
if (!form) {
return ''
}
const fingerprint = await buildBotFingerprint()
const field = form.querySelector('input[name="_bot_fingerprint"]')
if (field && fingerprint !== '') {
field.value = fingerprint
}
return fingerprint
}