Releases: TecharoHQ/anubis
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
v1.21.0: Minfilia Warde
Please, be at ease. You are among friends here.
In this release, Anubis becomes internationalized, gains the ability to use system load as input to issuing challenges, finally fixes the "invalid response" after "success" bug, and more! Please read these notes before upgrading as the changes are big enough that administrators should take action to ensure that the upgrade goes smoothly.
This release is brought to you by FreeCAD, an open-source computer aided design tool that lets you design things for the real world.
Big ticket changes
The biggest change is that the "invalid response" after "success" bug is now finally fixed for good by totally rewriting how Anubis' challenge issuance flow works. Instead of generating challenge strings from request metadata (under the assumption that the values being compared against are stable), Anubis now generates random data for each challenge. This data is stored in the active storage backend for up to 30 minutes. This also fixes #746 and other similar instances of this issue.
In order to reduce confusion, the "Success" interstitial that shows up when you pass a proof of work challenge has been removed.
Storage
Anubis now is able to store things persistently in memory, on the disk, or in Valkey (this includes other compatible software). By default Anubis uses the in-memory backend. If you have an environment with mutable storage (even if it is temporary), be sure to configure the bbolt storage backend.
Localization
Anubis now supports localized responses. Locales can be added in lib/localization/locales/. This release includes support for the following languages:
- Brazilian Portugese
- Chinese (Simplified)
- Chinese (Traditional)
- English
- Estonian
- Filipino
- French
- German
- Icelandic
- Italian
- Japanese
- Spanish
- Turkish
If facts or local regulations demand, you can set Anubis default language with the FORCED_LANGUAGE environment variable or the --forced-language command line argument:
FORCED_LANGUAGE=deLoad average
Anubis can dynamically take action based on the system load average, allowing you to write rules like this:
## System load based checks.
# If the system is under high load for the last minute, add weight.
- name: high-load-average
action: WEIGH
expression: load_1m >= 10.0 # make sure to end the load comparison in a .0
weight:
adjust: 20
# If it is not for the last 15 minutes, remove weight.
- name: low-load-average
action: WEIGH
expression: load_15m <= 4.0 # make sure to end the load comparison in a .0
weight:
adjust: -10Something to keep in mind about system load average is that it is not aware of the number of cores the system has. If you have a 16 core system that has 16 processes running but none of them is hogging the CPU, then you will get a load average below 16. If you are in doubt, make your "high load" metric at least two times the number of CPU cores and your "low load" metric at least half of the number of CPU cores. For example:
| Kind | Core count | Load threshold |
|---|---|---|
| high load | 4 | 8.0 |
| low load | 4 | 2.0 |
| high load | 16 | 32.0 |
| low load | 16 | 8 |
Also keep in mind that this does not account for other kinds of latency like I/O latency. A system can have its web applications unresponsive due to high latency from a MySQL server but still have that web application server report a load near or at zero.
Other features and fixes
There are a bunch of other assorted features and fixes too:
- Add
COOKIE_SECUREoption to set the cookie Secure flag - Sets cookie defaults to use SameSite: None
- Determine the
BIND_NETWORK/--bind-networkvalue from the bind address (#677). - Implement a development container manifest to make contributions easier.
- Fix dynamic cookie domains functionality (#731)
- Add option for custom cookie prefix (#732)
- Make the Open Graph subsystem and DNSBL subsystem use storage backends instead of storing everything in memory by default.
- Allow Common Crawl by default so scrapers have less incentive to scrape
- The bbolt storage backend now runs its cleanup every hour instead of every five minutes.
- Don't block Anubis starting up if Thoth health checks fail.
- A race condition involving opening two challenge pages at once in different tabs causing one of them to fail has been fixed.
- The "Try again" button on the error page has been fixed. Previously it meant "try the solution again" instead of "try the challenge again".
- In certain cases, a user could be stuck with a test cookie that is invalid, locking them out of the service for up to half an hour. This has been fixed with better validation of this case and clearing the cookie.
- Start exposing JA4H fingerprints for later use in CEL expressions.
- Add
/healthzroute for use in platform-based health checks.
Potentially breaking changes
We try to introduce breaking changes as much as possible, but these are the changes that may be relevant for you as an administrator:
Challenge format change
Previously Anubis did no accounting for challenges that it issued. This means that if Anubis restarted during a client, the client would be able to proceed once Anubis came back online.
During the upgrade to v1.21.0 and when v1.21.0 (or later) restarts with the in-memory storage backend, you may see a higher rate of failed challenges than normal. If this persists beyond a few minutes, open an issue.
If you are using the in-memory storage backend, please consider using a different storage backend.
Systemd service changes
The following potentially breaking change applies to native installs with systemd only:
Each instance of systemd service template now has a unique RuntimeDirectory, as opposed to each instance of the service sharing a RuntimeDirectory. This change was made to avoid the RuntimeDirectory getting nuked any time one of the Anubis instances restarts.
If you configured Anubis' unix sockets to listen on /run/anubis/foo.sock for instance anubis@foo, you will need to configure Anubis to listen on /run/anubis/foo/foo.sock and additionally configure your HTTP load balancer as appropriate.
If you need the legacy behaviour, install this systemd unit dropin:
# /etc/systemd/system/anubis@.service.d/50-runtimedir.conf
[Service]
RuntimeDirectory=anubis
Just keep in mind that this will cause problems when Anubis restarts.
What's Changed
- feat: implement localization system by @lolgzs in #716
- fix: determine bind network from bind address by @littlecxm in #714
- Add Brazilian Portuguese translation by @rffontenelle in #726
- fix: Dynamic cookie domain not working by @Earl0fPudding in #731
- feat(cmd): Add custom cookie prefix by @Earl0fPudding in #732
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #735
- build(deps): bump the gomod group with 2 updates by @dependabot[bot] in #736
- feat: dev container support by @Xe in #734
- Fix translations in pt-BR.json by @rffontenelle in #729
- Set cookies to have the Secure flag default to true by @victorvalenca in #739
- fix(web/main): remove the success interstitial by @Xe in #745
- feat(localization): Add option for forcing a language by @Earl0fPudding in #742
- fix(run/anubis@.service): unique runtimedir per instance by @Xe in #750
- feat(localization): Add German language translation by @Earl0fPudding in ht...
v1.21.0-pre3: Minfilia Warde
A small fix to amend broken RPM signatures.