Preview: Variablen verschluesselt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-09-30 21:53:41 +00:00
1 parent e358514240
commit 20ca1de694
2 files changed
+152

No files matched your search

+81
View File
@@ -0,0 +1,81 @@
import { test } from 'node:test'
import assert from 'node:assert/strict'
import crypto from 'node:crypto'
import {
encryptEnv, decryptEnv, validateEnvChange, envNames, maskLog, envKey,
} from '../server/services/previewEnv.js'
const key = crypto.randomBytes(32)
test('Round-Trip und Format', () => {
const s = encryptEnv({ A: 'x', B: 'ü' }, key)
assert.match(s, /^v1:[^:]+:[^:]+:[^:]+$/)
assert.deepEqual(decryptEnv(s, key), { A: 'x', B: 'ü' })
assert.notEqual(encryptEnv({ A: 'x' }, key), encryptEnv({ A: 'x' }, key))
})
test('leer', () => {
assert.deepEqual(decryptEnv(encryptEnv({}, key), key), {})
assert.deepEqual(decryptEnv('', key), {})
assert.deepEqual(decryptEnv(null, key), {})
})
test('falscher Schluessel und manipulierter Tag => Fehler', () => {
const s = encryptEnv({ A: 'geheim' }, key)
assert.throws(() => decryptEnv(s, crypto.randomBytes(32)))
const p = s.split(':')
const tag = Buffer.from(p[2], 'base64')
tag[0] ^= 1
p[2] = tag.toString('base64')
assert.throws(() => decryptEnv(p.join(':'), key))
assert.throws(() => decryptEnv('v2:a:b:c', key))
})
test('envNames sortiert', () => {
assert.deepEqual(envNames(encryptEnv({ B: '1', A: '2' }, key), key), ['A', 'B'])
assert.deepEqual(envNames('', key), [])
})
test('envKey', () => {
const old = process.env.PREVIEW_ENV_KEY
try {
delete process.env.PREVIEW_ENV_KEY
assert.equal(envKey(), null)
process.env.PREVIEW_ENV_KEY = Buffer.alloc(16).toString('base64')
assert.equal(envKey(), null)
process.env.PREVIEW_ENV_KEY = key.toString('base64')
assert.ok(envKey().equals(key))
} finally {
if (old === undefined) delete process.env.PREVIEW_ENV_KEY
else process.env.PREVIEW_ENV_KEY = old
}
})
test('validateEnvChange', () => {
let r = validateEnvChange({ A: '1' }, { set: { B: '2' }, remove: ['A', 'NIX'] })
assert.deepEqual(r, { ok: true, env: { B: '2' } })
assert.equal(validateEnvChange({}, { set: { abc: '1' } }).ok, false)
assert.equal(validateEnvChange({}, { set: { '1A': '1' } }).ok, false)
assert.equal(validateEnvChange({}, { set: { A: 'x'.repeat(4097) } }).ok, false)
assert.equal(validateEnvChange({}, { set: { A: 'x'.repeat(4096) } }).ok, true)
assert.equal(validateEnvChange({}, { set: { A: 'ü'.repeat(2049) } }).ok, false)
assert.equal(validateEnvChange({}, { set: { A: 1 } }).ok, false)
assert.equal(validateEnvChange({}, { set: { A: 'a\nb' } }).ok, false)
assert.equal(validateEnvChange({}, { set: { A: 'a\0b' } }).ok, false)
const many = Object.fromEntries(Array.from({ length: 31 }, (_, i) => [`V${i}`, '1']))
r = validateEnvChange({}, { set: many })
assert.equal(r.ok, false)
assert.match(r.error, /30/)
const thirty = Object.fromEntries(Array.from({ length: 30 }, (_, i) => [`V${i}`, '1']))
assert.equal(validateEnvChange(thirty, { set: { V0: '2' } }).ok, true)
assert.equal(validateEnvChange(thirty, { set: { NEU: '2' }, remove: ['V1'] }).ok, true)
assert.equal(validateEnvChange(thirty, { set: { NEU: '2' } }).ok, false)
assert.equal(validateEnvChange({}, {}).ok, true)
})
test('maskLog', () => {
const env = { A: 'geheim', B: 'abc', C: 'geheimer' , D: 'a.b+'}
assert.equal(maskLog('x geheimer y geheim z abc a.b+ axbb', env), 'x ••• y ••• z abc ••• axbb')
assert.equal(maskLog('', env), '')
assert.equal(maskLog('text', {}), 'text')
})