fix(config): deprecate the report_as field for challenges

This was a bad idea when it was added and it is irresponsible to
continue to have it. It causes more UX problems than it fixes with
slight of hand.

Closes: #1310
Closes: #1307
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso
2025-11-25 22:57:55 -05:00
parent 1f9c2272e6
commit d3b72e3d2d
21 changed files with 26 additions and 42 deletions
-5
View File
@@ -51,7 +51,6 @@ bots:
# action: CHALLENGE # action: CHALLENGE
# challenge: # challenge:
# difficulty: 16 # impossible # difficulty: 16 # impossible
# report_as: 4 # lie to the operator
# algorithm: slow # intentionally waste CPU cycles and time # algorithm: slow # intentionally waste CPU cycles and time
# Requires a subscription to Thoth to use, see # Requires a subscription to Thoth to use, see
@@ -249,7 +248,6 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh # https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh
algorithm: metarefresh algorithm: metarefresh
difficulty: 1 difficulty: 1
report_as: 1
# For clients that are browser-like but have either gained points from custom rules or # For clients that are browser-like but have either gained points from custom rules or
# report as a standard browser. # report as a standard browser.
- name: moderate-suspicion - name: moderate-suspicion
@@ -262,7 +260,6 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work # https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast algorithm: fast
difficulty: 2 # two leading zeros, very fast for most clients difficulty: 2 # two leading zeros, very fast for most clients
report_as: 2
- name: mild-proof-of-work - name: mild-proof-of-work
expression: expression:
all: all:
@@ -273,7 +270,6 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work # https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast algorithm: fast
difficulty: 4 difficulty: 4
report_as: 4
# For clients that are browser like and have gained many points from custom rules # For clients that are browser like and have gained many points from custom rules
- name: extreme-suspicion - name: extreme-suspicion
expression: weight >= 30 expression: weight >= 30
@@ -282,4 +278,3 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work # https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast algorithm: fast
difficulty: 6 difficulty: 6
report_as: 6
-1
View File
@@ -35,7 +35,6 @@
# action: CHALLENGE # action: CHALLENGE
# challenge: # challenge:
# difficulty: 16 # impossible # difficulty: 16 # impossible
# report_as: 4 # lie to the operator
# algorithm: slow # intentionally waste CPU cycles and time # algorithm: slow # intentionally waste CPU cycles and time
# Requires a subscription to Thoth to use, see # Requires a subscription to Thoth to use, see
+21
View File
@@ -25,6 +25,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Stabilize the CVE-2025-24369 regression test by always submitting an invalid proof instead of relying on random POW failures. - Stabilize the CVE-2025-24369 regression test by always submitting an invalid proof instead of relying on random POW failures.
- Add Polish locale ([#1292](https://github.com/TecharoHQ/anubis/pull/1309)) - Add Polish locale ([#1292](https://github.com/TecharoHQ/anubis/pull/1309))
### Deprecate `report_as` in challenge configuration
Previously Anubis let you lie to users about the difficulty of a challenge to interfere with operators of malicious scrapers as a psyops attack:
```yaml
bots:
# Punish any bot with "bot" in the user-agent string
# This is known to have a high false-positive rate, use at your own risk
- name: generic-bot-catchall
user_agent_regex: (?i:bot|crawler)
action: CHALLENGE
challenge:
difficulty: 16 # impossible
report_as: 4 # lie to the operator
algorithm: slow # intentionally waste CPU cycles and time
```
This has turned out to be a bad idea and has been removed.
If you are using this setting, you will get a warning in your logs. To remove this warning, remove this setting from your policy file.
### Logging customization ### Logging customization
Anubis now supports the ability to log to multiple backends ("sinks"). This allows you to have Anubis [log to a file](./admin/policies.mdx#file-sink) instead of just logging to standard out. You can also customize the [logging level](./admin/policies.mdx#log-levels) in the policy file: Anubis now supports the ability to log to multiple backends ("sinks"). This allows you to have Anubis [log to a file](./admin/policies.mdx#file-sink) instead of just logging to standard out. You can also customize the [logging level](./admin/policies.mdx#log-levels) in the policy file:
@@ -12,7 +12,6 @@ To use it in your Anubis configuration:
action: CHALLENGE action: CHALLENGE
challenge: challenge:
difficulty: 1 # Number of seconds to wait before refreshing the page difficulty: 1 # Number of seconds to wait before refreshing the page
report_as: 4 # Unused by this challenge method
algorithm: metarefresh # Specify a non-JS challenge method algorithm: metarefresh # Specify a non-JS challenge method
``` ```
@@ -12,7 +12,6 @@ To use it in your Anubis configuration:
action: CHALLENGE action: CHALLENGE
challenge: challenge:
difficulty: 1 # Number of seconds to wait before refreshing the page difficulty: 1 # Number of seconds to wait before refreshing the page
report_as: 4 # Unused by this challenge method
algorithm: preact algorithm: preact
``` ```
@@ -41,7 +41,6 @@ thresholds:
challenge: challenge:
algorithm: metarefresh algorithm: metarefresh
difficulty: 1 difficulty: 1
report_as: 1
- name: moderate-suspicion - name: moderate-suspicion
expression: expression:
@@ -52,7 +51,6 @@ thresholds:
challenge: challenge:
algorithm: fast algorithm: fast
difficulty: 2 difficulty: 2
report_as: 2
- name: extreme-suspicion - name: extreme-suspicion
expression: weight >= 20 expression: weight >= 20
@@ -60,7 +58,6 @@ thresholds:
challenge: challenge:
algorithm: fast algorithm: fast
difficulty: 4 difficulty: 4
report_as: 4
``` ```
This defines a suite of 4 thresholds: This defines a suite of 4 thresholds:
-2
View File
@@ -84,7 +84,6 @@ This rule has been known to have a high false positive rate in testing. Please u
action: CHALLENGE action: CHALLENGE
challenge: challenge:
difficulty: 16 # impossible difficulty: 16 # impossible
report_as: 4 # lie to the operator
algorithm: slow # intentionally waste CPU cycles and time algorithm: slow # intentionally waste CPU cycles and time
``` ```
@@ -93,7 +92,6 @@ Challenges can be configured with these settings:
| Key | Example | Description | | Key | Example | Description |
| :----------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | | :----------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `difficulty` | `4` | The challenge difficulty (number of leading zeros) for proof-of-work. See [Why does Anubis use Proof-of-Work?](/docs/design/why-proof-of-work) for more details. | | `difficulty` | `4` | The challenge difficulty (number of leading zeros) for proof-of-work. See [Why does Anubis use Proof-of-Work?](/docs/design/why-proof-of-work) for more details. |
| `report_as` | `4` | What difficulty the UI should report to the user. Useful for messing with industrial-scale scraping efforts. |
| `algorithm` | `"fast"` | The challenge method to use. See [the list of challenge methods](./configuration/challenges/) for more information. | | `algorithm` | `"fast"` | The challenge method to use. See [the list of challenge methods](./configuration/challenges/) for more information. |
### Remote IP based filtering ### Remote IP based filtering
@@ -49,7 +49,6 @@ bots:
# action: CHALLENGE # action: CHALLENGE
# challenge: # challenge:
# difficulty: 16 # impossible # difficulty: 16 # impossible
# report_as: 4 # lie to the operator
# algorithm: slow # intentionally waste CPU cycles and time # algorithm: slow # intentionally waste CPU cycles and time
- name: rss-feed-blog - name: rss-feed-blog
@@ -105,7 +104,6 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh # https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh
algorithm: metarefresh algorithm: metarefresh
difficulty: 1 difficulty: 1
report_as: 1
# For clients that are browser-like but have either gained points from custom rules or # For clients that are browser-like but have either gained points from custom rules or
# report as a standard browser. # report as a standard browser.
- name: moderate-suspicion - name: moderate-suspicion
@@ -122,7 +120,6 @@ thresholds:
# challenge data, and forwards that to the client. # challenge data, and forwards that to the client.
algorithm: preact algorithm: preact
difficulty: 1 difficulty: 1
report_as: 1
- name: mild-proof-of-work - name: mild-proof-of-work
expression: expression:
all: all:
@@ -133,7 +130,6 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work # https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast algorithm: fast
difficulty: 2 # two leading zeros, very fast for most clients difficulty: 2 # two leading zeros, very fast for most clients
report_as: 2
# For clients that are browser like and have gained many points from custom rules # For clients that are browser like and have gained many points from custom rules
- name: extreme-suspicion - name: extreme-suspicion
expression: weight >= 30 expression: weight >= 30
@@ -142,7 +138,6 @@ thresholds:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work # https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast algorithm: fast
difficulty: 4 difficulty: 4
report_as: 4
dnsbl: false dnsbl: false
+2 -3
View File
@@ -167,8 +167,8 @@ func (s *Server) hydrateChallengeRule(rule *policy.Bot, chall *challenge.Challen
if rule.Challenge.Difficulty == 0 { if rule.Challenge.Difficulty == 0 {
rule.Challenge.Difficulty = chall.Difficulty rule.Challenge.Difficulty = chall.Difficulty
} }
if rule.Challenge.ReportAs == 0 { if rule.Challenge.ReportAs != 0 {
rule.Challenge.ReportAs = chall.Difficulty s.logger.Warn("[DEPRECATION] the report_as field in this bot rule is deprecated, see https://github.com/TecharoHQ/anubis/issues/1310 for more information", "bot_name", rule.Name, "difficulty", rule.Challenge.Difficulty, "report_as", rule.Challenge.ReportAs)
} }
if rule.Challenge.Algorithm == "" { if rule.Challenge.Algorithm == "" {
rule.Challenge.Algorithm = chall.Method rule.Challenge.Algorithm = chall.Method
@@ -648,7 +648,6 @@ func (s *Server) check(r *http.Request, lg *slog.Logger) (policy.CheckResult, *p
return cr("default/allow", config.RuleAllow, weight), &policy.Bot{ return cr("default/allow", config.RuleAllow, weight), &policy.Bot{
Challenge: &config.ChallengeRules{ Challenge: &config.ChallengeRules{
Difficulty: s.policy.DefaultDifficulty, Difficulty: s.policy.DefaultDifficulty,
ReportAs: s.policy.DefaultDifficulty,
Algorithm: config.DefaultAlgorithm, Algorithm: config.DefaultAlgorithm,
}, },
Rules: &checker.List{}, Rules: &checker.List{},
-4
View File
@@ -464,10 +464,6 @@ func TestCheckDefaultDifficultyMatchesPolicy(t *testing.T) {
if bot.Challenge.Difficulty != i { if bot.Challenge.Difficulty != i {
t.Errorf("Challenge.Difficulty is wrong, wanted %d, got: %d", i, bot.Challenge.Difficulty) t.Errorf("Challenge.Difficulty is wrong, wanted %d, got: %d", i, bot.Challenge.Difficulty)
} }
if bot.Challenge.ReportAs != i {
t.Errorf("Challenge.ReportAs is wrong, wanted %d, got: %d", i, bot.Challenge.ReportAs)
}
}) })
} }
} }
@@ -36,7 +36,6 @@ func TestBasic(t *testing.T) {
Challenge: &config.ChallengeRules{ Challenge: &config.ChallengeRules{
Algorithm: "fast", Algorithm: "fast",
Difficulty: 0, Difficulty: 0,
ReportAs: 0,
}, },
} }
const challengeStr = "hunter" const challengeStr = "hunter"
-3
View File
@@ -110,7 +110,6 @@ func TestBotValid(t *testing.T) {
PathRegex: p("Mozilla"), PathRegex: p("Mozilla"),
Challenge: &ChallengeRules{ Challenge: &ChallengeRules{
Difficulty: -1, Difficulty: -1,
ReportAs: 4,
Algorithm: "fast", Algorithm: "fast",
}, },
}, },
@@ -124,7 +123,6 @@ func TestBotValid(t *testing.T) {
PathRegex: p("Mozilla"), PathRegex: p("Mozilla"),
Challenge: &ChallengeRules{ Challenge: &ChallengeRules{
Difficulty: 420, Difficulty: 420,
ReportAs: 4,
Algorithm: "fast", Algorithm: "fast",
}, },
}, },
@@ -361,7 +359,6 @@ func TestBotConfigZero(t *testing.T) {
b.Challenge = &ChallengeRules{ b.Challenge = &ChallengeRules{
Difficulty: 4, Difficulty: 4,
ReportAs: 4,
Algorithm: DefaultAlgorithm, Algorithm: DefaultAlgorithm,
} }
if b.Zero() { if b.Zero() {
-3
View File
@@ -18,7 +18,6 @@ thresholds:
challenge: challenge:
algorithm: metarefresh algorithm: metarefresh
difficulty: 1 difficulty: 1
report_as: 1
- name: moderate-suspicion - name: moderate-suspicion
expression: expression:
all: all:
@@ -28,11 +27,9 @@ thresholds:
challenge: challenge:
algorithm: fast algorithm: fast
difficulty: 2 difficulty: 2
report_as: 2
- name: extreme-suspicion - name: extreme-suspicion
expression: weight >= 20 expression: weight >= 20
action: CHALLENGE action: CHALLENGE
challenge: challenge:
algorithm: fast algorithm: fast
difficulty: 4 difficulty: 4
report_as: 4
-1
View File
@@ -24,7 +24,6 @@ var (
Challenge: &ChallengeRules{ Challenge: &ChallengeRules{
Algorithm: "fast", Algorithm: "fast",
Difficulty: anubis.DefaultDifficulty, Difficulty: anubis.DefaultDifficulty,
ReportAs: anubis.DefaultDifficulty,
}, },
}, },
} }
-1
View File
@@ -32,7 +32,6 @@ func TestThresholdValid(t *testing.T) {
Challenge: &ChallengeRules{ Challenge: &ChallengeRules{
Algorithm: "fast", Algorithm: "fast",
Difficulty: 1, Difficulty: 1,
ReportAs: 1,
}, },
}, },
err: nil, err: nil,
-1
View File
@@ -145,7 +145,6 @@ func ParseConfig(ctx context.Context, fin io.Reader, fname string, defaultDiffic
if b.Challenge == nil { if b.Challenge == nil {
parsedBot.Challenge = &config.ChallengeRules{ parsedBot.Challenge = &config.ChallengeRules{
Difficulty: defaultDifficulty, Difficulty: defaultDifficulty,
ReportAs: defaultDifficulty,
Algorithm: "fast", Algorithm: "fast",
} }
} else { } else {
-1
View File
@@ -4,5 +4,4 @@ bots:
action: CHALLENGE action: CHALLENGE
challenge: challenge:
difficulty: 16 difficulty: 16
report_as: 4
algorithm: hunter2 # invalid algorithm algorithm: hunter2 # invalid algorithm
-1
View File
@@ -42,4 +42,3 @@ thresholds:
challenge: challenge:
algorithm: fast algorithm: fast
difficulty: 1 difficulty: 1
report_as: 1
-1
View File
@@ -42,4 +42,3 @@ thresholds:
challenge: challenge:
algorithm: fast algorithm: fast
difficulty: 0 difficulty: 0
report_as: 0
-1
View File
@@ -4,7 +4,6 @@ bots:
action: CHALLENGE action: CHALLENGE
challenge: challenge:
difficulty: 2 difficulty: 2
report_as: 2
algorithm: fast algorithm: fast
status_codes: status_codes:
+2 -2
View File
@@ -155,7 +155,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
return; return;
} }
status.innerHTML = `${t('calculating_difficulty')} ${rules.report_as}, `; status.innerHTML = `${t('calculating_difficulty')} ${rules.difficulty}, `;
progress.style.display = "inline-block"; progress.style.display = "inline-block";
// the whole text, including "Speed:", as a single node, because some browsers // the whole text, including "Speed:", as a single node, because some browsers
@@ -166,7 +166,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
let lastSpeedUpdate = 0; let lastSpeedUpdate = 0;
let showingApology = false; let showingApology = false;
const likelihood = Math.pow(16, -rules.report_as); const likelihood = Math.pow(16, -rules.difficulty);
try { try {
const t0 = Date.now(); const t0 = Date.now();