Releases: TecharoHQ/anubis
v1.24.0-pre1: Y'shtola Rhul Prerelease 1
Anubis is back and better than ever! Lots of minor fixes with some big ones interspersed.
- Fix panic when validating challenges after privacy-mode browsers strip headers and the follow-up request matches an
ALLOWthreshold. - Expose WEIGHT rule matches as Prometheus metrics.
- Allow more OCI registry clients based on feedback.
- Expose services directory in the embedded
(data)filesystem. - Add Ukrainian locale (#1044).
- Allow Renovate as an OCI registry client.
- Properly handle 4in6 addresses so that IP matching works with those addresses.
- Add support to simple Valkey/Redis cluster mode
- Open Graph passthrough now reuses the configured target Host/SNI/TLS settings, so metadata fetches succeed when the upstream certificate differs from the public domain. (1283)
- Stabilize the CVE-2025-24369 regression test by always submitting an invalid proof instead of relying on random POW failures.
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 psychological attack:
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 timeThis has turned out to be a bad idea because it has caused massive user experience problems and has been removed. If you are using this setting, you will get a warning in your logs like this:
{
"time": "2025-11-25T23:10:31.092201549-05:00",
"level": "WARN",
"source": {
"function": "github.com/TecharoHQ/anubis/lib/policy.ParseConfig",
"file": "/home/xe/code/TecharoHQ/anubis/lib/policy/policy.go",
"line": 201
},
"msg": "use of deprecated report_as setting detected, please remove this from your policy file when possible",
"at": "config-validate",
"name": "mild-suspicion"
}To remove this warning, remove this setting from your policy file.
Logging customization
Anubis now supports the ability to log to multiple backends ("sinks"). This allows you to have Anubis log to a file instead of just logging to standard out. You can also customize the logging level in the policy file:
logging:
level: "warn" # much less verbose logging
sink: file # log to a file
parameters:
file: "./var/anubis.log"
maxBackups: 3 # keep at least 3 old copies
maxBytes: 67108864 # each file can have up to 64 Mi of logs
maxAge: 7 # rotate files out every n days
oldFileTimeFormat: 2006-01-02T15-04-05 # RFC 3339-ish
compress: true # gzip-compress old log files
useLocalTime: false # timezone for rotated files is UTCAdditionally, information about how Anubis uses each logging level has been added to the documentation.
DNS Features
- CEL expressions for:
- FCrDNS checks
- Forward DNS queries
- Reverse DNS queries
arpaReverseIPto transform IPv4/6 addresses into ARPA reverse IP notation.regexSafeto escape regex special characters (useful for includingremoteAddressor headers in regular expressions).
- DNS cache and other optimizations to minimize unnecessary DNS queries.
The DNS cache TTL can be changed in the bots config like this:
dns_ttl:
forward: 600
reverse: 600The default value for both forward and reverse queries is 300 seconds.
The verifyFCrDNS CEL function has two overloads:
(addr)
Simply verifies that the remote side has PTR records pointing to the target address.(addr, ptrPattern)
Verifies that the remote side refers to a specific domain and that this domain points to the target IP.
What's Changed
- feat: Add thai language. by @karorogunso in #900
- Update is.json by @sveinki in #1241
- fix(data/docker-client): allow some more OCI clients through by @Xe in #1258
- fix(data): add services folder to embedded filesystem by @Xe in #1259
- feat(localization): Add Ukrainian language translation by @nykula in #1044
- build(deps): bump the github-actions group with 3 updates by @dependabot[bot] in #1262
- Add Renovate to Docker clients by @DrJosh9000 in #1267
- fix(docs): use node:lts by @Xe in #1274
- fix(run): mark openrc service script as executable by @kouhaidev in #1272
- test: ipv4 in v6 address checking by @SlyEcho in #1271
- (feat) Add cluster support to redis/vaultkey store by @egimbernat in #1276
- feat(lib): expose WEIGH matches as prometheus metrics by @Xe in #1277
- Fix challenge validation panic when follow-up hits ALLOW by @JasonLovesDoggo in #1278
- feat(internal/headers): extend debug logging of X-Forwarded-For middlewares by @DerRockWolf in #1269
- test: Valkey test improvements for testcontainers by @SlyEcho in #1280
- docs: use nginx http2 directive instead of deprecated http2 listen parameter by @kouhaidev in #1251
- perf: field-align struct definitions to cut padding by @JasonLovesDoggo in #1284
- fix(tests): make CVE-2025-24369 regression deterministic by @JasonLovesDoggo in #1285
- build(deps): bump go deps by @JasonLovesDoggo in #1287
- build(deps): bump github.com/testcontainers/testcontainers-go from 0.39.0 to 0.40.0 in the gomod group across 1 directory by @dependabot[bot] in #1288
- test(deps): update dependencies to latest versions by @JasonLovesDoggo in #1289
- build(deps-dev): bump esbuild from 0.25.12 to 0.27.0 in the npm group by @dependabot[bot] in #1260
- fix(ogtags): respect target host/SNI/insecure flags in OG passthrough by @JasonLovesDoggo in #1283
- docs: clarify usage of PUBLIC_URL and REDIRECT_DOMAINS in installatio… by @JasonLovesDoggo in #1286
- feat(store/valkey): Add Redis(R) Sentinel support by @Xe in #1294
- Pass the remote IP to the proxied application by @eXpl0it3r in #1298
- ci: add go mod tidy check workflow by @Xe in #1300
- feat: writing logs to the filesystem with rotation support by @Xe in #1299
- chore: add dependabot cooldown by @Xe in #1302
- add Polish language translation by @bplajzer in #1309
- fix(config): deprecate the report_as field for challenges by @Xe in #1311
- Implement FCrDNS and other DNS features by @btomaev in #1308
- Show how to use subrequest auth with Caddy by @tbodt in #1312
- build(deps): bump actions-hub/kubectl from 1.34.1 to 1.34.2 in the github-actions group by @dependabot[bot] in #1303
- fix: pin Node.js and Go versions in CI configuration files by @JasonLovesDoggo in #1318
- build(deps): bump the github-actions group with 3 updates by @dependabot[bot] in #1317
- build(deps): bump the gomod group with 5 updates by @dependabot[bot] in #1316
New Contributors
- @karorogunso made their first contribution in #900
- @nykula made their first contribution in #1044
- @DrJosh9000 made their first contribution in #1267
- @kouhaidev made their first contribution in #1272
- @egimbernat made their first contribution in #1276
- @DerRockWolf made their first contribution in #1269
- @eXpl0it3r made their first contribution in #1298
- @bplajzer made their first contribution in #1309
- @btomaev made their first contribution in #1308
- @tbodt made their first contribution in #1312
Full Changelog: v1.23.1...v1.24.0-pre1
v1.23.1: Lyse Hext - Echo 1
- Fix
SERVE_ROBOTS_TXTsetting after the double slash fix broke it.
Potentially breaking changes
Remove default Tencent Cloud block rule
v1.23.0 added a default rule to block Tencent Cloud. After an email from their abuse team where they promised to take action to clean up their reputation, I have removed the default block rule. If this network causes you problems, please contact [email protected] and supply the following information:
- Time of abusive requests.
- IP address, User-Agent header, or other unique identifiers that can help the abuse team educate the customer about their misbehaving infrastructure.
- Does the abusive IP address request robots.txt? If not, be sure to include that information.
- A brief description of the impact to your system such as high system load, pages not rendering, or database system crashes. This helps the provider establish the fact that their customer is causing you measurable harm.
- Context as to what your service is, what it does, and why they should care.
Mention that you are using Anubis or BotStopper to protect your services. If they do not respond to you, please contact me as soon as possible.
Docker / OCI registry clients
Anubis v1.23.0 accidentally blocked Docker / OCI registry clients. In order to explicitly allow them, add an import for (data)/clients/docker-client.yaml:
bots:
- import: (data)/meta/default-config.yaml
- import: (data)/clients/docker-client.yamlThis is technically a regression as these clients used to work in Anubis v1.22.0, however it is allowable to make this opt-in as most websites do not expect to be serving Docker / OCI registry client traffic.
What's Changed
- fix: SERVE_ROBOTS_TXT works again by @Xe in #1229
- chore(default-config): remove Tencent Cloud block rule by @Xe in #1227
- feat(blog): a short post on how to file abuse reports by @Xe in #1230
- build(deps-dev): bump the npm group across 1 directory with 3 updates by @dependabot[bot] in #1238
- build(deps): bump github/codeql-action from 4.31.0 to 4.31.2 in the github-actions group by @dependabot[bot] in #1239
- build(deps): bump the gomod group across 1 directory with 18 updates by @dependabot[bot] in #1237
- fix(data): add ruleset to explicitly allow Docker / OCI clients by @Xe in #1253
- ci: add asset build verification workflow by @Xe in #1254
Full Changelog: v1.23.0...v1.23.1
v1.23.0: Lyse Hext
Sorry this took so long, work has been wiping me out. If you know of any companies that are hiring for someone of my skillset, please let me know.
- Add default tencent cloud DENY rule.
- Added
(data)/meta/default-config.yamlfor importing the entire default configuration at once. - Add
-custom-real-ip-headerflag to get the original request IP from a different header thanx-real-ip. - Add
contentLengthvariable to bot expressions. - Add
COOKIE_SAME_SITE_MODEto force anubis cookies SameSite value, and downgrade automatically fromNonetoLaxif cookie is insecure. - Fix lock convoy problem in decaymap (#1103).
- Fix lock convoy problem in bbolt by implementing the actor pattern (#1103).
- Remove bbolt actorify implementation due to causing production issues.
- Document missing environment variables in installation guide:
SLOG_LEVEL,COOKIE_PREFIX,FORCED_LANGUAGE, andTARGET_DISABLE_KEEPALIVE(#1086). - Add validation warning when persistent storage is used without setting signing keys.
- Fixed
robots2policyto properly group consecutive user agents intoany:instead of only processing the last one (#925). - Make the
fastalgorithm prefer purejs when running in an insecure context. - Add the
s3apistorage backend to allow Anubis to use S3 API compatible object storage as its storage backend. - Fix a "stutter" in the cookie name prefix so the auth cookie is named
techaro.lol-anubis-authinstead oftecharo.lol-anubis-auth-auth. - Make
cmd/containerbuildsupport commas for separating elements of the--docker-tagsargument as well as newlines. - Add the
DIFFICULTY_IN_JWToption, which allows one to add thedifficultyfield in the JWT claims which indicates the difficulty of the token (#1063). - Ported the client-side JS to TypeScript to avoid egregious errors in the future.
- Fixes concurrency problems with very old browsers (#1082).
- Randomly use the Refresh header instead of the meta refresh tag in the metarefresh challenge.
- Update OpenRC service to truncate the runtime directory before starting Anubis.
- Make the git client profile more strictly match how the git client behaves.
- Make the default configuration reward users using normal browsers.
- Allow multiple consecutive slashes in a row in application paths (#754).
- Add option to set
targetSNIto special keyword 'auto' to indicate that it should be automatically set to the request Host name (424). - The Preact challenge has been removed from the default configuration. It will be deprecated in the future.
- An open redirect when in subrequest mode has been fixed.
Potentially breaking changes
Multiple checks at once has and-like semantics instead of or-like semantics
Anubis lets you stack multiple checks at once with blocks like this:
name: allow-prometheus
action: ALLOW
user_agent_regex: ^prometheus-probe$
remote_addresses:
- 192.168.2.0/24Previously, this only returned ALLOW if any one of the conditions matched. This behaviour has changed to only return ALLOW if all of the conditions match. I expect this to have some issues with user configs, however this fix is grave enough that it's worth the risk of breaking configs. If this bites you, please let me know so we can make an escape hatch.
Better error messages
In order to make it easier for legitimate clients to debug issues with their browser configuration and Anubis, Anubis will emit internal error detail in base 64 so that administrators can chase down issues. Future versions of this may also include a variant that encrypts the error detail messages.
Bug Fixes
Sometimes the enhanced temporal assurance in #1038 and #1068 could backfire because Chromium and its ilk randomize the amount of time they wait in order to avoid a timing side channel attack. This has been fixed by both increasing the amount of time a client has to wait for the metarefresh and preact challenges as well as making the server side logic more permissive.
What's Changed
- docs(installation): add SLOG_LEVEL environment variable to configuration by @JasonLovesDoggo in #1086
- docs: document some missing env vars by @JasonLovesDoggo in #1087
- build(deps): bump the github-actions group across 1 directory with 8 updates by @dependabot[bot] in #1071
- fix(robots2policy): handle multiple user agents under one block by @JasonLovesDoggo in #925
- feat(lib/store): add s3api storage backend by @Xe in #1089
- Xe/demote temporal assurance by @Xe in #1090
- feat: Warn on missing signing keys when persisting challenges by @JasonLovesDoggo in #1088
- docs: add reminder for verified signatures in PR template by @JasonLovesDoggo in #1092
- build(deps): bump the github-actions group with 4 updates by @dependabot[bot] in #1093
- security: npm audit fix for GHSA-hfm8-9jrf-7g9w et. al by @Xe in #1098
- fix(cmd/containerbuild): support commas in --docker-tags by @Xe in #1099
- feat(lib): Add option for adding difficulty field to JWT claims by @Earl0fPudding in #1063
- chore: port client-side JS to TypeScript by @Xe in #1100
- fix(decaymap): fix lock convoy by @Xe in #1106
- feat(store/bbolt): implement actor pattern by @Xe in #1107
- feat: allow to set cookie sameSite mode and fallback to Lax mode if cookie is not secure by @vaab in #1105
- docs: add link to preact in challenge list by @agoujot in #1111
- ci: add aarch64 for ssh CI by @Xe in #1112
- ci(ssh): don't print uname -av output by @Xe in #1114
- feat(expressions): add contentLength to bot expressions by @Xe in #1120
- fix(run/openrc): truncate runtime directory before starting Anubis by @CyberTailor in #1122
- build(deps): bump the npm group with 2 updates by @dependabot[bot] in #1117
- build(deps): bump the github-actions group with 3 updates by @dependabot[bot] in #1118
- Update nl.json removing literal translated cookie 'koekje' with 'cookie' by @jieter in #1126
- convert issue templates into issue forms by @NetSysFire in #1115
- build(deps): bump github.com/docker/docker from 28.3.2+incompatible to 28.3.3+incompatible in /test by @dependabot[bot] in #1130
- feat(metarefresh): randomly use the Refresh header by @Xe in #1133
- Add Door43 link to known instances documentation by @richmahn in #1136
- fix: mend auth cookie name stutter by @Xe in #1139
- Update Nynorsk translation by @turtlegarden in #1143
- feat: support reading real client IP from a custom header by @avioletheart in #1138
- enable auto setting of SNI based on host header by @jmcclelland in #1129
- fix(lib): enable multiple consecutive slash support by @Xe in #1155
- build(deps-dev): bump esbuild from 0.25.9 to 0.25.10 in the npm group by @dependabot[bot] in #1147
- build(deps): bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 by @dependabot[bot] in #1132
- build(deps): bump github.com/docker/docker from 28.3.2+incompatible to 28.3.3+incompatible by @dependabot[bot] in #1131
- fix(lib): serve CSS properly by @Xe in #1158
- fix(default-config): make the default config far less paranoid by @Xe in #1179
- fix(default-config): remove preact challenge by @Xe in #1184
- feat: default config macro by @Xe in #1186
- fix(lib): de-flake package lib tests by @Xe in #1187
- Updated REDIRECT_DOMAINS documentation by @zc-devs in #1171
- fix(default-config): sometimes browsers don't send Upgrade-Insecure-Requests by @Xe in #1189
- fix(algorithms/fast): fix fast challenge on insecure contexts by @Xe in #1198
- Xe/show error state by @Xe in #1203
- locale: Update Nynorsk translation by @turtlegarden in #1204
- docs: point get s...
v1.23.0-pre2: Lyse Hext
What's Changed
- docs: point get started button to the per-environment setup docs by @Xe in #1213
- fix(store/bbolt): remove actorify by @Xe in #1215
- feat(default-config): block tencent cloud by default by @Xe in #1216
- link to docs site from readme by @pushcx in #1214
- fix!(policy/checker): make List and-like by @Xe in #1217
- chore: remove copilot instructions by @Xe in #1218
New Contributors
Full Changelog: v1.23.0-pre1...v1.23.0-pre2
v1.23.0-pre1: Lyse Hext
- Added
(data)/meta/default-config.yamlfor importing the entire default configuration at once. - Add
-custom-real-ip-headerflag to get the original request IP from a different header thanx-real-ip. - Add
contentLengthvariable to bot expressions. - Add
COOKIE_SAME_SITE_MODEto force anubis cookies SameSite value, and downgrade automatically fromNonetoLaxif cookie is insecure. - Fix lock convoy problem in decaymap (#1103).
- Fix lock convoy problem in bbolt by implementing the actor pattern (#1103).
- Document missing environment variables in installation guide:
SLOG_LEVEL,COOKIE_PREFIX,FORCED_LANGUAGE, andTARGET_DISABLE_KEEPALIVE(#1086). - Add validation warning when persistent storage is used without setting signing keys.
- Fixed
robots2policyto properly group consecutive user agents intoany:instead of only processing the last one (#925). - Make the
fastalgorithm prefer purejs when running in an insecure context. - Add the
s3apistorage backend to allow Anubis to use S3 API compatible object storage as its storage backend. - Fix a "stutter" in the cookie name prefix so the auth cookie is named
techaro.lol-anubis-authinstead oftecharo.lol-anubis-auth-auth. - Make
cmd/containerbuildsupport commas for separating elements of the--docker-tagsargument as well as newlines. - Add the
DIFFICULTY_IN_JWToption, which allows one to add thedifficultyfield in the JWT claims which indicates the difficulty of the token (#1063). - Ported the client-side JS to TypeScript to avoid egregious errors in the future.
- Fixes concurrency problems with very old browsers (#1082).
- Randomly use the Refresh header instead of the meta refresh tag in the metarefresh challenge.
- Update OpenRC service to truncate the runtime directory before starting Anubis.
- Make the git client profile more strictly match how the git client behaves.
- Make the default configuration reward users using normal browsers.
- Allow multiple consecutive slashes in a row in application paths (#754).
- Add option to set
targetSNIto special keyword 'auto' to indicate that it should be automatically set to the request Host name (424). - The Preact challenge has been removed from the default configuration. It will be deprecated in the future.
Better error messages
In order to make it easier for legitimate clients to debug issues with their browser configuration and Anubis, Anubis will emit internal error detail in base 64 so that administrators can chase down issues. Future versions of this may also include a variant that encrypts the error detail messages.
Bug Fixes
Sometimes the enhanced temporal assurance in #1038 and #1068 could backfire because Chromium and its ilk randomize the amount of time they wait in order to avoid a timing side channel attack. This has been fixed by both increasing the amount of time a client has to wait for the metarefresh and preact challenges as well as making the server side logic more permissive.
What's Changed
- docs(installation): add SLOG_LEVEL environment variable to configuration by @JasonLovesDoggo in #1086
- docs: document some missing env vars by @JasonLovesDoggo in #1087
- build(deps): bump the github-actions group across 1 directory with 8 updates by @dependabot[bot] in #1071
- fix(robots2policy): handle multiple user agents under one block by @JasonLovesDoggo in #925
- feat(lib/store): add s3api storage backend by @Xe in #1089
- Xe/demote temporal assurance by @Xe in #1090
- feat: Warn on missing signing keys when persisting challenges by @JasonLovesDoggo in #1088
- docs: add reminder for verified signatures in PR template by @JasonLovesDoggo in #1092
- build(deps): bump the github-actions group with 4 updates by @dependabot[bot] in #1093
- security: npm audit fix for GHSA-hfm8-9jrf-7g9w et. al by @Xe in #1098
- fix(cmd/containerbuild): support commas in --docker-tags by @Xe in #1099
- feat(lib): Add option for adding difficulty field to JWT claims by @Earl0fPudding in #1063
- chore: port client-side JS to TypeScript by @Xe in #1100
- fix(decaymap): fix lock convoy by @Xe in #1106
- feat(store/bbolt): implement actor pattern by @Xe in #1107
- feat: allow to set cookie sameSite mode and fallback to Lax mode if cookie is not secure by @vaab in #1105
- docs: add link to preact in challenge list by @agoujot in #1111
- ci: add aarch64 for ssh CI by @Xe in #1112
- ci(ssh): don't print uname -av output by @Xe in #1114
- feat(expressions): add contentLength to bot expressions by @Xe in #1120
- fix(run/openrc): truncate runtime directory before starting Anubis by @CyberTailor in #1122
- build(deps): bump the npm group with 2 updates by @dependabot[bot] in #1117
- build(deps): bump the github-actions group with 3 updates by @dependabot[bot] in #1118
- Update nl.json removing literal translated cookie 'koekje' with 'cookie' by @jieter in #1126
- convert issue templates into issue forms by @NetSysFire in #1115
- build(deps): bump github.com/docker/docker from 28.3.2+incompatible to 28.3.3+incompatible in /test by @dependabot[bot] in #1130
- feat(metarefresh): randomly use the Refresh header by @Xe in #1133
- Add Door43 link to known instances documentation by @richmahn in #1136
- fix: mend auth cookie name stutter by @Xe in #1139
- Update Nynorsk translation by @turtlegarden in #1143
- feat: support reading real client IP from a custom header by @avioletheart in #1138
- enable auto setting of SNI based on host header by @jmcclelland in #1129
- fix(lib): enable multiple consecutive slash support by @Xe in #1155
- build(deps-dev): bump esbuild from 0.25.9 to 0.25.10 in the npm group by @dependabot[bot] in #1147
- build(deps): bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 by @dependabot[bot] in #1132
- build(deps): bump github.com/docker/docker from 28.3.2+incompatible to 28.3.3+incompatible by @dependabot[bot] in #1131
- fix(lib): serve CSS properly by @Xe in #1158
- fix(default-config): make the default config far less paranoid by @Xe in #1179
- fix(default-config): remove preact challenge by @Xe in #1184
- feat: default config macro by @Xe in #1186
- fix(lib): de-flake package lib tests by @Xe in #1187
- Updated REDIRECT_DOMAINS documentation by @zc-devs in #1171
- fix(default-config): sometimes browsers don't send Upgrade-Insecure-Requests by @Xe in #1189
- fix(algorithms/fast): fix fast challenge on insecure contexts by @Xe in #1198
- Xe/show error state by @Xe in #1203
- locale: Update Nynorsk translation by @turtlegarden in #1204
New Contributors
- @vaab made their first contribution in #1105
- @agoujot made their first contribution in #1111
- @NetSysFire made their first contribution in #1115
- @richmahn made their first contribution in #1136
- @avioletheart made their first contribution in #1138
- @jmcclelland made their first contribution in #1129
- @zc-devs made their first contribution in #1171
Full Changelog: v1.22.0...v1.23.0-pre1
v1.22.0: Yda Hext
Someone has to make an effort at reconciliation if these conflicts are ever going to end.
In this release, we finally fix the odd number of CPU cores bug, pave the way for lighter weight challenges, make Anubis more adaptable, and more.
Big ticket items
Proof of React challenge
A new "proof of React" has been added. It runs a simple app in React that has several chained hooks. It is much more lightweight than the proof of work check.
Smaller features
- The
segmentsfunction was added for splitting a path into its slash-separated segments. - Added possibility to disable HTTP keep-alive to support backends not properly handling it.
- When issuing a challenge, Anubis stores information about that challenge into the store. That stored information is later used to validate challenge responses. This works around nondeterminism in bot rules. (#917)
- One of the biggest sources of lag in Firefox has been eliminated: the use of WebCrypto. Now whenever Anubis detects the client is using Firefox (or Pale Moon), it will swap over to a pure-JS implementation of SHA-256 for speed.
- Proof of work solving has had a complete overhaul and rethink based on feedback from browser engine developers, frontend experts, and overall performance profiling.
- Optimize the performance of the pure-JS Anubis solver.
- Web Workers are stored as dedicated JavaScript files in
static/js/workers/*.mjs. - Pave the way for non-SHA256 solver methods and eventually one that uses WebAssembly (or WebAssembly code compiled to JS for those that disable WebAssembly).
- Legacy JavaScript code has been eliminated.
- When parsing Open Graph tags, add any URLs found in the responses to a temporary "allow cache" so that social preview images work.
- The hard dependency on WebCrypto has been removed, allowing a proof of work challenge to work over plain (unencrypted) HTTP.
- The Anubis version number is put in the footer of every page.
- Add a default block rule for Huawei Cloud.
- Add a default block rule for Alibaba Cloud.
- Added support to use Traefik forwardAuth middleware.
- Add X-Request-URI support so that Subrequest Authentication has path support.
Fixes
Odd numbers of CPU cores are properly supported
Some phones have an odd number of CPU cores. This caused interesting issues. This was fixed by using Math.trunc to convert the number of CPU cores back into an integer.
Smaller fixes
- A standard library HTTP server log message about HTTP pipelining not working has been filtered out of Anubis' logs. There is no action that can be taken about it.
- Added a missing link to the Caddy installation environment in the installation documentation.
- Downstream consumers can change the default log/slog#Logger instance that Anubis uses by setting
opts.Loggerto your slog instance of choice (#864). - The Thoth client is now public in the repo instead of being an internal package.
- Custom-AsyncHttpClient's default User-Agent has an increased weight by default (#852).
- Add option for replacing the default explanation text with a custom one (#747)
- The contact email in the LibreJS header has been changed.
- Firefox for Android support has been fixed by embedding the challenge ID into the pass-challenge route. This also fixes some inconsistent issues with other mobile browsers.
- The default
faviconpattern indata/common/keep-internet-working.yamlhas been updated to permit requests for png/gif/jpg/svg files as well as ico. - The
--cookie-prefixflag has been fixed so that it is fully respected. - The default patterns in
data/common/keep-internet-working.yamlhave been updated to appropriately escape the '.' character in the regular expression patterns. - Add optional restrictions for JWT based on the value of a header (#697)
- The word "hack" has been removed from the translation strings for Anubis due to incidents involving people misunderstanding that word and sending particularly horrible things to the project lead over email.
- Bump AI-robots.txt to version 1.39
- Inject adversarial input to break AI coding assistants.
- Add better logging when using Subrequest Authentication.
Security-relevant changes
- Add a server-side check for the meta-refresh challenge that makes sure clients have waited for at least 95% of the time that they should.
Fix potential double-spend for challenges
Anubis operates by issuing a challenge and having the client present a solution for that challenge. Challenges are identified by a unique UUID, which is stored in the database.
The problem is that a challenge could potentially be used twice by a dedicated attacker making a targeted attack against Anubis. Challenge records did not have a "spent" or "used" field. In total, a dedicated attacker could solve a challenge once and reuse that solution across multiple sessions in order to mint additional tokens.
This was fixed by adding a "spent" field to challenges in the data store. When a challenge is solved, that "spent" field gets set to true. If a future attempt to solve this challenge is observed, it gets rejected.
With the advent of store based challenge issuance in #749, this means that these challenge IDs are only good for 30 minutes. Websites using the most recent version of Anubis have limited exposure to this problem.
Websites using older versions of Anubis have a much more increased exposure to this problem and are encouraged to keep this software updated as often and as frequently as possible.
Thanks to @taviso for reporting this issue.
Breaking changes
- The "slow" frontend solver has been removed in order to reduce maintenance burden. Any existing uses of it will still work, but issue a warning upon startup asking administrators to upgrade to the "fast" frontend solver.
- The legacy JSON based policy file example has been removed and all documentation for how to write a policy file in JSON has been deleted. JSON based policy files will still work, but YAML is the superior option for Anubis configuration.
New Locales
What's Changed
- build(deps): bump on-headers and compression in /docs by @dependabot[bot] in #910
- chore: expose thoth in lib by @Xe in #911
- test(lib): add a test for the X-Forwarded-For middleware by @Xe in #912
- build(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /docs by @dependabot[bot] in #909
- test: add automated Pale Moon tests by @Xe in #903
- feat(expressions): add segments function to break path into segments by @Xe in #916
- feat(default-rules): add weight to Custom-AsyncHttpClient by @Xe in #914
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #929
- fix(anubis): store the challenge method in the store by @Xe in #924
- build(deps): bump the gomod group in #931
- Update is.json by @sveinki in #935
- fix: polish Turkish translations by @bitigchi in #897
- fix(lib): add the ability to set a custom slog Logger by @Xe in #915
- fix: allow social preview images by @Xe in #934
- refactor(web): redo proof of work web worker logic by @Xe in #941
- Add HackLab.TO to known instances by @lillian-b in #936
- fix(web/sha256-browserjs): fix function name by @Xe in #943
- Add swedish local by @axellse in #913
- docs: remove JSON examples from policy file docs by @Xe in #945
- fix(internal): silence unsolicited response log lines by @Xe in #950
- fix(web): embed challenge ID in pass-challenge invocations by @Xe in #944
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #952
- Revert "build(deps): bump the github-actions group with 2 updates" by @JasonLovesDoggo in #962
- Fix capitalisation in bokmål and nynorsk translations by @turtlegarden in #959
- Added Dutch translation by @SecularSteve in #937
- fix(localization): Improve Czech language translation by @Medvidek77 in #895
- feat(checker): allow png/gif/jpg/jpeg...
v1.22.0-pre2: Yda Hext
Full release notes will be written later. This prerelease is meant to help test the new features. Read the changelog for a comprehensive list of changes. It's a lot.
Please file bugs if you encounter issues.
If no major issues are found in the next few days, this ships.
What's Changed
- s/Wordpress/WordPress in docs by @bradp in #1020
- docs: fix "stored" typo in CHANGELOG.md by @Krinkle in #1008
- lib/checker: Implement X-Original-URI support by @samip5 in #1015
- Add XOriginal to allowed words by @JasonLovesDoggo in #1031
- build(deps-dev): bump the npm group across 1 directory with 3 updates by @dependabot[bot] in #1032
- fix(worker): constrain nonce value to be a whole integer by @Xe in #1045
- fix: middleware traefik redirect url by @phoval in #1040
- docs(blog): add post about the odd CPU core count bug by @Xe in #1058
- docs: Fix broken link by @phuzion in #1059
- Allow to disable keep-alive for the targets not supporting it properly by @samm-git in #1049
- Alienbob: add Slackware URLs that are now protected by Anubis by @alienbob in #1051
- docs: document client IP headers and interop with cloudflare by @TinyServal in #1034
- Update nginx.mdx - needs port_in_redirect off setting by @own3mall in #1018
- internal/log: Implement logging of HOST when using subrequest auth by @samip5 in #1027
- feat: add 'proof of React' challenge by @Xe in #1038
- add Lithuanian locale by @rimas-kudelis in #998
- chore: introduce issue templates by @Xe in #939
- feat(localization): Add Vietnamese translation by @ninfia in #926
- fix(challenge/metarefresh): ensure that clients have waited long enough by @Xe in #1068
- ci: fix tests by @Xe in #1069
- chore: break AI agents in this code tree by @Xe in #1065
New Contributors
- @bradp made their first contribution in #1020
- @Krinkle made their first contribution in #1008
- @samip5 made their first contribution in #1015
- @phuzion made their first contribution in #1059
- @samm-git made their first contribution in #1049
- @alienbob made their first contribution in #1051
- @TinyServal made their first contribution in #1034
- @own3mall made their first contribution in #1018
- @ninfia made their first contribution in #926
Full Changelog: v1.22.0-pre1...v1.22.0-pre2
v1.22.0-pre1: Yda Hext
Full release notes will be written later. This prerelease is meant to help test the new features. Read the changelog for a comprehensive list of changes. It's a lot.
Please file bugs if you encounter issues.
What's Changed
- build(deps): bump on-headers and compression in /docs by @dependabot[bot] in #910
- chore: expose thoth in lib by @Xe in #911
- test(lib): add a test for the X-Forwarded-For middleware by @Xe in #912
- build(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /docs by @dependabot[bot] in #909
- test: add automated Pale Moon tests by @Xe in #903
- feat(expressions): add segments function to break path into segments by @Xe in #916
- feat(default-rules): add weight to Custom-AsyncHttpClient by @Xe in #914
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #929
- fix(anubis): store the challenge method in the store by @Xe in #924
- build(deps): bump the gomod group in #931
- Update is.json by @sveinki in #935
- fix: polish Turkish translations by @bitigchi in #897
- fix(lib): add the ability to set a custom slog Logger by @Xe in #915
- fix: allow social preview images by @Xe in #934
- refactor(web): redo proof of work web worker logic by @Xe in #941
- Add HackLab.TO to known instances by @lillian-b in #936
- fix(web/sha256-browserjs): fix function name by @Xe in #943
- Add swedish local by @axellse in #913
- docs: remove JSON examples from policy file docs by @Xe in #945
- fix(internal): silence unsolicited response log lines by @Xe in #950
- fix(web): embed challenge ID in pass-challenge invocations by @Xe in #944
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #952
- Revert "build(deps): bump the github-actions group with 2 updates" by @JasonLovesDoggo in #962
- Fix capitalisation in bokmål and nynorsk translations by @turtlegarden in #959
- Added Dutch translation by @SecularSteve in #937
- fix(localization): Improve Czech language translation by @Medvidek77 in #895
- feat(checker): allow png/gif/jpg/jpeg/svg favicons as well as ico by @arcayr in #961
- default pattern fixes by @arcayr in #963
- feat: support HTTP redirect for forward authentication middleware in Traefik by @phoval in #368
- Update known-instances.md: add lab.civicrm.org by @mlutfy in #971
- feat(lib): Add optional restrictions for JWT based on a specific header value by @Earl0fPudding in #697
- add Lithuanian locale by @rimas-kudelis in #972
- fix(locales): remove the word "hack" from the description of Anubis by @Xe in #973
- feat(web): Add option for customizable explanation text by @Earl0fPudding in #747
- Bump ai.robots.txt to v1.39 by @Dryusdan in #982
- feat(blog): add short funding update post by @Xe in #994
- fix(lib): ensure issued challenges don't get double-spent by @Xe in #1003
- fix(default-config): block Huawei Cloud by @Xe in #1004
- fix(default-config): also block alibaba cloud by @Xe in #1005
- Update installation.mdx to include a link to the Caddy docs by @juliankrieger in #993
New Contributors
- @bitigchi made their first contribution in #897
- @lillian-b made their first contribution in #936
- @axellse made their first contribution in #913
- @SecularSteve made their first contribution in #937
- @Medvidek77 made their first contribution in #895
- @arcayr made their first contribution in #961
- @phoval made their first contribution in #368
- @mlutfy made their first contribution in #971
- @rimas-kudelis made their first contribution in #972
- @juliankrieger made their first contribution in #993
Full Changelog: v1.21.3...v1.22.0-pre1
v1.21.3: Minfilia Warde - Echo 3
Fixes GHSA-jhjj-2g64-px7c
This could allow an attacker to craft an Anubis pass-challenge URL that forces a redirect to nonstandard URLs, such as the javascript: scheme which executes arbitrary JavaScript code in a browser context when the user clicks the "Try again" button.
This has been fixed by disallowing any URLs without the scheme http or https.
Additionally, the "Try again" button has been fixed to completely ignore the user-supplied redirect location. It now redirects to the home page (/).
Notes
An incomplete version of this fix was tagged at v1.21.2 and then the release process was aborted upon final testing. Do not package or use v1.21.2.
What's Changed
- fix(lib): add comprehensive XSS protection logic by @Xe in #905
- fix(web): make the try again button always go back to / by @Xe in #907
Full Changelog: v1.21.2...v1.21.3
v1.21.1: Minfilia Warde - Echo 1
- Expired records are now properly removed from bbolt databases (#848).
- Fix hanging on service restart (#853)
Added
Anubis now supports the missingHeader to assert the absence of headers in requests.
New locales
Anubis now supports these new languages:
Fixes
Fix "error: can't get challenge" when details about a challenge can't be found in the server side state
v1.21.0 changed the core challenge flow to maintain information about challenges on the server side instead of only doing them via stateless idempotent generation functions and relying on details to not change. There was a subtle bug introduced in this change: if a client has an unknown challenge ID set in its test cookie, Anubis will clear that cookie and then throw an HTTP 500 error.
This has been fixed by making Anubis throw a new challenge page instead.
Fix event loop thrashing when solving a proof of work challenge
Previously the "fast" proof of work solver had a fragment of JavaScript that attempted to only post an update about proof of work progress to the main browser window every 1024 iterations. This fragment of JavaScript was subtly incorrect in a way that passed review but actually made the workers send an update back to the main thread every iteration. This caused a pileup of unhandled async calls (similar to a socket accept() backlog pileup in Unix) that caused stack space exhaustion.
This has been fixed in the following ways:
- The complicated boolean logic has been totally removed in favour of a worker-local iteration counter.
- The progress bar is updated by worker
0instead of all workers.
Hopefully this should limit the event loop thrashing and let ia32 browsers (as well as any environment with a smaller stack size than amd64 and aarch64 seem to have) function normally when processing Anubis proof of work challenges.
Fix potential memory leak when discovering a solution
In some cases, the parallel solution finder in Anubis could cause all of the worker promises to leak due to the fact the promises were being improperly terminated. This was fixed by having Anubis debounce worker termination instead of allowing it to potentially recurse infinitely.
What's Changed
- docs(known-instances): update list of known instances by @lotharsm in #847
- fix(cmd/anubis): add signal handling to metrics server by @EmRowlands in #856
- test: add i18n smoke test by @Xe in #858
- test(ssh-ci): deflake SSH CI with exponential backoff by @Xe in #859
- Fix broken BBolt database cleanup process by @thenickdude in #848
- fix(localization): untranslated string in Filipino language by @hankskyjames777 in #850
- feat(localization): Add Czech language translation by @xmorave2 in #849
- feat(expressions): add missingHeader function to bot environment by @Xe in #870
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #871
- build(deps-dev): bump the npm group with 3 updates by @dependabot[bot] in #872
- build(deps): bump the gomod group with 6 updates by @dependabot[bot] in #873
- Revert "build(deps): bump the gomod group with 6 updates" by @JasonLovesDoggo in #874
- Remove duplicated string in Filipino language file by @searinminecraft in #875
- fix(web): amend future leak on proof of work solution by @Xe in #879
- fix(web/fast): remove event loop thrashing by @Xe in #880
- Update pt-BR.json by @HQuest in #878
- fix(lib): fix challenge issuance logic by @Xe in #881
- Add Finnish localization by @ZerionSeven in #863
- feat: Russian localization for Anubis by @Xe in #882
- feat(localization): Add in Bokmål and Nynorsk translations by @turtlegarden in #855
- chore: release v1.21.1 by @Xe in #887
New Contributors
- @EmRowlands made their first contribution in #856
- @thenickdude made their first contribution in #848
- @hankskyjames777 made their first contribution in #850
- @xmorave2 made their first contribution in #849
- @HQuest made their first contribution in #878
- @ZerionSeven made their first contribution in #863
- @turtlegarden made their first contribution in #855
Full Changelog: v1.21.0...v1.21.1