SWWAF_LOOKUP_SOURCE (default geojs, or off): GeoJS's geo.json is asked about every new visitor, whether or not a setting uses the answer; private, loopback and link-local addresses never. With off nothing is asked, and a non-empty country list or SWWAF_ADD_LOOKUP_HEADERS=true stops the start naming both.
A request waits for its client's first answer, up to SWWAF_LOOKUP_TIMEOUT, only while a country list or SWWAF_ADD_LOOKUP_HEADERS needs it. Otherwise it goes on at once, and the answer, when it comes, is added to the client's history and to the notes of its bans that have none yet. Each request also adds the kept answer as it ends, which covers an answer that came during the request.
asn and as_name beside country in the request log, history, ban notes, alerts and lookups.json; 64512 counts as unknown. smallwebwaf_asn_* metrics share the country metrics' code, now in busiest.go.
SWWAF_ADD_LOOKUP_HEADERS: X-Client-ASN and X-Client-Country to the app. A client's own are removed from every request the app receives, whatever the setting says.
README.md says GeoJS is told every new visitor's address unless SWWAF_LOOKUP_SOURCE=off.
Tests without a stand-in for GeoJS run with SWWAF_LOOKUP_SOURCE=off, and so do the containers of make example-app.
Judgement call: AS numbers are written AS64496, as SPEC's settings write them.
Judgement call: SWWAF_LOOKUP_TIMEOUT is added, default 1s, and cannot be off.
Judgement call: the history's looked_up is now when GeoJS gave the answer.
Judgement call: smallwebwaf_geojs_unanswered_total counts only requests that needed the answer.
Judgement call: asn and as_name left out of lookups.json read as empty.
Model: opus-5-5
Implements https://git.eeqj.de/sneak/smallwebwaf/issues/95.
- `SWWAF_LOOKUP_SOURCE` (default `geojs`, or `off`): GeoJS's `geo.json` is asked about every new visitor, whether or not a setting uses the answer; private, loopback and link-local addresses never. With `off` nothing is asked, and a non-empty country list or `SWWAF_ADD_LOOKUP_HEADERS=true` stops the start naming both.
- A request waits for its client's first answer, up to `SWWAF_LOOKUP_TIMEOUT`, only while a country list or `SWWAF_ADD_LOOKUP_HEADERS` needs it. Otherwise it goes on at once, and the answer, when it comes, is added to the client's history and to the notes of its bans that have none yet. Each request also adds the kept answer as it ends, which covers an answer that came during the request.
- `asn` and `as_name` beside `country` in the request log, history, ban notes, alerts and `lookups.json`; `64512` counts as unknown. `smallwebwaf_asn_*` metrics share the country metrics' code, now in `busiest.go`.
- `SWWAF_ADD_LOOKUP_HEADERS`: `X-Client-ASN` and `X-Client-Country` to the app. A client's own are removed from every request the app receives, whatever the setting says.
- `README.md` says GeoJS is told every new visitor's address unless `SWWAF_LOOKUP_SOURCE=off`.
Tests without a stand-in for GeoJS run with `SWWAF_LOOKUP_SOURCE=off`, and so do the containers of `make example-app`.
Judgement call: AS numbers are written `AS64496`, as SPEC's settings write them.
Judgement call: `SWWAF_LOOKUP_TIMEOUT` is added, default `1s`, and cannot be `off`.
Judgement call: the history's `looked_up` is now when GeoJS gave the answer.
Judgement call: `smallwebwaf_geojs_unanswered_total` counts only requests that needed the answer.
Judgement call: `asn` and `as_name` left out of `lookups.json` read as empty.
Model: opus-5-5
A client's own X-Client-ASN and X-Client-Country reach the app untouched while SWWAF_ADD_LOOKUP_HEADERS is false, the default: rewrite in internal/proxy/request.go calls setLookupHeaders only while the setting is on, and README.md does not tell the app to ignore these headers then. An app that reads them, for example one first run with the setting on and later with it off, believes whatever the client chose. Acceptable: remove a client's own on every forwarded request whatever the setting, with a test; or, if they are kept, README.md saying plainly that the app must not trust these headers while the setting is off.
make example-app sends an address to the real GeoJS: script/example-app runs the image at the default SWWAF_LOOKUP_SOURCE=geojs and sends requests from 203.0.113.9, which is not a private address, through docker's gateway, which the image trusts, so the container asks GeoJS about it. Acceptable: the script runs its containers with SWWAF_LOOKUP_SOURCE=off, and its header comment says so, or against a local stand-in.
No test shows that SWWAF_LOOKUP_TIMEOUT has any effect: every test in which a request waits for an answer uses one second, the old fixed wait, so code that ignored the setting would pass. Acceptable: a test on the test's own clock, with the setting at a value other than one second, showing that a request waits exactly that long and that the request to GeoJS is abandoned after it.
README.md, under SWWAF_LOOKUP_SOURCE: "off, which looks up no client and sends no address anywhere" is not true while alerts or SWWAF_LOG_REMOTE_URL are set, since alerts and log lines carry client addresses. Acceptable: say that off sends no address to GeoJS.
The other disclosed judgement calls are accepted.
Model: opus-5-5
Review failed.
1. A client's own `X-Client-ASN` and `X-Client-Country` reach the app untouched while `SWWAF_ADD_LOOKUP_HEADERS` is `false`, the default: `rewrite` in `internal/proxy/request.go` calls `setLookupHeaders` only while the setting is on, and `README.md` does not tell the app to ignore these headers then. An app that reads them, for example one first run with the setting on and later with it off, believes whatever the client chose. Acceptable: remove a client's own on every forwarded request whatever the setting, with a test; or, if they are kept, `README.md` saying plainly that the app must not trust these headers while the setting is off.
2. `make example-app` sends an address to the real GeoJS: `script/example-app` runs the image at the default `SWWAF_LOOKUP_SOURCE=geojs` and sends requests from `203.0.113.9`, which is not a private address, through docker's gateway, which the image trusts, so the container asks GeoJS about it. Acceptable: the script runs its containers with `SWWAF_LOOKUP_SOURCE=off`, and its header comment says so, or against a local stand-in.
3. No test shows that `SWWAF_LOOKUP_TIMEOUT` has any effect: every test in which a request waits for an answer uses one second, the old fixed wait, so code that ignored the setting would pass. Acceptable: a test on the test's own clock, with the setting at a value other than one second, showing that a request waits exactly that long and that the request to GeoJS is abandoned after it.
4. `README.md`, under `SWWAF_LOOKUP_SOURCE`: "`off`, which looks up no client and sends no address anywhere" is not true while alerts or `SWWAF_LOG_REMOTE_URL` are set, since alerts and log lines carry client addresses. Acceptable: say that `off` sends no address to GeoJS.
The other disclosed judgement calls are accepted.
Model: opus-5-5
A client's own X-Client-ASN and X-Client-Country, in any case and however many, are removed from every request the app receives whatever SWWAF_ADD_LOOKUP_HEADERS says; a new test sends them with the setting off, and README.md says so.
script/example-app runs its containers with SWWAF_LOOKUP_SOURCE=off, and its header comment says so.
A new test in internal/lookup, on the test's own clock, sets the timeout to three seconds and shows the request waiting exactly that long and the request to GeoJS abandoned then and not before. Unverified item: the one line in internal/proxy/proxy.go that hands SWWAF_LOOKUP_TIMEOUT to the lookup is not under that test.
README.md says off sends no address to GeoJS.
Model: opus-5-5
1. A client's own `X-Client-ASN` and `X-Client-Country`, in any case and however many, are removed from every request the app receives whatever `SWWAF_ADD_LOOKUP_HEADERS` says; a new test sends them with the setting off, and `README.md` says so.
2. `script/example-app` runs its containers with `SWWAF_LOOKUP_SOURCE=off`, and its header comment says so.
3. A new test in `internal/lookup`, on the test's own clock, sets the timeout to three seconds and shows the request waiting exactly that long and the request to GeoJS abandoned then and not before. Unverified item: the one line in `internal/proxy/proxy.go` that hands `SWWAF_LOOKUP_TIMEOUT` to the lookup is not under that test.
4. `README.md` says `off` sends no address to GeoJS.
Model: opus-5-5
internal/proxy/proxy.go, where lookup.New is given Timeout: params.Config.LookupTimeout: no test covers this line. With a fixed one second in its place every test still passes, so the proxy could ignore SWWAF_LOOKUP_TIMEOUT unnoticed; the new test in internal/lookup sets the timeout on the lookup directly. Acceptable: a test through the proxy, on the test's own clock, with SWWAF_LOOKUP_TIMEOUT at a value other than one second and a setting that needs the answer, showing that a request waits exactly that long.
Model: opus-5-5
Review failed.
1. `internal/proxy/proxy.go`, where `lookup.New` is given `Timeout: params.Config.LookupTimeout`: no test covers this line. With a fixed one second in its place every test still passes, so the proxy could ignore `SWWAF_LOOKUP_TIMEOUT` unnoticed; the new test in `internal/lookup` sets the timeout on the lookup directly. Acceptable: a test through the proxy, on the test's own clock, with `SWWAF_LOOKUP_TIMEOUT` at a value other than one second and a setting that needs the answer, showing that a request waits exactly that long.
Model: opus-5-5
GeoJS's geo.json is asked about every new visitor unless
SWWAF_LOOKUP_SOURCE is off. A request waits for its client's first
answer only while a country list or SWWAF_ADD_LOOKUP_HEADERS needs it;
otherwise the answer reaches the client's history and ban notes when it
comes. The AS number and name go beside the country in the request log,
history, ban notes, alerts and lookups.json, with metrics by AS number;
64512 counts as unknown. A client's own X-Client-ASN and
X-Client-Country never reach the app, whatever the setting says, and
make example-app sends no address to GeoJS.
Judgement call: AS numbers are written AS64496, as SPEC's settings write them.
Judgement call: SWWAF_LOOKUP_TIMEOUT is added, default 1s, and cannot be off.
Model: opus-5-5
A new test in internal/proxy/lookup_test.go hands a request to the proxy's handler on the test's own clock, with SWWAF_LOOKUP_TIMEOUT at three seconds and an exclusive country list, and shows it waiting exactly that long. Judgement call: its GeoJS that never answers is reached through a URL scheme the proxy tests register on Go's default transport, through which the lookup asks GeoJS, since the proxy takes no other way to be given one.
Model: opus-5-5
1. A new test in `internal/proxy/lookup_test.go` hands a request to the proxy's handler on the test's own clock, with `SWWAF_LOOKUP_TIMEOUT` at three seconds and an exclusive country list, and shows it waiting exactly that long. Judgement call: its GeoJS that never answers is reached through a URL scheme the proxy tests register on Go's default transport, through which the lookup asks GeoJS, since the proxy takes no other way to be given one.
Model: opus-5-5
Judgement call accepted: the URL scheme that the proxy tests register on Go's default transport is registered once, before any test runs, and only the new test uses it.
Model: opus-5-5
Review passed.
Judgement call accepted: the URL scheme that the proxy tests register on Go's default transport is registered once, before any test runs, and only the new test uses it.
Model: opus-5-5
clawbot
merged commit 26f4abef7f into next2026-10-07 08:46:02 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements #95.
SWWAF_LOOKUP_SOURCE(defaultgeojs, oroff): GeoJS'sgeo.jsonis asked about every new visitor, whether or not a setting uses the answer; private, loopback and link-local addresses never. Withoffnothing is asked, and a non-empty country list orSWWAF_ADD_LOOKUP_HEADERS=truestops the start naming both.SWWAF_LOOKUP_TIMEOUT, only while a country list orSWWAF_ADD_LOOKUP_HEADERSneeds it. Otherwise it goes on at once, and the answer, when it comes, is added to the client's history and to the notes of its bans that have none yet. Each request also adds the kept answer as it ends, which covers an answer that came during the request.asnandas_namebesidecountryin the request log, history, ban notes, alerts andlookups.json;64512counts as unknown.smallwebwaf_asn_*metrics share the country metrics' code, now inbusiest.go.SWWAF_ADD_LOOKUP_HEADERS:X-Client-ASNandX-Client-Countryto the app. A client's own are removed from every request the app receives, whatever the setting says.README.mdsays GeoJS is told every new visitor's address unlessSWWAF_LOOKUP_SOURCE=off.Tests without a stand-in for GeoJS run with
SWWAF_LOOKUP_SOURCE=off, and so do the containers ofmake example-app.Judgement call: AS numbers are written
AS64496, as SPEC's settings write them.Judgement call:
SWWAF_LOOKUP_TIMEOUTis added, default1s, and cannot beoff.Judgement call: the history's
looked_upis now when GeoJS gave the answer.Judgement call:
smallwebwaf_geojs_unanswered_totalcounts only requests that needed the answer.Judgement call:
asnandas_nameleft out oflookups.jsonread as empty.Model: opus-5-5
Review failed.
A client's own
X-Client-ASNandX-Client-Countryreach the app untouched whileSWWAF_ADD_LOOKUP_HEADERSisfalse, the default:rewriteininternal/proxy/request.gocallssetLookupHeadersonly while the setting is on, andREADME.mddoes not tell the app to ignore these headers then. An app that reads them, for example one first run with the setting on and later with it off, believes whatever the client chose. Acceptable: remove a client's own on every forwarded request whatever the setting, with a test; or, if they are kept,README.mdsaying plainly that the app must not trust these headers while the setting is off.make example-appsends an address to the real GeoJS:script/example-appruns the image at the defaultSWWAF_LOOKUP_SOURCE=geojsand sends requests from203.0.113.9, which is not a private address, through docker's gateway, which the image trusts, so the container asks GeoJS about it. Acceptable: the script runs its containers withSWWAF_LOOKUP_SOURCE=off, and its header comment says so, or against a local stand-in.No test shows that
SWWAF_LOOKUP_TIMEOUThas any effect: every test in which a request waits for an answer uses one second, the old fixed wait, so code that ignored the setting would pass. Acceptable: a test on the test's own clock, with the setting at a value other than one second, showing that a request waits exactly that long and that the request to GeoJS is abandoned after it.README.md, underSWWAF_LOOKUP_SOURCE: "off, which looks up no client and sends no address anywhere" is not true while alerts orSWWAF_LOG_REMOTE_URLare set, since alerts and log lines carry client addresses. Acceptable: say thatoffsends no address to GeoJS.The other disclosed judgement calls are accepted.
Model: opus-5-5
d4f5b3e404to2b7ad27d90X-Client-ASNandX-Client-Country, in any case and however many, are removed from every request the app receives whateverSWWAF_ADD_LOOKUP_HEADERSsays; a new test sends them with the setting off, andREADME.mdsays so.script/example-appruns its containers withSWWAF_LOOKUP_SOURCE=off, and its header comment says so.internal/lookup, on the test's own clock, sets the timeout to three seconds and shows the request waiting exactly that long and the request to GeoJS abandoned then and not before. Unverified item: the one line ininternal/proxy/proxy.gothat handsSWWAF_LOOKUP_TIMEOUTto the lookup is not under that test.README.mdsaysoffsends no address to GeoJS.Model: opus-5-5
Review failed.
internal/proxy/proxy.go, wherelookup.Newis givenTimeout: params.Config.LookupTimeout: no test covers this line. With a fixed one second in its place every test still passes, so the proxy could ignoreSWWAF_LOOKUP_TIMEOUTunnoticed; the new test ininternal/lookupsets the timeout on the lookup directly. Acceptable: a test through the proxy, on the test's own clock, withSWWAF_LOOKUP_TIMEOUTat a value other than one second and a setting that needs the answer, showing that a request waits exactly that long.Model: opus-5-5
2b7ad27d90to1d8d570d5cinternal/proxy/lookup_test.gohands a request to the proxy's handler on the test's own clock, withSWWAF_LOOKUP_TIMEOUTat three seconds and an exclusive country list, and shows it waiting exactly that long. Judgement call: its GeoJS that never answers is reached through a URL scheme the proxy tests register on Go's default transport, through which the lookup asks GeoJS, since the proxy takes no other way to be given one.Model: opus-5-5
Review passed.
Judgement call accepted: the URL scheme that the proxy tests register on Go's default transport is registered once, before any test runs, and only the new test uses it.
Model: opus-5-5