source: Klonkt/test/ssrf-allowlist.test.js@ f50a84b

main
Last change on this file since f50a84b was dc0da72, checked in by roboburr <roboburr@…>, 4 weeks ago

Alleen claimen wat je herkent (regressie uit shaer-8ru)

Barts honderd aanbiedingen liepen meteen stuk op "400 unsupported_offer", en dat
was mijn fout van een uur eerder.

Ik zette het gate-voorstel als case 'Offer' in de outbox-switch. Die case
claimde ELKE Offer: wat geen shaer:GatedSetting was kreeg 400 -- dus ook de
adoptie-handshake, en straks elke Offer-vorm die we nog toevoegen. De
guardianship-afhandeling stond ervoor en ving het meestal op, maar zodra die iets
niet herkende viel het in mijn 400 in plaats van door te lopen.

Nu voor de switch, naast de andere Offer-afhandeling, en alleen als
parseGatedSetting iets teruggeeft. De toets die 'unsupported_offer' verwachtte is
vervangen: die legde mijn verkeerde aanname vast. Er staat nu een toets op dat een
adoptie-Offer NIET door de gate-tak wordt afgevangen.

Twee kleinere dingen die dezelfde ronde boven kwamen:

  • Het aanbod-script gebruikte een verzonnen relatie-URI en werd daarom stil geweigerd. isGuardianRelationship accepteert precies twee waarden.
  • De SSRF-toets hing af van wat er toevallig draaide: hij ging ervan uit dat er niets op [::1]:3060 luisterde, en viel om zodra de testkudde daar stond. Nu een poort waar met opzet niets luistert. Een toets die afhangt van wat er draait bewijst niets.

Suite 756/756.

  • Property mode set to 100644
File size: 2.9 KB
Line 
1// De SSRF-poort mag gericht open voor een testkudde op de eigen machine
2// (shaer-6wt, Barts vraag 8-8: "waarom via https? gewoon localhost ::1").
3//
4// Wat hier bewaakt wordt is de SMALHEID. De bescherming bestaat omdat een
5// actor-URI van een vreemde komt; een brede "loopback mag"-vlag zou hem in een
6// dev-omgeving uitzetten, en dev-omgevingen worden productie. Een lijst van
7// precieze host:poort-paren opent precies wat erin staat en niets ernaast.
8//
9// Run: npm test
10import { test } from 'node:test';
11import assert from 'node:assert/strict';
12
13process.env.DATABASE_PATH = ':memory:';
14// Een poort waar met opzet NIETS op luistert. Eerst stond hier 3060, en toen de
15// testkudde daar ging draaien slaagde de fetch en viel de toets om -- een toets
16// die afhangt van wat er toevallig draait, bewijst niets.
17process.env.AP_ALLOW_HOSTS = '[::1]:59321';
18const AP = await import('../src/services/ActivityPubService.js');
19
20const faalt = async (url) => {
21 try { await AP.safeFetch(url); return null; }
22 catch (e) { return e.message; }
23};
24
25test('wat er WEL op staat komt langs de poort', async () => {
26 // De slaagtest, en zonder hem is de rest waardeloos: alleen weigeringen
27 // toetsen laat de suite groen terwijl er niets doorheen komt. Er draait hier
28 // niets op 3060, dus we verwachten een VERBINDINGSfout -- het bewijs is dat
29 // het geen ssrf-fout is.
30 const fout = await faalt('http://[::1]:59321/niets');
31 assert.ok(fout, 'er is wel een fout, want er luistert niets op die poort');
32 assert.ok(!String(fout).startsWith('ssrf-'), `door de poort, maar kreeg: ${fout}`);
33});
34
35test('een adres dat NIET op de lijst staat blijft geweigerd', async () => {
36 // Zelfde machine, andere poort. Zou dit doorlaten, dan is de lijst een vlag.
37 assert.equal(await faalt('http://[::1]:3060/u/w001'), 'ssrf-blocked-ip');
38});
39
40test('en 127.0.0.1 evenmin, ook al is het dezelfde machine', async () => {
41 // De lijst opent een HOST:POORT, geen begrip van "lokaal".
42 assert.equal(await faalt('http://127.0.0.1:59321/niets'), 'ssrf-blocked-ip');
43});
44
45test('het metadata-adres blijft dicht', async () => {
46 // Waar de bescherming voor bestaat.
47 assert.equal(await faalt('http://169.254.169.254/latest/meta-data/'), 'ssrf-blocked-ip');
48});
49
50test('zonder de omgevingsvariabele is er geen uitzondering', async () => {
51 // De lijst is leeg tenzij iemand hem expliciet vult. Dit is de stand waarin
52 // elke productie-instance draait.
53 const eerder = process.env.AP_ALLOW_HOSTS;
54 delete process.env.AP_ALLOW_HOSTS;
55 const mod = await import(`../src/services/ActivityPubService.js?leeg=${Date.now()}`);
56 let fout = null;
57 try { await mod.safeFetch('http://[::1]:59321/niets'); } catch (e) { fout = e.message; }
58 assert.equal(fout, 'ssrf-blocked-ip');
59 process.env.AP_ALLOW_HOSTS = eerder;
60});
61
62test('een ander schema blijft hoe dan ook geweigerd', async () => {
63 assert.equal(await faalt('file:///etc/passwd'), 'ssrf-bad-scheme');
64});
Note: See TracBrowser for help on using the repository browser.