const assert = require('node:assert/strict'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const { test } = require('node:test'); const { scanAptProxies, summarizeAptFindings } = require('./apt-audit.js'); function mkAptDir(t, files) { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'apt-audit-')); t.after(() => fs.rmSync(dir, { recursive: true, force: true })); for (const [name, content] of Object.entries(files)) { fs.writeFileSync(path.join(dir, name), content); } return dir; } const BRIDGE_CONF = 'Acquire::http::Proxy "http://127.0.0.1:8888/";\nAcquire::https::Proxy "http://127.0.0.1:8888/";\n'; test('clean setup: only 80proxy-bridge with bridge URL → no threats', t => { const dir = mkAptDir(t, { '20archive': '// no proxies here\n', '80proxy-bridge': BRIDGE_CONF, '99update-notifier': '// unrelated\n', }); const { findings } = scanAptProxies(dir); const summary = summarizeAptFindings(findings); assert.equal(summary.bridgePresent, true); assert.deepEqual(summary.threats, []); }); test('legacy 80proxy with embedded creds is flagged creds even when sorting before ours', t => { const dir = mkAptDir(t, { '80proxy': 'Acquire::http::Proxy "http://user:p%40ss@proxy.corp:8080/";\n', '80proxy-bridge': BRIDGE_CONF, }); const { findings } = scanAptProxies(dir); const credFinding = findings.find(f => f.name === '80proxy'); assert.equal(credFinding.severity, 'creds'); assert.equal(summarizeAptFindings(findings).threats.length, 1); }); test('a later-sorting file with an external proxy overrides the bridge (apt last-wins)', t => { const dir = mkAptDir(t, { '80proxy-bridge': BRIDGE_CONF, '99custom': 'Acquire::http::Proxy "http://other.proxy:3128/";\n', }); const { findings } = scanAptProxies(dir); const f99 = findings.find(f => f.name === '99custom'); assert.equal(f99.severity, 'overrides'); assert.equal(f99.sortsAfterBridge, true); assert.equal(summarizeAptFindings(findings).threats.length, 1); }); test('earlier-sorting external proxy does not override but is still reported external', t => { const dir = mkAptDir(t, { '10proxy': 'Acquire::https::Proxy "http://other.proxy:3128/";\n', '80proxy-bridge': BRIDGE_CONF, }); const { findings } = scanAptProxies(dir); const f10 = findings.find(f => f.name === '10proxy'); assert.equal(f10.severity, 'external'); assert.equal(f10.sortsAfterBridge, false); }); test('missing directory returns an error instead of crashing', t => { const { findings, error } = scanAptProxies('/nonexistent-apt-dir-xyz'); assert.deepEqual(findings, []); assert.ok(error); }); test('bridge file missing entirely: bridgePresent false, all proxy files reported', t => { const dir = mkAptDir(t, { '50proxy': 'Acquire::http::Proxy "http://some.proxy:8080/";\n', }); const { findings } = scanAptProxies(dir); const summary = summarizeAptFindings(findings); assert.equal(summary.bridgePresent, false); assert.equal(summary.threats.length, 1); assert.equal(summary.threats[0].severity, 'external'); // effective config; not "overriding" a bridge that isn't there // A cred-bearing file must still be flagged creds even without a bridge file: const dir2 = mkAptDir(t, { '99bad': 'Acquire::http::Proxy "http://u:p@proxy:8080/";\n' }); const { findings: f2 } = scanAptProxies(dir2); assert.equal(f2[0].severity, 'creds'); });