Repository files, collaboration, releases and project activity.
archforge-external-status / tests/security.test.jsmain
▤ tests/security.test.js1651 bytes
10 lines · Select a line number for a permalink
1
'use strict';2
const test=require('node:test'),assert=require('node:assert/strict'),crypto=require('node:crypto');3
const sec=require('../src/security');const {readConfig}=require('../src/config');4
test('strong scrypt password hashes and comparison',()=>{const v=sec.passwordHash('a very long password!');assert.ok(sec.verifyPassword('a very long password!',v));assert.equal(sec.verifyPassword('wrong',v),false);assert.throws(()=>sec.passwordHash('short'));});5
test('TOTP can be verified with step skew, wrong digits rejected',()=>{const secret=sec.base32Encode(Buffer.from('12345678901234567890'));const time=60000000;assert.ok(sec.verifyTotp(secret,sec.totp(secret,time),time));assert.equal(sec.verifyTotp(secret,'123',time),false);});6
test('Encryption uses authenticated AEAD',()=>{const key=crypto.randomBytes(32).toString('hex');const v=sec.encrypt(key,'top secret');assert.equal(sec.decrypt(key,v),'top secret');assert.throws(()=>sec.decrypt(key,v.slice(0,-2)+'xx'));});7
test('HTML output is escaped',()=>assert.equal(sec.esc('<script>"'), '<script>"'));8
test('Only HTTPS URLs accepted in configuration',()=>{assert.throws(()=>require('../src/config').urlValue('http://example.com'));assert.equal(require('../src/config').urlValue('https://example.com/'),'https://example.com/');});9
test('webhook hostname and path restrictions',()=>{const {discordAllowed}=require('../src/notifications');assert.ok(discordAllowed('https://discord.com/api/webhooks/123456/ab-C_8'));assert.equal(discordAllowed('https://evil.com/api/webhooks/123456/abc'),false);assert.equal(discordAllowed('https://discord.com.evil.com/api/webhooks/123/abc'),false);});