A ban's earlier_bans undercounts once a ban after an admin's ban is dropped #128

Open
opened 2026-10-14 18:13:37 +02:00 by clawbot · 0 comments
Collaborator

internal/bans/bans.go, earlierBans with dropOne. earlierBans takes the counts in the notes of the netblock's first ban held as those of the bans dropped before it, then adds one for each ban held. dropOne drops the netblock's earliest ban that is not an admin's. When an admin's ban comes first, the ban dropped is a later one, and its count is lost.

Repro, in the ledger with MaxBans 2:

  1. An admin bans netblock A for a minute.
  2. A breaks a limit twice, each time after its last ban has ended: two bans for a limit.
  3. Netblock B is banned for a limit. The ledger is full, and A's first ban for a limit is dropped.
  4. A breaks a limit again once its second ban for a limit has ended.

The third ban's earlier_bans is {"limit": 1, "admin": 1}, though A had 2 bans for a limit and 1 by an admin before it. A test in internal/bans doing these steps fails with that result.

README, "What it does so far": a ban's notes give "how many bans the netblock had before, for a broken limit, for a clear sign of attack, by an admin and for CrowdSec's decision". earlier_bans in bans.json and in the ban's alert are wrong. Ban lengths do not depend on them.

Severity: minor.

Model: opus-5-5

`internal/bans/bans.go`, `earlierBans` with `dropOne`. `earlierBans` takes the counts in the notes of the netblock's first ban held as those of the bans dropped before it, then adds one for each ban held. `dropOne` drops the netblock's earliest ban that is not an admin's. When an admin's ban comes first, the ban dropped is a later one, and its count is lost. Repro, in the ledger with `MaxBans` 2: 1. An admin bans netblock A for a minute. 2. A breaks a limit twice, each time after its last ban has ended: two bans for a limit. 3. Netblock B is banned for a limit. The ledger is full, and A's first ban for a limit is dropped. 4. A breaks a limit again once its second ban for a limit has ended. The third ban's `earlier_bans` is `{"limit": 1, "admin": 1}`, though A had 2 bans for a limit and 1 by an admin before it. A test in `internal/bans` doing these steps fails with that result. README, "What it does so far": a ban's notes give "how many bans the netblock had before, for a broken limit, for a clear sign of attack, by an admin and for CrowdSec's decision". `earlier_bans` in `bans.json` and in the ban's alert are wrong. Ban lengths do not depend on them. Severity: minor. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/smallwebwaf#128