import test from 'node:test'; import assert from 'node:assert/strict'; import redaction from '../src/main/log-redaction.cjs'; const { redactSecrets, sanitizeForDiagnostics, pathAlias, stableAlias, redactPrivateInfrastructure } = redaction; test('redacts runtime credentials, structured secrets, private keys and URL credentials', () => { const token = ['gitea', 'TEST', 'ONLY', 'SecretToken123456'].join('_'); const input = [ `Authorization: Bearer ${token}`, `https://${['jens', 'p4ssw0rd'].join(':')}@gitea.example.test/api?access_token=${token}`, 'client_secret=another-secret-value', ['-----BEGIN', 'PRIVATE KEY-----\nsecret-key-material\n-----END PRIVATE KEY-----'].join(' ') ].join('\n'); const output = redactSecrets(input, [token]); assert.doesNotMatch(output, /ThisIsARealisticSecret|p4ssw0rd|another-secret-value|secret-key-material/); assert.match(output, /REDACTED/); }); test('sanitizes nested sensitive keys and aliases user paths', () => { const value = { accessToken: 'do-not-keep', nested: { password: 'do-not-keep-either', path: 'C:\\Users\\Jens\\Projects\\ForgeFlow' }, home: '/home/jens/projects/forgeflow' }; const sanitized = sanitizeForDiagnostics(value, { homeDir: '/home/jens', cwd: '/work/ForgeFlow' }); assert.equal(sanitized.accessToken, '[REDACTED]'); assert.equal(sanitized.nested.password, '[REDACTED]'); assert.doesNotMatch(JSON.stringify(sanitized), /do-not-keep|Users\\Jens|\/home\/jens/); assert.match(JSON.stringify(sanitized), //); }); test('strict privacy mode replaces stable identifiers deterministically', () => { const first = sanitizeForDiagnostics({ fullName: 'jens/private-project', login: 'jens', host: '192.168.10.20', basePath: '/mnt/user/appdata' }, { strictIdentifiers: true }); const second = sanitizeForDiagnostics({ fullName: 'jens/private-project', login: 'jens', host: '192.168.10.20', basePath: '/mnt/user/appdata' }, { strictIdentifiers: true }); assert.equal(first.fullName, second.fullName); assert.equal(first.login, second.login); assert.notEqual(first.fullName, 'jens/private-project'); assert.match(first.fullName, /^fullname-[a-f0-9]{12}$/); assert.notEqual(first.host, '192.168.10.20'); assert.notEqual(first.basePath, '/mnt/user/appdata'); assert.equal(stableAlias('same', 'repo'), stableAlias('same', 'repo')); }); test('strict privacy redacts private addresses, infrastructure URLs and server paths in log text', () => { const result = redactPrivateInfrastructure('host 192.168.10.20 url https://internal.example.test/status path /mnt/user/appdata/example'); assert.doesNotMatch(result, /192\.168\.10\.20|internal\.example\.test|\/mnt\/user\/appdata/); }); test('path aliasing handles slash variants', () => { const result = pathAlias('C:\\Users\\Jens\\src and C:/Users/Jens/src', { homeDir: 'C:\\Users\\Jens', cwd: 'D:\\ForgeFlow' }); assert.doesNotMatch(result, /Users[\\/]Jens/); assert.match(result, //); });