Compare commits

...

493 Commits

Author SHA1 Message Date
Xe Iaso
f2cde94b71 test(decaymap): fix tests
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-28 18:46:32 -05:00
Xe Iaso
f56c242167 fix(decaymap): scratch that, once every 15 minutes
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-28 18:31:38 -05:00
Xe Iaso
a75d9066fd fix(decaymap): serialize use of decaymap, make decaying happen once per minute
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-28 18:30:37 -05:00
Xe Iaso
d748dc9da8 test: basic nginx smoke test (#1365)
* docs: split nginx configuration files to their own directory

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: add nginx config smoke test based on the config in the docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-28 23:18:25 +00:00
p0008874
9b210d795e docs(known-instances): Alphabetical order + Add Valve Corporation (#1352)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-12-26 01:05:26 +00:00
The Ninth
e084e5011e feat(localization): add Polish language translation (#1363)
(cherry picked from commit 1f9c2272e6)

Co-authored-by: bplajzer <b.plajzerr@gmail.com>
2025-12-25 15:14:04 -05:00
dependabot[bot]
2532478abd build(deps): bump the github-actions group with 4 updates (#1355)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-12-24 01:02:48 -05:00
Xe Iaso
6d9c0abe74 chore: tag v1.24.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-23 21:17:59 -05:00
Xe Iaso
a37068a423 fix(default-config): remove browser detection logic (#1360)
Looks like these rules don't work anymore.

Closes: #1353

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-24 02:13:54 +00:00
Xe Iaso
9d9be61c24 fix(default-config): must-accept-rule on browsers only (#1350)
TIL docker clients don't include the Accept header all the time. I would
have thought they did that. Oops.

Closes: #1346

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-19 20:42:24 +00:00
Michael
535ed74b17 i18n(de): improve consistency and wording (#1348)
- Use consistent informal address (fix simplified_explanation)
- Translate "protected_from" ("From" → "Von")
- Standardize "Webseite" → "Website"
- Use more natural phrasing:
  - "Berechnung wird durchgeführt" → "Berechnung läuft"
  - "Zur Hauptseite" → "Zur Startseite"
  - Replace awkward "sozialen Vertrag" phrasing
- "Fingerabdruckerkennung" → "Browser-Fingerprinting" (more common)
- Improve sentence structure and punctuation

Signed-off-by: Michael <87752300+michi-onl@users.noreply.github.com>
2025-12-19 00:29:49 +00:00
Xe Iaso
ba8a1b7caf fix(honeypot/naive): right, we want the client IP, not the load balancer IP
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-16 04:44:59 -05:00
Xe Iaso
40afc13d7f fix(honeypot/naive): implement better IP parsing logic
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-16 04:32:45 -05:00
Xe Iaso
122e4bc072 feat: first implementation of honeypot logic (#1342)
* feat: first implementation of honeypot logic

This is a bit of an experiment, stick with me.

The core idea here is that badly written crawlers are that: badly
written. They look for anything that contains `<a href="whatever" />`
tags and will blindly use those values to recurse. This takes advantage
of that by hiding a link in a `<script>` tag like this:

```html
<script type="ignore"><a href="/bots-only">Don't click</a></script>
```

Browsers will ignore it because they have no handler for the "ignore"
script type.

This current draft is very unoptimized (it takes like 7 seconds to
generate a page on my tower), however switching spintax libraries will
make this much faster.

The hope is to make this pluggable with WebAssembly such that we force
administrators to choose a storage method. First we crawl before we
walk.

The AI involvement in this commit is limited to the spintax in
affirmations.txt, spintext.txt, and titles.txt. This generates a bunch
of "pseudoprofound bullshit" like the following:

> This Restoration to Balance & Alignment
>
> There's a moment when creators are being called to realize that the work
> can't be reduced to results, but about energy. We don't innovate products
> by pushing harder, we do it by holding the vision. Because momentum can't
> be forced, it unfolds over time when culture are moving in the same
> direction. We're being invited into a paradigm shift in how we think
> about innovation. [...]

This is intended to "look" like normal article text. As this is a first
draft, this sucks and will be improved upon.

Assisted-by: GLM 4.6, ChatGPT, GPT-OSS 120b
Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(honeypot/naive): optimize hilariously

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(honeypot/naive): attempt to automatically filter out based on crawling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): use mazeGen instead of bsGen

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: add honeypot docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(test): go mod tidy

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: fix spelling metadata

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-16 04:14:29 -05:00
dependabot[bot]
cb91145352 build(deps): bump the gomod group across 1 directory with 6 updates (#1341)
Co-authored-by: Jason Cameron <jason.cameron@stanwith.me>
2025-12-15 02:43:18 +00:00
dependabot[bot]
5c97d693c1 build(deps): bump the github-actions group across 1 directory with 4 updates (#1340)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-12-15 02:34:45 +00:00
dependabot[bot]
988906bb79 build(deps): bump the npm group with 2 updates (#1339)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-12-14 21:29:42 -05:00
Xe Iaso
9c54aa852f chore: v1.24.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-02 07:58:29 -05:00
dependabot[bot]
cb689ee55b build(deps): bump the gomod group with 5 updates (#1316)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-12-01 03:14:20 +00:00
dependabot[bot]
071b836741 build(deps): bump the github-actions group with 3 updates (#1317)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-30 22:12:30 -05:00
Jason Cameron
bbdeee00f7 fix: pin Node.js and Go versions in CI configuration files (#1318)
fixes cache poisoning issues
2025-12-01 03:03:39 +00:00
dependabot[bot]
21d7753b1c build(deps): bump actions-hub/kubectl in the github-actions group (#1303)
Bumps the github-actions group with 1 update: [actions-hub/kubectl](https://github.com/actions-hub/kubectl).


Updates `actions-hub/kubectl` from 1.34.1 to 1.34.2
- [Release notes](https://github.com/actions-hub/kubectl/releases)
- [Commits](f14933a23b...1d2c1e96fe)

---
updated-dependencies:
- dependency-name: actions-hub/kubectl
  dependency-version: 1.34.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-30 13:53:32 -05:00
tbodt
43b8658bfd Show how to use subrequest auth with Caddy (#1312)
Signed-off-by: tbodt <tblodt@icloud.com>
2025-11-27 09:04:28 -05:00
The Ninth
00fa939acf Implement FCrDNS and other DNS features (#1308)
* Implement FCrDNS and other DNS features

* Redesign DNS cache and methods

* Fix DNS cache

* Rename regexSafe arg

* Alter verifyFCrDNS(addr) behaviour

* Remove unused dnsCache field from Server struct

* Upd expressions docs

* Update docs/docs/CHANGELOG.md

Signed-off-by: Xe Iaso <me@xeiaso.net>

* refactor(dns): simplify FCrDNS logging

* docs: clarify verifyFCrDNS behavior

Add a note to the documentation for `verifyFCrDNS` to clarify that it returns true when no PTR records are found for the given IP address.

* fix(dns): Improve FCrDNS error handling and tests

The `VerifyFCrDNS` function previously ignored errors returned from reverse DNS lookups. This could lead to incorrect passes when a DNS failure (other than a simple 'not found') occurred. This change ensures that any error from a reverse lookup will cause the FCrDNS check to fail.

The test suite for FCrDNS has been updated to reflect this change. The mock DNS lookups now simulate both 'not found' errors and other generic DNS errors. The test cases have been updated to ensure that the function behaves correctly in both scenarios, resolving a situation where two test cases were effectively duplicates.

* docs: Update FCrDNS documentation and spelling

Corrected a typo in the `verifyFCrDNS` function documentation.

Additionally, updated the spelling exception list to include new terms and remove redundant entries.

* chore: update spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-11-26 22:24:45 -05:00
Xe Iaso
4ead3ed16e fix(config): deprecate the report_as field for challenges (#1311)
* 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>

* fix(policy): use the new logger for config validation messages

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(admin/thresholds): remove this report_as setting

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-25 23:25:17 -05:00
bplajzer
1f9c2272e6 add Polish language translation (#1309)
* feat(localization): add Polish language translation

* feat(localization): add Polish language translation
2025-11-24 11:55:47 -05:00
Xe Iaso
b11d8132dd chore: add dependabot cooldown (#1302)
* chore: add dependabot cooldown

One of the things I need to worry about with Anubis is the idea that
could pwn a dependency and then get malicious code into prod without
realizing it, a-la Jia Tan. Given that Anubis relies on tools like
Dependabot to manage updating dependencies (good for other reasons),
it makes sense to have Dependabot have a 7 day cooldown for new
versions of dependencies.

This follows the advice from Yossarian on their blog at [1]. Thanks
for the post and easy to copy/paste snippets!

[1]: https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: update spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-21 19:05:26 +00:00
Xe Iaso
f032d5d0ac feat: writing logs to the filesystem with rotation support (#1299)
* refactor: move lib/policy/config to lib/config

Signed-off-by: Xe Iaso <me@xeiaso.net>

* refactor: don't set global loggers anymore

Ref #864

You were right @kotx, it is a bad idea to set the global logger
instance.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(config): add log sink support

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: update spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(test): go mod tidy

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: update spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(admin/policies): add logging block documentation

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(cmd/anubis): revert this change, it's meant to be its own PR

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: go mod tidy

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: add file logging smoke test

Assisted-by: GLM 4.6 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix: don't expose the old log file time format string

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-21 11:46:00 -05:00
Xe Iaso
a709a2b2da ci: add go mod tidy check workflow (#1300)
Assisted-by: GLM 4.6 via Conductor
2025-11-20 16:54:21 +00:00
Lukas Dürrenberger
18d2b4ffff Pass the remote IP to the proxied application (#1298) 2025-11-20 16:32:15 +00:00
Xe Iaso
02989f03d0 feat(store/valkey): Add Redis(R) Sentinel support (#1294)
* feat(internal): add ListOr[T any] type

This is a utility type that lets you decode a JSON T or list of T as a
single value. This will be used with Redis Sentinel config so that you
can specify multiple sentinel addresses.

Ref TecharoHQ/botstopper#24

Assisted-by: GLM 4.6 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(store/valkey): add Redis(R) Sentinel support

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

check-spelling run (pull_request) for Xe/redis-sentinel

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* chore(store/valkey): remove pointless comments

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document the Redis™ Sentinel configuration options

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(store/valkey): Redis™ Sentinel doesn't require a password

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-11-18 09:55:19 -05:00
Jason Cameron
69e9023cbb docs: clarify usage of PUBLIC_URL and REDIRECT_DOMAINS in installatio… (#1286) 2025-11-17 12:11:34 -05:00
Jason Cameron
1d91bc99f2 fix(ogtags): respect target host/SNI/insecure flags in OG passthrough (#1283) 2025-11-16 21:32:03 -05:00
dependabot[bot]
c70b939651 build(deps-dev): bump esbuild from 0.25.12 to 0.27.0 in the npm group (#1260)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-16 19:13:00 -05:00
Jason Cameron
b5c5e07fc2 test(deps): update dependencies to latest versions (#1289) 2025-11-17 00:09:22 +00:00
dependabot[bot]
26fd86bb9a build(deps): bump github.com/testcontainers/testcontainers-go (#1288)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-16 23:47:41 +00:00
Jason Cameron
0258f6b59c build(deps): bump go deps (#1287) 2025-11-16 23:41:20 +00:00
Jason Cameron
56170e4af5 fix(tests): make CVE-2025-24369 regression deterministic (#1285)
* fix(tests): make CVE-2025-24369 regression deterministic

* fix(tests): stabilize CVE-2025-24369 regression test by using invalid proof
2025-11-16 18:34:36 -05:00
Jason Cameron
9dd4de6f1f perf: apply fieldalignement (#1284) 2025-11-16 20:43:07 +00:00
kouhaidev
da1890380e docs: use nginx http2 directive instead of deprecated http2 listen parameter (#1251)
Acked-by: Jason Cameron <git@jasoncameron.dev>
2025-11-16 06:59:16 +00:00
Henri Vasserman
6c8629e3ac test: Valkey test improvements for testcontainers (#1280)
* test: testcontainers improvements

Use the endpoint feature to get the connection URL for the container.

There are cases where localhost is not the correct one, for example when DOCKER_HOST is set to another machine.

Also, don't specify the external port for the mapping so a random unused port is used, in cases when there is already Valkey/Redis running as a container and port mapped externally on 6379.

* also remove this hack, doesn't seem necessary.
2025-11-15 14:32:37 -05:00
DerRockWolf
f6bf98fa28 feat(internal/headers): extend debug logging of X-Forwarded-For middlewares (#1269) 2025-11-15 14:31:43 -05:00
Jason Cameron
97ba84e26d Fix challenge validation panic when follow-up hits ALLOW (#1278)
* fix(localization): correct formatting of Swedish loading message

* fix(main): correct formatting and improve readability in main.go

* fix(challenge): add difficulty and policy rule hash to challenge metadata

* docs(challenge): fix panic when validating challenges in privacy-mode browsers
2025-11-14 19:51:48 -05:00
Xe Iaso
68fcc0c44f feat(lib): expose WEIGH matches as prometheus metrics (#1277)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-14 17:12:59 -05:00
Esteban Gimbernat
6a7f80e6f5 (feat) Add cluster support to redis/vaultkey store (#1276)
* (feat) Add cluster support to redis/vaultkey store

* (chore) Update CHANGELOG.md

* (fix) Disable maintenance notification on the Valkey store

* (fix) Valkey text fix and allow maintnotifications in spelling.
2025-11-14 08:22:22 -05:00
Henri Vasserman
a5bb6d2751 test: ipv4 in v6 address checking (#1271)
* test: ipv4 in v6 address checking

* fix(lib/policy): unmap 4in6 addresses in RemoteAddrChecker

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: perfect CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-11-14 03:39:50 +00:00
kouhaidev
1e298f5d0e fix(run): mark openrc service script as executable (#1272)
Signed-off-by: Kouhai <66407198+kouhaidev@users.noreply.github.com>
2025-11-13 22:14:21 -05:00
Xe Iaso
a4770956a8 fix(docs): use node:lts (#1274)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-14 03:14:00 +00:00
Josh Deprez
316905bf1d Add Renovate to Docker clients (#1267)
Renovate-bot looks at the container APIs directly to learn about new image versions and digests. The [default User-Agent](https://docs.renovatebot.com/self-hosted-configuration/#useragent) is `Renovate/${renovateVersion} (https://github.com/renovatebot/renovate)`
2025-11-12 03:22:00 +00:00
dependabot[bot]
1a12171d74 build(deps): bump the github-actions group with 3 updates (#1262)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-09 18:08:06 -08:00
Denys Nykula
4f50d3245e feat(localization): Add Ukrainian language translation (#1044) 2025-11-08 18:46:20 +00:00
Xe Iaso
49c9333359 fix(data): add services folder to embedded filesystem (#1259)
* fix(data): add services folder to embedded filesystem

Also includes a regression test to ensure this does not happen again.

Assisted-By: GLM 4.6 via Claude Code

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-08 18:08:48 +00:00
Xe Iaso
c7e4cd1032 fix(data/docker-client): allow some more OCI clients through (#1258)
* fix(data/docker-client): allow some more OCI clients through

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/more-docker-client-programs

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix(data/docker-client): add containerd

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-11-08 17:50:56 +00:00
Sveinn í Felli
3f81076743 Update is.json (#1241)
Minor spelling and grammar adjustments for Icelandic

Signed-off-by: Sveinn í Felli <sv1@fellsnet.is>
2025-11-08 10:42:03 -05:00
Karorogunso
115f24c33d Add thai language. (#900)
Signed-off-by: Karorogunso <karorogunso@users.noreply.github.com>
2025-11-08 10:41:46 -05:00
Xe Iaso
b836506785 chore: v1.23.1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-07 19:39:07 -05:00
Xe Iaso
cb67c54ac5 ci: add asset build verification workflow (#1254)
* ci: add asset build verification workflow

A CI pass that fails if generated files are out of date.

* chore: npm run assets

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-08 00:24:38 +00:00
Xe Iaso
b5ead0a68c fix(data): add ruleset to explicitly allow Docker / OCI clients (#1253)
* fix(data): add ruleset to explicitly allow Docker / OCI clients

Fixes #1252

This 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.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/gh-1252/docker-registry-client-fix

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* test(docker-registry): export the right envvars

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: add simdjson dependency for homebrew node

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: install go/node without homebrew

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: use right github commit variable

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: remove simdjson dependency

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: install ko with an action

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: add OCI registry caveat docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-11-08 00:17:25 +00:00
dependabot[bot]
df217d61c8 build(deps): bump the gomod group across 1 directory with 18 updates (#1237)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-03 01:24:26 +00:00
dependabot[bot]
cc1d79aec6 build(deps): bump github/codeql-action in the github-actions group (#1239)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-02 20:23:50 -05:00
dependabot[bot]
4d1d7c39eb build(deps-dev): bump the npm group across 1 directory with 3 updates (#1238)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-11-02 20:14:51 -05:00
Xe Iaso
83a83e9691 feat(blog): a short post on how to file abuse reports (#1230)
* feat(blog): add blogpost on how to file abuse reports

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(blog/abuse-reports): fix some wording to read a bit more professionally

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (push) for Xe/blog/abuse-reports

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix(blog/abuse-reports): minor spelling and grammar fixups

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-10-31 13:54:24 -04:00
Xe Iaso
531e1dd7f4 chore(default-config): remove Tencent Cloud block rule (#1227)
Tencent Cloud's abuse team reached out to me recently and asked for this
rule to be removed. Prior attempts to reach out to them to report
abusive traffic have failed, thus leading to this IP space block as a
last resort to try and maintain uptime for systems administrators.

Unfortunately, it's difficult for Tencent's abuse team to take action if
there is a blanket block like this. Let's see if this doesn't cause too
much grief.
2025-10-31 11:20:04 -04:00
Xe Iaso
59f1e36167 fix: SERVE_ROBOTS_TXT works again (#1229)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-31 09:08:33 -04:00
Xe Iaso
62c1b80189 chore: tag v1.23.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-29 20:38:34 -04:00
Xe Iaso
7ed1753fcc fix(lib): close open redirect when in subrequest mode (#1222)
* test(nginx-external-auth): bring up to code standards

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): close open redirect when in subrequest mode

Closes GHSA-cf57-c578-7jvv

Previously Anubis had an open redirect in subrequest auth mode due to an
insufficent fix in GHSA-jhjj-2g64-px7c. This patch adds additional
validation at several steps of the flow to prevent open redirects in
subrequest auth mode as well as implements automated testing to prevent
this from occuring in the future.

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-29 16:07:31 -04:00
dependabot[bot]
3dab060bfa build(deps): bump the github-actions group across 1 directory with 6 updates (#1221)
Bumps the github-actions group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/cache](https://github.com/actions/cache) | `4.2.4` | `4.3.0` |
| [docker/login-action](https://github.com/docker/login-action) | `3.5.0` | `3.6.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4.6.2` | `5.0.0` |
| [actions/setup-node](https://github.com/actions/setup-node) | `5.0.0` | `6.0.0` |
| [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) | `6.7.0` | `7.1.2` |
| [github/codeql-action](https://github.com/github/codeql-action) | `3.30.3` | `4.31.0` |



Updates `actions/cache` from 4.2.4 to 4.3.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](0400d5f644...0057852bfa)

Updates `docker/login-action` from 3.5.0 to 3.6.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](184bdaa072...5e57cd1181)

Updates `actions/upload-artifact` from 4.6.2 to 5.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](ea165f8d65...330a01c490)

Updates `actions/setup-node` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](a0853c2454...2028fbc5c2)

Updates `astral-sh/setup-uv` from 6.7.0 to 7.1.2
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](b75a909f75...85856786d1)

Updates `github/codeql-action` from 3.30.3 to 4.31.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](192325c861...4e94bd11f7)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: docker/login-action
  dependency-version: 3.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/setup-node
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: astral-sh/setup-uv
  dependency-version: 7.1.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 4.31.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-26 22:41:24 -04:00
Xe Iaso
ab8b91fc0c chore: v1.23.0-pre2
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-26 19:23:16 -04:00
Xe Iaso
168e72088f chore: remove copilot instructions (#1218)
Recent models like GPT-5 have broken these instructions. As such, I
don't think that it's worth having these around anymore. I think that
longer term it may be better to have a policy of having people disclaim
which models they use in commit footers rather than having a "don't use
this tool" policy, which people are just going to work around and
ignore.
2025-10-24 22:42:48 -04:00
Xe Iaso
6b1cd6120f fix!(policy/checker): make List and-like (#1217)
* fix!(policy/checker): make List and-like

This has the potential to break user configs.

Anubis lets you stack multiple checks at once with blocks like this:

```yaml
name: allow-prometheus
action: ALLOW
user_agent_regex: ^prometheus-probe$
remote_addresses:
  - 192.168.2.0/24
```

Previously, 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 have marked this as a potentially breaking change because I'm
absolutely certain that someone is relying on this behaviour due to
spacebar heating. If this bites you, please let me know ASAP.

Signed-off-by: Xe Iaso <me@xeiaso.net>
Assisted-by: GPT-OSS 120b on local hardware

* fix(policy/checker): more explicit short-circuit

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-25 01:25:05 +00:00
Peter Bhat Harkins
d7459de941 link to docs site from readme (#1214) 2025-10-24 15:53:11 -04:00
Xe Iaso
c96c229b68 feat(default-config): block tencent cloud by default (#1216)
* feat(default-config): block tencent cloud by default

This is what happens when you don't have an abuse contact.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: update spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-24 19:43:42 +00:00
Xe Iaso
b384ad03cb fix(store/bbolt): remove actorify (#1215)
Closes #1206

This can cause Anubis to have other issues, but at the very least these
issues are at the Anubis level, not the level of your target service so
it's less bad.
2025-10-24 19:28:58 +00:00
Xe Iaso
a4efcef1c9 docs: point get started button to the per-environment setup docs (#1213)
Thanks untitaker!
2025-10-24 19:19:29 +00:00
Xe Iaso
2fc3765340 chore: tag v1.23.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-22 14:35:23 +00:00
Sunniva Løvstad
ec2981bf6f locale: Update Nynorsk translation (#1204)
* Update nn.json

Signed-off-by: Sunniva Løvstad <github@turtle.garden>

* Update nn.json (2)

Signed-off-by: Sunniva Løvstad <github@turtle.garden>

* Change awkward wording

Proof of Work → work-proof, that is confirmation that someone is real through work (the computer works)

Signed-off-by: Sunniva Løvstad <github@turtle.garden>

---------

Signed-off-by: Sunniva Løvstad <github@turtle.garden>
2025-10-22 12:46:46 +00:00
Xe Iaso
e3d3195bf2 Xe/show error state (#1203)
* fix(lib): show error message detail when hitting some common flows

Instead of giving the user nothing to go off of, this patch gives them
an opaque blob of ROT-13 encoded base64. The logic is that if you are
smart enough to figure out how to decode this, you're probably smart
enough to either fix your broken client or give it to the adminstrator.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/show-error-state

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-10-21 13:10:27 -04:00
Xe Iaso
25d677cbba fix(algorithms/fast): fix fast challenge on insecure contexts (#1198)
* fix(algorithms/fast): fix fast challenge on insecure contexts

Closes #1192

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-17 19:32:24 -04:00
Xe Iaso
00261d049e fix(default-config): sometimes browsers don't send Upgrade-Insecure-Requests (#1189)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-13 18:31:14 +00:00
Thomas Anderson
a12b4bb755 changed redirect_domains docs (#1171) 2025-10-13 16:21:56 +00:00
Xe Iaso
4dfc73abd1 fix(lib): de-flake package lib tests (#1187)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-13 11:50:13 -04:00
Xe Iaso
ffbbdce3da feat: default config macro (#1186)
* feat(data): add default-config macro

Closes #1152

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: add default-config-macro smoke test

This uses an AI generated python script to diff the contents of the bots
field of the default configuration file and the
data/meta/default-config.yaml file. It emits a patch showing what needs
to be changed.

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-13 11:33:16 -04:00
Xe Iaso
c09c86778d fix(default-config): remove preact challenge (#1184)
* fix(default-config): remove the preact challenge from the default config

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-10-11 09:22:07 -04:00
Xe Iaso
9c47c180d0 fix(default-config): make the default config far less paranoid (#1179)
* test: add httpdebug tool

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(data/clients/git): more strictly match the git client

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(default-config): make the default config far less paranoid

This uses a variety of heuristics to make sure that clients that claim
to be browsers are more likely to behave like browsers. Most of these
are based on the results of a lot of reverse engineering and data
collection from honeypot servers.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-10-11 08:48:12 -04:00
Xe Iaso
d51d32726c fix(lib): serve CSS properly (#1158)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-27 22:16:23 -04:00
dependabot[bot]
ff33982ee9 build(deps): bump github.com/docker/docker (#1131)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.3.2+incompatible to 28.3.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.2...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.3.3+incompatible
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-27 14:29:07 -04:00
dependabot[bot]
ec90a8b87d build(deps): bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 (#1132)
Bumps [github.com/ulikunitz/xz](https://github.com/ulikunitz/xz) from 0.5.12 to 0.5.14.
- [Commits](https://github.com/ulikunitz/xz/compare/v0.5.12...v0.5.14)

---
updated-dependencies:
- dependency-name: github.com/ulikunitz/xz
  dependency-version: 0.5.14
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-27 13:46:23 -04:00
dependabot[bot]
5731477e0a build(deps-dev): bump esbuild from 0.25.9 to 0.25.10 in the npm group (#1147)
Bumps the npm group with 1 update: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.25.9 to 0.25.10
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.9...v0.25.10)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-27 13:46:12 -04:00
Xe Iaso
714c85dbc4 fix(lib): enable multiple consecutive slash support (#1155)
* fix(lib): enable multiple consecutive slash support

Closes #754
Closes #808
Closes #815

Apparently more applications use multiple slashes in a row than I
thought. There is no easy way around this other than to do this hacky
fix to avoid net/http#ServeMux's URL cleaning.

* test(double_slash): add sourceware case

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): fix tests for double slash fix

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-27 13:44:46 -04:00
Jamie McClelland
75ea1b60d5 enable auto setting of SNI based on host header (#1129)
With this change, setting targetSNI to 'auto' causes anubis to
use the request host name as the SNI name, allowing multiple sites
to use the same anubis instance and same backend, while still securely
connecting to the backend via https.

See https://github.com/TecharoHQ/anubis/issues/424
2025-09-25 08:08:16 +00:00
violet
1cf03535a5 feat: support reading real client IP from a custom header (#1138)
* feat: support reading real client IP from a custom header

* pr reviews

---------

Co-authored-by: violet <violet@tsukuyomi>
2025-09-25 04:01:24 -04:00
Sunniva Løvstad
c3ed405dbc Update Nynorsk translation (#1143)
* chore: fix capitalisation in bokmål and nynorsk

* stadfest → e-verb

Signed-off-by: Sunniva Løvstad <github@turtle.garden>

---------

Signed-off-by: Sunniva Løvstad <github@turtle.garden>
2025-09-25 04:01:02 -04:00
Xe Iaso
8cdf58c9e6 ci(ssh): re-enable aarch64-16k
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-20 15:30:29 +00:00
Xe Iaso
1c170988c8 fix: mend auth cookie name stutter (#1139)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-19 13:51:11 -04:00
Xe Iaso
9439466ff2 ci(ssh): disable aarch64-16k until my SFP connecter comes in on friday
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-17 16:00:10 +00:00
Richard Mahn
4787aeca51 Add Door43 link to known instances documentation (#1136)
Signed-off-by: Richard Mahn <richmahn@users.noreply.github.com>
2025-09-17 13:11:11 +00:00
Xe Iaso
fb3637df95 feat(metarefresh): randomly use the Refresh header (#1133)
* feat(lib/challenge): expose ResponseWriter to challenge issuers

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(metarefresh): randomly use the Refresh header

There are several ways to trigger an automatic refresh without
JavaScript. One of them is the "meta refresh" method[1], but the other
is with the Refresh header[2]. Both are semantically identical and
supported with browsers as old as Chrome version 1.

Given that they are basically the same thing, this patch makes Anubis
randomly select between them by using the challenge random data's first
character. This will fire about 50% of the time.

I expect this to have no impact. If this works out fine, then I will
implement some kind of fallback logic for the fast challenge such that
admins can opt into allowing clients with a no-js configuration to pass
the fast challenge. This needs to bake in the oven though.

[1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/http-equiv
[2]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Refresh

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(metarefresh): simplify random logic

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-09-16 17:32:13 -04:00
dependabot[bot]
26076b8520 build(deps): bump github.com/docker/docker in /test (#1130)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.3.2+incompatible to 28.3.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.2...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.3.3+incompatible
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-16 16:22:28 -04:00
NetSysFire
edb84f03b7 convert issue templates into issue forms (#1115) 2025-09-16 13:14:10 +00:00
Jan Pieter Waagmeester
b2d525bba4 Update nl.json removeing literal translated 'cookie' (koekje) with 'cookie' (#1126)
Signed-off-by: Jan Pieter Waagmeester <jieter@jieter.nl>
2025-09-16 07:53:30 -04:00
dependabot[bot]
00679aed66 build(deps): bump the github-actions group with 3 updates (#1118)
Bumps the github-actions group with 3 updates: [actions-hub/kubectl](https://github.com/actions-hub/kubectl), [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `actions-hub/kubectl` from 1.34.0 to 1.34.1
- [Release notes](https://github.com/actions-hub/kubectl/releases)
- [Commits](af345ed727...f14933a23b)

Updates `astral-sh/setup-uv` from 6.6.1 to 6.7.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](557e51de59...b75a909f75)

Updates `github/codeql-action` from 3.30.1 to 3.30.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](f1f6e5f6af...192325c861)

---
updated-dependencies:
- dependency-name: actions-hub/kubectl
  dependency-version: 1.34.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.30.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-15 18:23:31 -04:00
dependabot[bot]
03299024c5 build(deps): bump the npm group with 2 updates (#1117)
Bumps the npm group with 2 updates: [preact](https://github.com/preactjs/preact) and [postcss-import-url](https://github.com/unlight/postcss-import-url).


Updates `preact` from 10.27.1 to 10.27.2
- [Release notes](https://github.com/preactjs/preact/releases)
- [Commits](https://github.com/preactjs/preact/compare/10.27.1...10.27.2)

Updates `postcss-import-url` from 1.0.0 to 7.2.0
- [Release notes](https://github.com/unlight/postcss-import-url/releases)
- [Changelog](https://github.com/unlight/postcss-import-url/blob/master/CHANGELOG.md)
- [Commits](https://github.com/unlight/postcss-import-url/commits/v7.2.0)

---
updated-dependencies:
- dependency-name: preact
  dependency-version: 10.27.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: postcss-import-url
  dependency-version: 7.2.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-15 18:23:15 -04:00
Anna
f745d37d90 fix(run/openrc): truncate runtime directory before starting Anubis (#1122)
If Anubis is not shut down correctly and there are leftover socket
files, Anubis will refuse to start.

As "checkpath -D" currently does not work as expected
(https://github.com/OpenRC/openrc/issues/335), simply use "rm -rf"
before starting Anubis.

Signed-off-by: Anna @CyberTailor <cyber@sysrq.in>
2025-09-15 07:44:35 -04:00
Xe Iaso
d12993e31d feat(expressions): add contentLength to bot expressions (#1120)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-15 01:41:45 +00:00
Xe Iaso
88b3e457ee docs: update BotStopper docs based on new features
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-14 20:16:43 +00:00
Xe Iaso
bb2b113b63 ci(ssh): don't print uname -av output (#1114)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-14 03:03:46 +00:00
Xe Iaso
6c283d0cd9 ci: add aarch64 for ssh CI (#1112)
* ci: add aarch64 for ssh CI

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: better comment aile and t-elos' roles

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: fix aile

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: update ssh known hosts secret

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci(ssh): replace raw connection strings with arch-quirks

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci(ssh): disable this check in PRs again

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-14 00:15:23 +00:00
agoujot
0037e214a1 add link to preact in challenge list (#1111)
Preact was added in 1.22, but it currently isn't listed in the "Challenges" page.

Signed-off-by: agoujot <145840578+agoujot@users.noreply.github.com>
2025-09-13 17:31:36 -04:00
Valentin Lab
29ae2a4b87 feat: fallback to SameSite Lax mode if cookie is not secure (#1105)
Also, will allow to set cookie `SameSite` mode on command line or
environment. Note that `None` mode will be forced to ``Lax`` if
cookie is set to not be secure.

Signed-off-by: Valentin Lab <valentin.lab@kalysto.org>
2025-09-13 10:56:54 +00:00
Xe Iaso
401e18f29f feat(store/bbolt): implement actor pattern (#1107)
* feat(store/bbolt): implement actor pattern

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(internal/actorify): document package

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/actorify

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-09-12 18:35:22 +00:00
Xe Iaso
63591866aa fix(decaymap): fix lock convoy (#1106)
* fix(decaymap): fix lock convoy

Ref #1103

This uses the actor pattern to delay deletion instead of making things
fight over a lock. It also properly fixes locking logic to prevent the
convoy problem.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-12 16:43:08 +00:00
Xe Iaso
f79d36d21e docs: update CHANGELOG properly
It helps if you save your editor buffer!

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-11 14:07:52 +00:00
Xe Iaso
f5b5243b5e docs: update CHANGELOG
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-11 14:04:32 +00:00
Xe Iaso
2011b83a44 chore: port client-side JS to TypeScript (#1100)
* chore(challenge/preact): port to typescript

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(js/algorithms): port to typescript

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(js/worker): port to typescript

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(web): fix TypeScript build logic

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(web): port bench.mjs to typescript

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(web): port main.mjs to typescript

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/use-typescript

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix(js/algorithms/fast): handle old browsers

Closes #1082

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-09-11 10:03:10 -04:00
Martin
8ed89a6c6e feat(lib): Add option for adding difficulty field to JWT claims (#1063)
* Add option for difficulty JWT field

* Add DIFFICULTY_IN_JWT option to docs

* Add missing_required_forwarded_headers to lt translation via Google Translate

* docs(CHANGELOG): move CHANGELOG entry to the top

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-09-11 13:50:33 +00:00
Xe Iaso
9430d0e6a5 fix(cmd/containerbuild): support commas in --docker-tags (#1099)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-08 22:19:42 +00:00
Xe Iaso
8b9dafac51 security: npm audit fix for GHSA-hfm8-9jrf-7g9w et. al (#1098)
* security: npm audit fix for GHSA-hfm8-9jrf-7g9w et. al

Closes #1097

I'm not sure that this is required, but I'd sleep better at night not
finding out that it is required the hard way.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: bump postcss version

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-08 14:17:59 -04:00
dependabot[bot]
9997130a7c build(deps): bump the github-actions group with 4 updates (#1093)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-09-07 22:01:27 -04:00
Jason Cameron
e239083944 docs: add reminder for verified signatures in PR template (#1092) 2025-09-07 16:15:26 -04:00
Jason Cameron
abf6c8de57 feat: Warn on missing signing keys when persisting challenges (#1088) 2025-09-07 15:43:58 -04:00
Xe Iaso
7e1b5d9951 fix: demote temporal assurance checks
* fix(challenge): demote temporal assurance to 80% instead of 95%

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenge/preact): wait a little longer to be extra safe

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenge/metarefresh): wait a little longer to be extra safe

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(CHANGELOG): add fix notes

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-07 16:10:54 +00:00
Xe Iaso
98945fb56f feat(lib/store): add s3api storage backend (#1089)
* feat(lib/store): add s3api storage backend

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(store/s3api): replace fake S3 API keys with the bee movie script

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(store/s3api): fix spelling sin

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(store/s3api): remove vestigal experiment

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(store/s3api): support IsPersistent call

Ref #1088

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(test): go mod tidy

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-07 09:24:14 -04:00
Jason Cameron
82099d9e05 fix(robots2policy): handle multiple user agents under one block (#925) 2025-09-06 22:35:19 -04:00
dependabot[bot]
87c2f1e0e6 build(deps): bump the github-actions group across 1 directory with 8 updates (#1071)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-09-06 22:30:43 -04:00
Jason Cameron
f0199d014f docs: document some missing env vars (#1087) 2025-09-07 01:34:42 +00:00
Jason Cameron
75109f6b73 docs(installation): add SLOG_LEVEL environment variable to configuration (#1086)
* docs(installation): add SLOG_LEVEL environment variable to configuration

* docs(installation): add SLOG_LEVEL environment variable to configuration
2025-09-06 20:59:02 -04:00
Xe Iaso
c43d7ca686 docs(botstopper): add HTML templating support
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-06 23:42:23 +00:00
Xe Iaso
5d5c39e123 chore: v1.22.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-06 11:54:36 -04:00
Xe Iaso
d35e47c655 feat: glob matching for redirect domains (#1084)
* feat: glob matching for redirect domains

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-06 15:46:18 +00:00
Xe Iaso
48b49a0190 docs(CHANGELOG): add changelog entry for v1.22.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-05 22:42:08 +00:00
Xe Iaso
de94139789 test: ensure FORCED_LANGUAGE works (#1083)
Closes #1077
2025-09-05 22:07:17 +00:00
Rimas Kudelis
fd011d19e2 Updates to lt.json (#1075)
Minor improvements to Lithuanian strings

Signed-off-by: Rimas Kudelis <rimas@kudelis.lt>
2025-09-03 20:07:46 -04:00
Xe Iaso
489abb6b4d chore: release v1.22.0-pre2
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-02 21:31:17 -04:00
Xe Iaso
8da0771647 chore: break AI agents in this code tree (#1065)
Update metadata

check-spelling run (pull_request) for Xe/anti-assistant


on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

Update metadata

check-spelling run (pull_request) for Xe/anti-assistant


on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

chore: fix package builds

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-09-02 10:11:01 -04:00
Xe Iaso
f0bcbe43af ci: fix tests (#1069)
* fix(locailization): fix ci

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(test): fix CI

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(test): fix CI?

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(test): fix CI??

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-31 08:13:00 -04:00
Xe Iaso
f6e077c907 fix(challenge/metarefresh): ensure that clients have waited long enough (#1068)
Some admins have noticed that clients are not waiting the right amount
of time in order to access a resource protected by the metarefresh
challenge. This patch adds a check to make sure that clients have waited
at least 95% (difficulty times 950 milliseconds instead of difficulity
times 1000 milliseconds) of the time they should.

If this scales, maybe time is the best way to go for Anubis in the near
future instead of anything else computational.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-31 07:51:54 -04:00
/har/per
2704ba95d0 feat(localization): Add Vietnamese translation (#926)
* feat(localization): Add Vietnamese translation

* feat(localization): Add Vietnamese language translation

* feat(localization): Add record to CHANGELOG.md

* feat(localization): Add test case for Vietnamese
2025-08-30 00:23:02 -04:00
Xe Iaso
f6a578787f chore(docs): adjust anubis rules
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-29 23:04:32 +00:00
Xe Iaso
31a654ecb6 chore: introduce issue templates (#939)
* chore: introduce issue templates

* chore: fix spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-29 20:41:39 +00:00
Xe Iaso
1a4b5cadcb chore: fix spelling
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-29 20:31:20 +00:00
Rimas Kudelis
d5cdd21631 feat(localizaton): add Lithuanian locale (#998) 2025-08-29 16:29:57 -04:00
Xe Iaso
0e0847cbeb feat: add 'proof of React' challenge (#1038)
* feat: add 'proof of React' challenge

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenge/preact): use JSX fragments

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenge/preact): ensure that the client waits as long as it needs to

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: fix spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenges/xeact): add noscript warning

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenges/xeact): add default loading message

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenges/xeact): make a UI render without JS

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenges/xeact): use %s here, not %w

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(test/healthcheck): run asset build

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenge/preact): fix build in ci

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-29 16:09:27 -04:00
Xe Iaso
00afa72c4b fix(blog/cpu-core-odd): make the diagram look decent in light mode
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-29 19:54:22 +00:00
Xe Iaso
eb50f59351 docs(changelog): fix mis-paste
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-29 19:54:02 +00:00
Skyler Mäntysaari
01f55cf552 internal/log: Implement logging of HOST when using subrequest auth (#1027)
* internal/log: Implement logging of HOST when using subrequest auth

The host header wouldn't be set on subrequest auth, so we need to look for X-Forwarded-Host header when logging requests.

* chore: add changelog entry

---------

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Co-authored-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-29 19:04:33 +00:00
OwN-3m-All
99bd06b8c3 Update nginx.mdx - needs port_in_redirect off setting (#1018)
* Update nginx.mdx - needs port_in_redirect off setting

Signed-off-by: OwN-3m-All <own3mall@gmail.com>

* Update metadata

check-spelling run (pull_request) for patch-1

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: OwN-3m-All <own3mall@gmail.com>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-08-29 19:03:08 +00:00
TinyServal
d6f1f24e1b docs: document client IP headers and interop with cloudflare (#1034) 2025-08-29 14:54:03 -04:00
Eric Hameleers
6a5485fde9 Alienbob: add Slackware URLs that are now protected by Anubis (#1051)
* Update known-instances.md with Slackware git servers

Signed-off-by: Eric Hameleers <alien@slackware.com>

* Update CHANGELOG.md with Slackware git servers being protected by Anubis

Signed-off-by: Eric Hameleers <alien@slackware.com>

---------

Signed-off-by: Eric Hameleers <alien@slackware.com>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Co-authored-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-29 14:24:04 +00:00
Alex Samorukov
582181f9b9 Allow to disable keep-alive for the targets not supporting it properly (#1049)
* Allow to disable keep-alive for the targets not supporting it properly

* Add changelog entry
2025-08-29 10:17:03 -04:00
Chris
44264981b5 Fix broken docs link (#1059)
Fixes a broken docs link

Signed-off-by: Chris <398094+phuzion@users.noreply.github.com>
2025-08-28 11:28:25 -03:00
Xe Iaso
21c3e0c469 docs(blog): add post about the odd CPU core count bug (#1058)
* docs(blog): add post about the odd CPU core count bug

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-28 09:32:04 -04:00
phoval
9ddc1eb840 fix: middleware traefik redirect url (#1040) 2025-08-28 07:24:29 -04:00
Xe Iaso
c661bc37d1 fix(worker): constrain nonce value to be a whole integer (#1045)
* fix(worker): constrain nonce value to be a whole integer

Closes #1043

Sometimes the worker could get into a strange state where it has a
decimal nonce, but the server assumes that the nonce can only be a whole
number. This patch constrains the nonce to be a whole number on the
worker end by detecting if the nonce is a decimal number and then
truncating away the decimal portion.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(algorithms/fast): truncate decimal place on number of threads

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-26 14:05:03 -04:00
dependabot[bot]
fb8ce508ee build(deps-dev): bump the npm group across 1 directory with 3 updates (#1032)
Bumps the npm group with 3 updates in the / directory: [cssnano](https://github.com/cssnano/cssnano), [cssnano-preset-advanced](https://github.com/cssnano/cssnano) and [esbuild](https://github.com/evanw/esbuild).


Updates `cssnano` from 7.1.0 to 7.1.1
- [Release notes](https://github.com/cssnano/cssnano/releases)
- [Commits](https://github.com/cssnano/cssnano/compare/cssnano@7.1.0...cssnano@7.1.1)

Updates `cssnano-preset-advanced` from 7.0.8 to 7.0.9
- [Release notes](https://github.com/cssnano/cssnano/releases)
- [Commits](https://github.com/cssnano/cssnano/compare/cssnano-preset-advanced@7.0.8...cssnano-preset-advanced@7.0.9)

Updates `esbuild` from 0.25.8 to 0.25.9
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.8...v0.25.9)

---
updated-dependencies:
- dependency-name: cssnano
  dependency-version: 7.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: cssnano-preset-advanced
  dependency-version: 7.0.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: esbuild
  dependency-version: 0.25.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 00:33:44 +00:00
Jason Cameron
573b0079fb Update metadata (#1031) 2025-08-24 21:40:12 +00:00
Skyler Mäntysaari
d1d631a18a lib/checker: Implement X-Original-URI support (#1015) 2025-08-23 23:14:37 -04:00
Timo Tijhof
f3cd6c9ca4 docs: fix "stored" typo in CHANGELOG.md (#1008)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-08-24 03:12:08 +00:00
Brad Parbs
23772fd3cb s/Wordpress/WordPress in docs (#1020)
Signed-off-by: Brad Parbs <brad@bradparbs.com>
2025-08-24 02:52:09 +00:00
Xe Iaso
a7a61690fc chore: commit for v1.22.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-23 22:39:43 -04:00
Xe Iaso
f5afe8b6c8 chore: release v1.22.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-24 02:38:54 +00:00
Julian Krieger
61682e4987 Update installation.mdx to include a link to the Caddy docs (#993)
* Update installation.mdx to include a link to the Caddy docs

Signed-off-by: Julian Krieger <julian.krieger@hm.edu>

* Update CHANGELOG.md to include documentation changes

Signed-off-by: Julian Krieger <julian.krieger@hm.edu>

---------

Signed-off-by: Julian Krieger <julian.krieger@hm.edu>
2025-08-20 23:02:49 +00:00
Xe Iaso
b0fa256e3e fix(default-config): also block alibaba cloud (#1005)
* fix(default-config): also block alibaba cloud

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-20 23:01:49 +00:00
Xe Iaso
ee55d857eb fix(default-config): block Huawei Cloud (#1004)
* fix(default-config): block Huawei Cloud

Closes #978

Huawei Cloud has been egregious about its scraping. All attempts to
contact their abuse team have failed. If you work for Huawei Cloud,
please raise this issue internally and get the scraping to just stop.

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-20 22:40:07 +00:00
Xe Iaso
993ea8da1b chore: copy SECURITY.md from TecharoHQ/.github
This hopefully makes the security policy harder to miss.

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-20 12:42:02 -04:00
Xe Iaso
6e4e471792 fix(lib): ensure issued challenges don't get double-spent (#1003)
* fix(lib): ensure issued challenges don't get double-spent

Closes #1002

TL;DR: challenge IDs were not validated at time of token issuance. A
dedicated attacker could solve a challenge once and reuse it across
multiple sessons in order to mint additional tokens.

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.

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-20 12:33:32 -04:00
Xe Iaso
e8dfff6350 feat(blog): add short funding update post (#994)
* feat(blog): add short funding update post

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-18 08:42:27 -04:00
Dryusdan
237a6a98e2 Bump ai.robots.txt to v1.39 (#982) 2025-08-18 06:52:23 -04:00
Xe Iaso
e43999f30c chore: add libreapay
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-16 03:01:59 +00:00
Martin
29d038835f feat(web): Add option for customizable explanation text (#747)
* Add option for customizable explanation text

* Add changes to CHANGELOG.md

* Replace custom explanation text in favor of static simplified text

Also includes translations for the simple_explanation using Google
Translate as a placeholder so tests pass.

---------

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Co-authored-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-14 11:12:55 -04:00
Xe Iaso
39215457e4 fix(locales): remove the word "hack" from the description of Anubis (#973)
This was causing confusion and less technical users were thinking that
websites had been intruded upon, causing them to send me horrible things
over email.

All non-English strings were amended using Google Translate. Please fix
the localization as appropriate.
2025-08-14 01:15:28 +00:00
Martin
ff691dfee8 feat(lib): Add optional restrictions for JWT based on a specific header value (#697)
* Add JWTRestrictionHeader funktionality

* Add JWTRestrictionHeader to docs

* Move JWT_RESTRICTION_HEADER from advanced section to normal one

* Add rull request URL to Changelog

* Set default value of JWT_RESTRICTION_HEADER to X-Real-IP
2025-08-13 23:27:42 +00:00
Mathieu Lu
83503525f2 Update known-instances.md: add lab.civicrm.org (#971)
Signed-off-by: Mathieu Lu <mathieu@civicrm.org>
2025-08-13 19:32:29 +00:00
phoval
a8b7b2ad7b feat: support HTTP redirect for forward authentication middleware in Traefik (#368)
* feat: support HTTP redirect for forward authentication middleware in Traefik

* fix(docs): fix my terrible merge 

Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* chore: fix typo in docs

Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* fix(ci): add forwardauth

Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* chore: improve doc, target must be a space

* chore: changelog

* fix: validate X-Forwarded headers and check redirect domain

* chore: refactor error handling

* fix(doc): cookie traefik

* fix: tests merge

* Update docs/docs/admin/environments/traefik.mdx

Co-authored-by: Henri Vasserman <henv@hot.ee>
Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
Co-authored-by: Jason Cameron <jasoncameron.all@gmail.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Henri Vasserman <henv@hot.ee>
2025-08-12 20:59:45 -04:00
Elliot Speck
87651f9506 default pattern fixes (#963)
* feat(checker): allow png/gif/jpg/jpeg/svg favicons as well as ico

* changelog: add updates to keep-internet-working.yaml

* fix(checker): tighten default regex patterns for well-known files

* changelog: add updates to regular expression patterns in keep-internet-working.yaml

---------

Signed-off-by: Elliot Speck <11192354+arcayr@users.noreply.github.com>
2025-08-09 07:40:33 -04:00
Elliot Speck
100005ce70 feat(checker): allow png/gif/jpg/jpeg/svg favicons as well as ico (#961)
* feat(checker): allow png/gif/jpg/jpeg/svg favicons as well as ico

* changelog: add updates to keep-internet-working.yaml

---------

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Co-authored-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-08 16:53:23 +00:00
Medvidek77
0a68415c2e fix(localization): Improve Czech language translation (#895)
* fix(localization): Improve Czech language translation

Improved naturalness and flow of several phrases. Corrected typos and punctuation. Completed one previously unfinished sentence.

Signed-off-by: Medvidek77 <medvidek77@centrum.cz>

* Update cs.json

Signed-off-by: Medvidek77 <medvidek77@centrum.cz>

---------

Signed-off-by: Medvidek77 <medvidek77@centrum.cz>
2025-08-08 12:50:23 -04:00
SecularSteve
b3886752a1 Added Dutch translation (#937)
* Added Dutch translation

Signed-off-by: SecularSteve <33793273+SecularSteve@users.noreply.github.com>

* Added Dutch translation

Signed-off-by: SecularSteve <33793273+SecularSteve@users.noreply.github.com>

* Added Dutch translation

Signed-off-by: SecularSteve <33793273+SecularSteve@users.noreply.github.com>

* Update lib/localization/locales/nl.json

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: SecularSteve <33793273+SecularSteve@users.noreply.github.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-08-08 12:49:49 -04:00
Sunniva Løvstad
0e9f831201 chore: fix capitalisation in bokmål and nynorsk (#959) 2025-08-08 12:48:07 -04:00
Xe Iaso
22ee227f20 fix(anubis): use global cookie prefix variable
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-07 13:51:18 +00:00
Jason Cameron
adda60c163 Revert "build(deps): bump the github-actions group with 2 updates (#952)" (#962) 2025-08-06 03:01:25 +00:00
dependabot[bot]
e0a15bf4dc build(deps): bump the github-actions group with 2 updates (#952)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-08-05 22:45:07 -04:00
Xe Iaso
f6481b81a2 fix(web): embed challenge ID in pass-challenge invocations (#944)
* refactor: make challenge pages return the challenge component

This means that challenge pages will return only the little bit that
actually matters, not the entire component.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(web): move Anubis version info to be implicitly in the footer

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(web): embed challenge ID into generated pages

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): make tests pass

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/policy/config): amend tests

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): fix tests again

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-08-04 18:49:19 +00:00
Xe Iaso
790bcbe773 fix(internal): silence unsolicited response log lines (#950)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-03 19:08:23 +00:00
Xe Iaso
7c80c23e90 docs: remove JSON examples from policy file docs (#945)
* docs: remove JSON examples from policy file docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): remove mentions of botPolicies.json in the tests

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update link to challenge methods

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: unbreak links to the challenges category

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-03 18:09:26 +00:00
axell
2d8e942377 Add swedish local (#913)
* add swedish local

* added to changelog

* add to TestLocalizationService

* build(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /docs (#909)

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* add local (signed this time hopefully)

* Update sv.json

Co-authored-by: David Marby <david@dmarby.se>
Signed-off-by: axel <mail@axell.me>

* Update sv.json

Co-authored-by: David Marby <david@dmarby.se>
Signed-off-by: axel <mail@axell.me>

* Update localization_test.go

Co-authored-by: Jonathan Herlin <Jonte@jherlin.se>
Signed-off-by: axel <mail@axell.me>

* Update sv.json

Co-authored-by: Jonathan Herlin <Jonte@jherlin.se>
Signed-off-by: axel <mail@axell.me>

* Update sv.json

Co-authored-by: Jonathan Herlin <Jonte@jherlin.se>
Signed-off-by: axel <mail@axell.me>

* Update sv.json

Co-authored-by: Jonathan Herlin <Jonte@jherlin.se>
Signed-off-by: axel <mail@axell.me>

* Update sv.json

Co-authored-by: Jonathan Herlin <Jonte@jherlin.se>
Signed-off-by: axel <mail@axell.me>

* Update sv.json

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: axel <mail@axell.me>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: David Marby <david@dmarby.se>
Co-authored-by: Jonathan Herlin <Jonte@jherlin.se>
2025-08-02 22:17:31 -04:00
Xe Iaso
d5f01dbdb9 fix(web/sha256-browserjs): fix function name (#943)
* fix(web/sha256-browserjs): fix function name

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update changelog

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-08-02 16:05:48 +00:00
lillian-b
70bf58cc63 Add HackLab.TO to known instances (#936)
* Add HackLab.TO to known instances

Signed-off-by: lillian-b <146143737+lillian-b@users.noreply.github.com>

* fix?

Signed-off-by: lillian-b <146143737+lillian-b@users.noreply.github.com>

---------

Signed-off-by: lillian-b <146143737+lillian-b@users.noreply.github.com>
2025-08-02 15:30:34 +00:00
Xe Iaso
0dccf2e009 refactor(web): redo proof of work web worker logic (#941)
* chore(web/js): delete proof-of-work-slow.mjs

This code has served its purpose and now needs to be retired to the
great beyond. There is no replacement for this, the fast implementation
will be used instead.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(web): handle building multiple JS entrypoints and web workers

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(web): rewrite frontend worker handling

This completely rewrites how the proof of work challenge works based on
feedback from browser engine developers and starts the process of making
the proof of work function easier to change out.

- Import @aws-crypto/sha256-js to use in Firefox as its implementation
  of WebCrypto doesn't jump directly from highly optimized browser
  internals to JIT-ed JavaScript like Chrome's seems to.
- Move the worker code to `web/js/worker/*` with each worker named after
  the hashing method and hash method implementation it uses.
- Update bench.mjs to import algorithms the new way.
- Delete video.mjs, it was part of a legacy experiment that I never had
  time to finish.
- Update LibreJS comment to add info about the use of
  @aws-crypto/sha256-js.
- Also update my email to my @techaro.lol address.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(web): don't hard dep webcrypto anymore

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(lib/policy): start the deprecation process for slow

This mostly adds a warning, but the "slow" method is in the process of
being removed. Warn admins with slog.Warn.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(web/js): allow running Anubis in non-secure contexts

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/purge-slow

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-08-02 11:27:26 -04:00
Xe Iaso
8d08de6d9c fix: allow social preview images (#934)
* feat(ogtags): when encountering opengraph URLs, add them to an allow cache

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib): automatically allow any urls in the ogtags allow cache

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(changelog): remove this bit to make it its own PR

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(palemoon): add 180 second timeout

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(palemoon): actually invoke timeout

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-31 08:44:49 -04:00
Xe Iaso
1f7fcf938b fix(lib): add the ability to set a custom slog Logger (#915)
* fix(lib): add the ability to set a custom slog Logger

Closes #864

* test(lib): amend s.check usage

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-31 08:06:35 -04:00
Emir SARI
6ae386a11a fix: polish Turkish translations (#897)
* Polish Turkish translations

* Update tr.json

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Emir SARI <emir_sari@icloud.com>

* Update tr.json

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Emir SARI <emir_sari@icloud.com>

* Update tr.json

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Emir SARI <emir_sari@icloud.com>

* Try to make “From” sound better

Signed-off-by: Emir SARI <emir_sari@icloud.com>

---------

Signed-off-by: Emir SARI <emir_sari@icloud.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-31 07:33:16 -04:00
Sveinn í Felli
963527fb60 Update is.json (#935)
Just one new string.

Signed-off-by: Sveinn í Felli <sv1@fellsnet.is>
2025-07-30 12:08:27 -04:00
Xe Iaso
b81c577106 chore(docs/anubis-cfg): update contact email
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-29 15:38:08 +00:00
Xe Iaso
987c1d7410 chore(go.mod): depend on at least go 1.24.2
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-29 04:06:16 +00:00
Saterfield990
826433e8be build(deps): bump the gomod group (#931)
* build(deps): bump the gomod group

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: npm run assets

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-28 23:47:18 -04:00
Xe Iaso
4a4031450c fix(anubis): store the challenge method in the store (#924)
* fix(lib): reduce challenge string size

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(internal): add host, method, and path to request logs

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(anubis): log when challenges explicitly fail

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): make challenge validation fully deterministic

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(anubis): nuke challengeFor function

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update changelog

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-28 10:57:50 -04:00
dependabot[bot]
8feacc78fc build(deps): bump the github-actions group with 2 updates (#929)
Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `astral-sh/setup-uv` from 6.4.1 to 6.4.3
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](7edac99f96...e92bafb625)

Updates `github/codeql-action` from 3.29.2 to 3.29.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](181d5eefc2...4e828ff8d4)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.29.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jason Cameron  <git@jasoncameron.dev>
2025-07-27 22:47:21 -04:00
Xe Iaso
bca2e87e80 feat(default-rules): add weight to Custom-AsyncHttpClient (#914)
Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-27 00:41:43 +00:00
Xe Iaso
a735770c93 feat(expressions): add segments function to break path into segments (#916)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-25 16:21:08 -04:00
Xe Iaso
bf42014ac3 test: add automated Pale Moon tests (#903)
* test: start work on Pale Moon tests

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(palemoon): rewrite to use ci-images

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: enable palemoon tests

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(palemoon): add some variables

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix: disable tmate

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(palemoon): disable i386 for now

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-25 11:42:08 -04:00
dependabot[bot]
0ef3461816 build(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /docs (#909)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-25 11:18:27 -04:00
Xe Iaso
7d7028d25c test(lib): add a test for the X-Forwarded-For middleware (#912)
Previously the X-Forwarded-For middleware could return two commas in a
row. This is a regression test to make sure that doesn't happen again.

Imports a patch previously exclusive to Botstopper.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-25 10:58:41 -04:00
Xe Iaso
9affd2edf4 chore: expose thoth in lib (#911)
Imports a patch previously exclusive to Botstopper.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-25 10:58:30 -04:00
dependabot[bot]
26b6d8a91a build(deps): bump on-headers and compression in /docs (#910)
Bumps [on-headers](https://github.com/jshttp/on-headers) and [compression](https://github.com/expressjs/compression). These dependencies needed to be updated together.

Updates `on-headers` from 1.0.2 to 1.1.0
- [Release notes](https://github.com/jshttp/on-headers/releases)
- [Changelog](https://github.com/jshttp/on-headers/blob/master/HISTORY.md)
- [Commits](https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0)

Updates `compression` from 1.8.0 to 1.8.1
- [Release notes](https://github.com/expressjs/compression/releases)
- [Changelog](https://github.com/expressjs/compression/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/compression/compare/1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: on-headers
  dependency-version: 1.1.0
  dependency-type: indirect
- dependency-name: compression
  dependency-version: 1.8.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-25 10:53:28 -04:00
Xe Iaso
958992a69a chore: release v1.21.3
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-25 10:30:44 -04:00
Xe Iaso
221d9f2072 fix(web): make the try again button always go back to / (#907)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-25 14:25:04 +00:00
Xe Iaso
bb434a3351 fix(lib): add comprehensive XSS protection logic (#905)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-24 11:24:58 -04:00
Xe Iaso
45ff8f526e fix(lib): add additional validation logic for XSS protection
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-24 14:57:58 +00:00
Xe Iaso
5700512da5 chore: release v1.21.2
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-24 10:47:32 -04:00
Xe Iaso
d40e9056bc fix(lib): block XSS attacks via nonstandard URLs (#904)
* fix(lib): block XSS attacks via nonstandard URLs

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.

Release-status: cut
Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-24 14:05:00 +00:00
Moonchild
21f570962c Pass forward X-Real-IP to nginx backend server (#901)
The TLS termination server sets X-Real-IP to be used by the back-end, but the back-end configuration example doesn't actually extract it so nginx logs (and back-end processing) fails to log or use the visiting IP in any way (it just states `unix:` if using a unix socket like in the example given, or the local IP if forwarded over TCP).

Adding real_ip_header to the config will fix this.

Signed-off-by: Moonchild <moonchild@palemoon.org>
2025-07-24 12:11:53 +00:00
Xe Iaso
1cb1352a44 fix(blog/v1.21.1): we avoid breaking changes
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-22 22:54:22 +00:00
Xe Iaso
a4c08687cc docs: add blogpost for announcing v1.21.1 (#886)
* docs: add release announcement post for v1.21.1

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(v1.21.1): small fixups

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(v1.21.1): spelling fixes

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(v1.21.1): clarify that Bell is trash

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

check-spelling run (pull_request) for Xe/v1.21.1-blogpost

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-07-22 16:42:58 -04:00
Xe Iaso
1a19d7eee4 chore: release v1.21.1 (#887)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-22 16:32:06 -04:00
Sunniva Løvstad
25af5a232f feat(localization): Add in Bokmål and Nynorsk translations (#855)
* feat(localization): add bokmål and nynorsk translations

* feat(localization): update tests for Bokmål and Nynorsk

* docs(localization): document bokmål and nynorsk locales

* fix(locales/nb,nn): remove unicode ellipsis to make tests pass

Signed-off-by: Xe Iaso <me@xeiaso.net>

* style(localization): sort languages to make test output stable

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

check-spelling run (pull_request) for main

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-21 22:37:49 -04:00
Xe Iaso
24d2501187 feat: Russian localization for Anubis (#882)
* feat(localization): Add Russian language translation

* test(localization): ensure Russian translations are tested

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(changelog): update with Russian translation

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Co-authored-by: MichaelAgarkov <michaelagarkov@internet.ru>
2025-07-21 23:14:51 +00:00
ZerionSeven
1dc9525427 Add Finnish localization (#863)
* add Finnish localization

* add fi to supportedLanguages

* add entry for Finnish to CHANGELOG
2025-07-21 18:56:16 -04:00
Xe Iaso
24e3746b0b fix(lib): fix challenge issuance logic (#881)
* fix(lib): fix challenge issuance logic

Fixes #869

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.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): you win this time spell check

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-21 18:53:59 -04:00
HQuest
31184ccd5f Update pt-BR.json (#878)
* Update pt-BR.json

While current version is good enough as a machine translation, it is not natural enough for what a reader would like to read while browsing sites made by native devs - including the subtle nuances from the original English version, now incorporated to the translation instead of plain, literal translations with questionable meanings.

Signed-off-by: HQuest <hquest@gmail.com>

* fix(locales/pt-BR): anubis is from Canada

CA is the ISO country code for Canada, but also the US state code for California.

Co-authored-by: Victor Fernandes  <victorvalenca@gmail.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: HQuest <hquest@gmail.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Victor Fernandes <victorvalenca@gmail.com>
2025-07-21 22:21:47 +00:00
Xe Iaso
e69fadddf1 fix(web/fast): remove event loop thrashing (#880)
Fixes #877

Continued from #879, event loop thrashing can cause stack space
exhaustion on ia32 systems. Previously this would thrash the event loop
in Firefox and Firefox derived browsers such as Pale Moon. I suspect
that this is the ultimate root cause of the bizarre irreproducible bugs
that Pale Moon (and maybe Cromite) users have been reporting since at
least #87 was merged.

The root cause is an invalid boolean statement:

```js
// send a progress update every 1024 iterations. since each thread checks
// separate values, one simple way to do this is by bit masking the
// nonce for multiples of 1024. unfortunately, if the number of threads
// is not prime, only some of the threads will be sending the status
// update and they will get behind the others. this is slightly more
// complicated but ensures an even distribution between threads.
if (
  (nonce > oldNonce) | 1023 && // we've wrapped past 1024
  (nonce >> 10) % threads === threadId // and it's our turn
) {
  postMessage(nonce);
}
```

The logic here looks fine but is subtly wrong as was reported in #877
by a user in the Pale Moon community. Consider the following scenario:

`nonce` is a counter that increments by the worker count every loop.
This is intended to spread the load between CPU cores as such:

| Iteration | Worker ID | Nonce |
| :-------- | :-------- | :---- |
| 1         | 0         | 0     |
| 1         | 1         | 1     |
| 2         | 0         | 2     |
| 3         | 1         | 3     |

And so on.

The incorrect part of this is the boolean logic, specifically the part
with the bitwise or `|`. I think the intent was to use a logical or
(`||`), but this had the effect of making the `postMessage` handler fire
on every iteration. The intent of this snippet (as the comment clearly
indicates) is to make sure that the main event loop is only updated with
the worker status every 1024 iterations per worker. This had the
opposite effect, causing a lot of messages to be sent from workers to
the parent JavaScript context.

This is bad for the event loop.

Instead, I have ripped out that statement and replaced it with a much
simpler increment only counter that fires every 1024 iterations.
Additionally, only the first thread communicates back to the parent
process. This does mean that in theory the other workers could be ahead
of the first thread (posting a message out of a worker has a nonzero
cost), but in practice I don't think this will be as much of an issue as
the current behaviour is.

The root cause of the stack exhaustion is likely the pressure caused by
all of the postMessage futures piling up. Maybe the larger stack size in
64 bit environments is causing this to be fine there, maybe it's some
combination of newer hardware in 64 bit systems making this not be as
much of a problem due to it being able to handle events fast enough to
keep up with the pressure.

Either way, thanks much to @wolfbeast and the Pale Moon community for
finding this. This will make Anubis faster for everyone!

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-21 18:05:24 -04:00
Xe Iaso
5e8ebaeb5d fix(web): amend future leak on proof of work solution (#879)
Possible fix for #877

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. A recursion bomb happens in the
following scenario:

1. A worker sends a message indicating it found a solution to the proof
   of work challenge.
2. The `onmessage` handler for that worker calls `terminate()`
3. Inside `terminate()`, the parent process loops through all other
   workers and calls `w.terminate()` on them.
4. It's possible that terminating a worker could lead to the `onerror`
   event handler.
5. This would create a recursive loop of `onmessage` -> `terminate` ->
   `onerror` -> `terminate` -> `onerror` and so on.

This infinite recursion quickly consumes all available stack space, but
this has never been noticed in development because all of my computers
have at least 64Gi of ram provisioned to them under the axiom paying for
more ram is cheaper than paying in my time spent having to work around
not having enough ram. Additionally, ia32 has a smaller base stack size,
which means that they will run into this issue much sooner than users on
other CPU architectures will.

The fix adds a boolean `settled` flag to prevent termination from
running more than once.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-21 17:50:31 -04:00
searingmoonlight
3e1aaa6273 Remove duplicated string in Filipino language file (#875)
Signed-off-by: searingmoonlight <kitakita@disroot.org>
2025-07-20 23:17:48 -04:00
Jason Cameron
dce7ed2405 Revert "build(deps): bump the gomod group with 6 updates (#873)" (#874) 2025-07-21 01:22:40 +00:00
dependabot[bot]
03758405d3 build(deps): bump the gomod group with 6 updates (#873)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-21 00:57:00 +00:00
dependabot[bot]
eb78ccc30c build(deps-dev): bump the npm group with 3 updates (#872)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-20 20:56:02 -04:00
dependabot[bot]
4156f84020 build(deps): bump the github-actions group with 2 updates (#871)
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-20 20:54:50 -04:00
Xe Iaso
76dcd21582 feat(expressions): add missingHeader function to bot environment (#870)
Also add tests to the bot expressions custom functions.
2025-07-20 19:09:29 -04:00
Josef Moravec
6b639cd911 feat(localization): Add Czech language translation (#849)
* feat(localization): Add Czech language translation

* feat(localization): Add record to CHANGELOG.md
2025-07-18 17:23:19 -04:00
Josef Moravec
a0aba2d74a chore: spelling
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-18 21:22:50 +00:00
hankskyjames777
b485499125 fix untranslated string (#850)
Signed-off-by: hankskyjames777 <54805804+hankskyjames777@users.noreply.github.com>
2025-07-18 13:52:38 -04:00
Nicholas Sherlock
300720f030 fix broken bbolt database cleanup process (#848) (#848)
Closes #820, was broken since #761
2025-07-18 13:51:32 -04:00
Xe Iaso
d6298adc6d chore: fix name of backoff-retry, expose in devcontainer
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-18 17:51:13 +00:00
Xe Iaso
1a9d8fb0cf test(ssh-ci): deflake SSH CI with exponential backoff (#859)
* test(ssh-ci): deflake SSH CI with exponential backoff

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): re-disable in PRs

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-18 17:46:49 +00:00
Xe Iaso
36e25ff5f3 test: add i18n smoke test (#858)
* test: add i18n smoke test

Makes sure that all of the languages that Anubis supports show up when
the challenge page is sent to a client.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(i18n): build anubis so that the smoke test doesn't backoff timeout

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-18 13:30:46 -04:00
Emily Rowlands
c59b7179c3 fix(cmd/anubis): add signal handling to metrics server (#856)
This fixes a bug that was introduced in 68b653b0, in which the call
to metricsServer was passed a plain context.Background without
signal handling.

This commit adds back in the signal handling for the metrics server,
as well as for the Thoth client and storage backend.

Closes: #853

Signed-off-by: Emily Rowlands <emily@erowl.net>
2025-07-18 13:56:52 +00:00
Lothar Serra Mari
59515ed669 docs(known-instances): update list of known instances (#847)
Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-07-17 07:37:37 -04:00
Xe Iaso
4d6b578f93 chore: release v1.21.0 (#844)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-16 21:21:20 -04:00
Xe Iaso
2915c1d209 fix(docs/manifest): k8s typo
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-16 20:35:33 -04:00
Xe Iaso
68b653b099 feat(anubis): add /healthz route to metrics server (#843)
* feat(anubis): add /healthz route to metrics server

Also add health check test for Docker Compose and update documentation
for health checking Anubis with Docker Compose.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-17 00:31:18 +00:00
CXM
509a4f3ce8 fix(localization): fix missing string in template (#835)
* fix(localization): fix missing string in template

* chore: temp place locale
2025-07-16 19:40:27 -04:00
Marcel Bischoff
5c4d8480e6 Add services folder, add Uptime Robot policy definition (#838)
Uptime Robot is a commonly used service for tracking service
interruptions. Additional policy definitions may be beneficial for
services that do publish their IP addresses in use. The list is
additionally aggregated to slightly shorten it.

Signed-off-by: Marcel Bischoff <marcel@herrbischoff.com>
2025-07-16 09:17:48 -04:00
Xe Iaso
132b2ed853 feat(cmd/anubis): capture ja4h fingerprints (#834)
This is not used yet, but it will be part of a larger strategy around
adding/removing weight based on JA4H (and other) fingerprint matches
with Thoth.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 23:31:33 -04:00
Xe Iaso
d28991ce8d fix: race conditions, cookie logic, and the try again button (#833)
* fix(lib): fix race condition when rendering multiple challenge pages at once

Closes #832

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(web): make try again button work

Looks like the intent of this was "try the solution again". This fix
makes the client try the challenge again.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(web): don't block a user if they have an invalid challenge cookie

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-15 00:54:08 +00:00
Xe Iaso
0fd4bb81b8 ci(docs): fix docs image tag names in the right file
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 21:28:22 +00:00
Xe Iaso
603c68fd54 ci(docs): fix docs image tag names
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 21:25:36 +00:00
Xe Iaso
c8f2eb1185 ci(docs): make a new docker image for the docs per commit sha (#831)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 17:23:23 -04:00
Xe Iaso
f6b94dca98 test: add git push smoke test (#830)
* test: add git push smoke test

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(git-push): add git config commands

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(git-push): set upstream

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(git-push): set remote branch name

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 10:42:35 -04:00
Xe Iaso
6d8b98eb3d Revert "test: add git push smoke test"
This reverts commit b9d8275234.
2025-07-14 10:26:47 -04:00
Xe Iaso
b9d8275234 test: add git push smoke test
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 10:25:40 -04:00
Xe Iaso
c2cc1df172 test: add smoke test for git clone (#828)
* test: add smoke test for git clone

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: exempt tests from spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: rename this to git-clone

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: pin ko setup reference

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: don't persist credentials

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: terminating newline

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 14:01:03 +00:00
Xe Iaso
735b2ceb14 fix(default-config): disable system load check by default (#827)
This was causing issues with git clone against highly loaded servers. I
thought that this would be pretty innocuous, but I guess I was wrong.
Oops!

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-14 13:06:56 +00:00
dependabot[bot]
2cb57fc247 build(deps-dev): bump esbuild from 0.25.5 to 0.25.6 in the npm group (#825)
Bumps the npm group with 1 update: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-13 21:28:29 -04:00
dependabot[bot]
61ce581f36 build(deps): bump the gomod group with 3 updates (#823)
Bumps the gomod group with 3 updates: [github.com/gaissmai/bart](https://github.com/gaissmai/bart), [golang.org/x/net](https://github.com/golang/net) and [golang.org/x/text](https://github.com/golang/text).


Updates `github.com/gaissmai/bart` from 0.20.4 to 0.20.5
- [Release notes](https://github.com/gaissmai/bart/releases)
- [Commits](https://github.com/gaissmai/bart/compare/v0.20.4...v0.20.5)

Updates `golang.org/x/net` from 0.41.0 to 0.42.0
- [Commits](https://github.com/golang/net/compare/v0.41.0...v0.42.0)

Updates `golang.org/x/text` from 0.26.0 to 0.27.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: github.com/gaissmai/bart
  dependency-version: 0.20.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: golang.org/x/net
  dependency-version: 0.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: golang.org/x/text
  dependency-version: 0.27.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-13 20:41:26 -04:00
Xe Iaso
3f6750ac7d chore(sponsors): add fabulous systems
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-12 23:08:30 +00:00
Xe Iaso
25d75b352a chore: release v1.21.0-pre3 2025-07-12 17:29:18 -04:00
Xe Iaso
de17823bc7 chore: release v1.21.0-pre2 (#816)
* chore: release v1.21.0-pre2

* chore: disable automated stable package builds for now

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-12 16:57:08 -04:00
Xe Iaso
29622e605d chore(docs): add link to status page in the footer (#814)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-12 13:32:24 -04:00
Jesús Martínez Novo
9fa1795db7 fix(index.templ) centered-div class usage typo (#812)
* Fix centered-div class usage in index.templ

There was a redundant <center> tag around a div with centered-div class. Well, not so redundant because a typo in the class attribute caused it to not apply.

Removed another <center> tag and replaced by a div.centered-div for consistency.

Signed-off-by: Jesús Martínez Novo <martineznovo@gmail.com>

* Fix centered-div class usage in index.templ (continuation)

Template needed to be compiled into go code...

---------

Signed-off-by: Jesús Martínez Novo <martineznovo@gmail.com>
2025-07-11 14:59:17 -04:00
Maxime Louet
fbf69680f5 chore(docs): fix typo in configuration/expressions (#811)
This example code block was missing a closing single quote.

Signed-off-by: Maxime Louet <maxime@saumon.io>
2025-07-11 13:30:27 +00:00
Lothar Serra Mari
c74de19532 docs(known-instances): add rpmfusion.org and wiki.freepascal.org to known instances (#807)
* docs(known-instances): add rpmfusion.org to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* docs(known-instances): add wiki.freepascal.org to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

---------

Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-07-10 14:38:17 -04:00
Evgeni Golov
6dc726013a correct gitea.botPolicies extension to be yaml, not json (#800)
* correct gitea.botPolicies extension to be yaml, not json

while Anubis probably doesn't care about the extension, and would parse a JSON file just fine too, the rest of the page talks about `gitea.botPolicies.yaml`, so let's be consistent

Signed-off-by: Evgeni Golov <evgeni@golov.de>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Evgeni Golov <evgeni@golov.de>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-10 17:10:47 +00:00
Lothar Serra Mari
02304e8f3c docs(known-instances): update list of known instances (#801)
* docs(known-instances): add clew.se to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* docs(known-instances): add tumfatig.net to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

---------

Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-07-10 12:56:46 -04:00
Xe Iaso
607c9791d8 chore(docs): add fly.toml file as a hail mary
Ref #799

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-10 06:05:17 -04:00
Xe Iaso
6b67be86a1 chore(docs/manifest): branded 404 page
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-09 17:06:23 -04:00
Xe Iaso
e02f017153 chore(docs/manifest): remove fastcgi from the nginx config
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-09 17:01:42 -04:00
Xe Iaso
66b39f64af docs: update CHANGELOG for language changes (#793)
Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-09 20:58:08 +00:00
Xe Iaso
944fd25924 chore: use nginx-micro to make the docs image 13 MB (#796)
* chore: use nginx-micro to make the docs image 13 MB

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: update spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-09 20:54:44 +00:00
Xe Iaso
fa3fbfb0a5 feat(blog): incident report for TI-20250709-0001 (#795)
* feat(blog): incident report for TI-20250709-0001

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

check-spelling run (pull_request) for Xe/TI-20250709-0001

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix(blog/TI-20250709-0001): add TecharoHQ/anubis#794

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(blog/TI-20250709-0001): amend grammar

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-07-09 14:56:12 +00:00
Xe Iaso
3c739c1305 fix(internal/thoth): don't block Anubis starting if healthcheck fails (#794)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-09 13:31:28 +00:00
searingmoonlight
cc56baa5c7 feat(localization): Add Filipino language (#775)
* feat(localization): Add Filipino language

* Add tests

* remove duplicated string

* Minor fixes in translation

Signed-off-by: searingmoonlight <scripterrookie12@gmail.com>

---------

Signed-off-by: searingmoonlight <scripterrookie12@gmail.com>
2025-07-09 12:07:26 +00:00
giomba
053d29e0b6 feat(localization): Add Italian language translation (#778)
Signed-off-by: Giovan Battista Rolandi <giomba@glgprograms.it>
2025-07-09 11:49:19 +00:00
Sveinn í Felli
a668095c22 Create is.json (#780)
* Create is.json

Adding Icelandic translation

Signed-off-by: Sveinn í Felli <sv1@fellsnet.is>

* fix(localization): add Icelandic to manifest.json

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Sveinn í Felli <sv1@fellsnet.is>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-09 11:29:40 +00:00
Henri Vasserman
1c4a1aec4a feat(i18n): add Estonian locale (#783)
* feat(i18n): add et locale

* chore: update changelog

* wording

* "feature"
2025-07-09 11:18:11 +00:00
dai
5b8b6d1c94 feat(localization): add Japanese language translation (#772)
* feat(localization): add Japanese language translation

* fix(locales): add Japanese to the manifest

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(locales): fix manifest

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
Co-authored-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-09 07:08:34 -04:00
Joe Brockmeier
0cb6ef76e1 Update apache.mdx (#784)
Was missing the opening stanza to enable mod_proxy for Apache.

Signed-off-by: Joe Brockmeier <jzb@zonker.net>
2025-07-09 07:08:19 -04:00
Henri Vasserman
a900e98b8b fix(localization): HTML language header and forced-language (#787)
* fix: HTML language header and forced-language

* style(changelog): added a couple headers

* add test
2025-07-09 07:04:42 -04:00
Mahid Sheikh
e79cd93b61 docs(installation): Clarify information about private keys and multiple instances (#788)
Signed-off-by: Mahid Sheikh <mahid@standingpad.org>
2025-07-09 10:54:36 +00:00
CXM
d17fc6a174 feat(localization): add Simplified Chinese (#774) 2025-07-09 06:53:08 -04:00
Lothar Serra Mari
95768cb70f docs(known-instances): update list of known instances (#776)
* docs(known-instances): update list of known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* Update metadata

check-spelling run (pull_request) for probably-daily-new-spotted-instances-update

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Lothar Serra Mari <mail@serra.me>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Co-authored-by: Lothar Serra Mari <lotharsm@users.noreply.github.com>
2025-07-07 22:01:14 +00:00
mihugo
ca61b8a05f Update apache.mdx replace nginx with Apache in place (#779)
Signed-off-by: mihugo <mike.github@m3h.com>
2025-07-07 17:17:24 -04:00
dependabot[bot]
1ea1157cd7 build(deps): bump github.com/shirou/gopsutil/v4 in the gomod group (#771)
Bumps the gomod group with 1 update: [github.com/shirou/gopsutil/v4](https://github.com/shirou/gopsutil).


Updates `github.com/shirou/gopsutil/v4` from 4.25.1 to 4.25.6
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v4.25.1...v4.25.6)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v4
  dependency-version: 4.25.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-06 21:21:14 -04:00
dependabot[bot]
44ae5f2e2b build(deps): bump the github-actions group with 2 updates (#770)
Bumps the github-actions group with 2 updates: [dominikh/staticcheck-action](https://github.com/dominikh/staticcheck-action) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `dominikh/staticcheck-action` from 1.3.1 to 1.4.0
- [Release notes](https://github.com/dominikh/staticcheck-action/releases)
- [Changelog](https://github.com/dominikh/staticcheck-action/blob/master/CHANGES.md)
- [Commits](fe1dd0c365...024238d289)

Updates `github/codeql-action` from 3.29.1 to 3.29.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](39edc492db...181d5eefc2)

---
updated-dependencies:
- dependency-name: dominikh/staticcheck-action
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.29.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-07-06 20:51:24 -04:00
Xe Iaso
ea2e76c6ee chore: tag version 1.21.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-06 19:35:06 -04:00
Xe Iaso
4ea0add50d feat(lib/policy/expressions): add system load average to bot expression inputs (#766)
* feat(lib/policy/expressions): add system load average to bot expression inputs

This lets Anubis dynamically react to system load in order to
increase and decrease the required level of scrutiny. High load? More
scrutiny required. Low load? Less scrutiny required.

* docs: spell system correctly

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/load-average

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix(default-config): don't enable low load average feature by default

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-06 20:13:50 +00:00
XLion
289c802a0b feat(localization): Add Traditional Chinese language translation (#759)
* Add translation for Traditional Chinese

* Add translation for Traditional Chinese: test

* Add translation for Traditional Chinese: Add PR number to CHANGELOG

* Add translation for Traditional Chinese: test: remove empty lines

* Add translation for Traditional Chinese: test: remove empty lines
2025-07-06 19:59:00 +00:00
Lothar Serra Mari
543b942be1 docs(known-instances): update list of known instances (#767)
Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-07-06 19:45:18 +00:00
Lothar Serra Mari
edbe1dcfd6 feat(localization): Update German language translation (#764) 2025-07-06 11:25:05 -04:00
Xe Iaso
94db16c0df docs: add emma.pet sponsor
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-06 14:25:27 +00:00
Xe Iaso
c2f46907a1 docs: remove proof of work branding (#763)
* docs(index): start cleanup, remove proof of work from core branding

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(index): rewrite copy, add CELPHASE illustrations

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-06 02:34:52 +00:00
Xe Iaso
6fa5b8e4e0 fix(lib/store/bbolt): run cleanup every hour instead of every 5 minutes (#762)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-06 01:19:44 +00:00
Xe Iaso
f98750b038 fix(lib/store/bbolt): use a multi-bucket flow instead of a single bucket flow (#761)
* fix(lib/store/bbolt): use a multi-bucket flow instead of a single bucket flow

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (push) for Xe/optimize-bbolt

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix(lib/store/bbolt): gracefully handle the obsolete anubis bucket in cleanup

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-07-06 01:16:11 +00:00
Xe Iaso
7d0c58d1a8 fix: make ogtags and dnsbl use the Store instead of memory (#760)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 16:17:46 -04:00
Xe Iaso
e870ede120 docs(known-instances): add git.aya.so
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 16:41:36 +00:00
Xe Iaso
592d1e3dfc docs(known-instances): add Pluralpedia
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 16:40:32 +00:00
Xe Iaso
f6254b4b98 docs(installation): clarify BASE_PREFIX matches the /.within.website endpoints
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 13:47:02 +00:00
Lothar Serra Mari
d19026d693 docs(known-instances): Add Duke University, coinhoards.org (and myself) to known instances (#757)
* docs(known-instances): add Duke University to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* docs(known-instances): add fabulous.systems to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* docs(known-instances): add coinhoards.org to known instances

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* chore(spelling): exempt the known instances page

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Lothar Serra Mari <mail@serra.me>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-05 08:29:44 -04:00
Xe Iaso
7b72c790ab chore: spelling
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 12:29:19 +00:00
Xe Iaso
719a1409ca test(lib/store/bbolt): disable this test case for now
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 04:56:19 +00:00
Xe Iaso
890f21bf47 chore(devcontainer): move playwright to its own devcontainer service (#756)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-05 00:53:45 -04:00
Xe Iaso
93bfe910d8 docs(user/faq): clarify Anubis not being a cryptocurrency miner
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-04 22:49:39 +00:00
Xe Iaso
19d8de784b chore(docs/manifest): enable bbolt in an emptyDir
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-04 21:07:37 +00:00
Xe Iaso
dff2176beb feat(lib): use new challenge creation flow (#749)
* feat(decaymap): add Delete method

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(lib/challenge): refactor Validate to take ValidateInput

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib): implement store interface

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib/store): all metapackage to import all store implementations

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(policy): import all store backends

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib): use new challenge creation flow

Previously Anubis constructed challenge strings from request metadata.
This was a good idea in spirit, but has turned out to be a very bad idea
in practice. This new flow reuses the Store facility to dynamically
create challenge values with completely random data.

This is a fairly big rewrite of how Anubis processes challenges. Right
now it defaults to using the in-memory storage backend, but on-disk
(boltdb) and valkey-based adaptors will come soon.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(decaymap): fix documentation typo

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(lib): fix SA4004

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/store): make generic storage interface test adaptor

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(decaymap): invert locking process for Delete

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib/store): add bbolt store implementation

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: go mod tidy

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(devcontainer): adapt to docker compose, add valkey service

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): make challenges live for 30 minutes by default

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib/store): implement valkey backend

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/store/valkey): disable tests if not using docker

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/policy/config): ensure valkey stores can be loaded

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for Xe/store-interface

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* chore(devcontainer): remove port forwards because vs code handles that for you

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(default-config): add a nudge to the storage backends section of the docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(docs): listen on 0.0.0.0 for dev container support

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(policy): document storage backends

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG and internal links

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(admin/policies): don't start a sentence with as

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: fixes found in review

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-07-04 20:42:28 +00:00
SGHFan
506d8817d5 Update known-instances.md (#755)
Add eBird to instance list

Signed-off-by: SGHFan <62897482+SGHFan@users.noreply.github.com>
2025-07-04 19:54:26 +00:00
Duru Can Celasun
d0fae02d05 feat(localization): Add Turkish language translation (#751)
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-04 00:50:16 -04:00
Xe Iaso
845095c3f6 chore(robots.txt): don't block CCBot
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-04 00:23:21 +00:00
Xe Iaso
2f1e78cc6c chore(docs/manifest): allow common crawl to test with the team
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-04 00:22:43 +00:00
Xe Iaso
7c0996448a chore(default-config): allowlist common crawl (#753)
This may seem strange, but allowlisting common crawl means that scrapers
have less incentive to scrape because they can just grab the data from
common crawl instead of scraping it again.
2025-07-04 00:10:45 +00:00
Xe Iaso
d7a758f805 docs: add BotStopper docs from the git repo (#752)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-03 23:09:45 +00:00
Martin
c121896f9c feat(localization): Add German language translation (#741)
* Add german translation

* Adjust german localization

* Adjust js_finished_reading in german localization

* Mention this change in CHANGELOG.md

* Add test for German localization

* Update lib/localization/locales/de.json

Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Signed-off-by: Martin <31348196+Earl0fPudding@users.noreply.github.com>

* Remove duplicate "leider" in lib/localization/locales/de.json

Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Signed-off-by: Martin <31348196+Earl0fPudding@users.noreply.github.com>

* Update lib/localization/locales/de.json

Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Signed-off-by: Martin <31348196+Earl0fPudding@users.noreply.github.com>

* Update lib/localization/locales/de.json

Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Signed-off-by: Martin <31348196+Earl0fPudding@users.noreply.github.com>

---------

Signed-off-by: Martin <31348196+Earl0fPudding@users.noreply.github.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-03 10:48:17 +00:00
Xe Iaso
888b7d6e77 fix(run/anubis@.service): unique runtimedir per instance (#750)
* fix(run/anubis@.service): unique runtimedir per instance

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-03 10:29:05 +00:00
Martin
0e43138324 feat(localization): Add option for forcing a language (#742)
* Add forcesLanguage option

* Change comments for forced language option

* Add changes to CHANGELOG.md

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-07-02 05:33:00 +00:00
Xe Iaso
c981c23f7e chore: npm run generate
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-02 05:25:10 +00:00
Xe Iaso
9f0c5e974e fix(web/main): remove the success interstitial (#745)
I'm gonna be totally honest here, I'm still not sure why #564 is still
an issue. This is really confusing and I'm going to totally throw out
how Anubis issues challenges and redo it with Valkey (#201, #622).

The problem seems to be that I assume that the makeChallenge function in
package lib is idempotent for the same client. I have no idea why this
would be inconsistent, but for some reason it is and I'm just at a loss
for words as to why this is happening.

This stops the bleeding by improving the UX as a stopgap.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-07-01 23:44:38 +00:00
Victor Fernandes
292c470ada Set cookies to have the Secure flag default to true (#739)
* Set Cookies to use the Secure Flag and default SameSite to None

* Add secure flag test

* Updated changelog and documentation for secure flag option
2025-06-30 14:58:31 -04:00
Rafael Fontenelle
12453fdc00 Fix translations in pt-BR.json (#729)
Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
2025-06-30 14:14:24 -04:00
Xe Iaso
f5b3bf81bc feat: dev container support (#734)
* chore: add devcontainer for Anubis

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(devcontainer): ensure user can write to $HOME

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(devcontainer): forward ports, add launch config

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(devcontainer): add playwright deps

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document devcontainer usage

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci(devcontainer): fix action references

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(devcontainer): fix ko on arm64

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-29 23:41:29 -04:00
dependabot[bot]
1820649987 build(deps): bump the gomod group with 2 updates (#736)
---
updated-dependencies:
- dependency-name: github.com/a-h/templ
  dependency-version: 0.3.906
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: sigs.k8s.io/yaml
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-29 21:32:56 -04:00
dependabot[bot]
14eeeb56d6 build(deps): bump the github-actions group with 2 updates (#735)
Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `astral-sh/setup-uv` from 6.3.0 to 6.3.1
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](445689ea25...bd01e18f51)

Updates `github/codeql-action` from 3.29.0 to 3.29.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](ce28f5bb42...39edc492db)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.29.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-29 20:53:14 -04:00
Martin
d9e0fbe905 feat(cmd): Add custom cookie prefix (#732)
* Add cookie prefix option

* Add explaination comment for TestCookieName

* Rename TestCookieName value from cookie-test-if-you-block-this-anubis-wont-work to cookie-verification

* Add changes to CHANGELOG.md

* Add values to CookieName and TestCookieName in anubis.go required for testcases
2025-06-29 20:03:09 -04:00
Martin
6aa17532da fix: Dynamic cookie domain not working (#731)
* Fix cookieDynamicDomain option not being set in Options struct

* Fix using wrong cookie name when using dynamic cookie domains

* Adjust testcases for new cookie option structs

* Add known words to expect.txt and change typo in Zombocom

* Cleanup expect.txt

* Add changes to changelog

* Bump versions of grpc and apimachinery

* Fix testcases and add additional condition for dynamic cookie domain
2025-06-29 15:38:55 -04:00
Xe Iaso
b1edf84a7c docs(blog/v1.20.0): i am smart
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-27 21:10:02 -04:00
Xe Iaso
d47a3406db docs(blog/v1.20.0): how did CI not catch this?
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-27 19:55:58 -04:00
Xe Iaso
ff5991b5cf docs(blog/v1.20.0): add cover image
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-27 19:20:12 -04:00
Xe Iaso
19f78f37ad docs(blog/v1.20.0): fix typo
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-27 18:59:07 -04:00
Xe Iaso
b0b0a5c08a feat(blog): v1.20.0 announcement post
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-27 18:56:09 -04:00
Rafael Fontenelle
261306dc63 Add Brazilian Portuguese translation (#726)
* Create pt-br.json

Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>

* Enable pt-br locale

Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>

* Fix language code

Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>

* Update and rename pt-br.json to pt-BR.json

Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>

* Update lib/localization/locales/pt-BR.json

Co-authored-by: Victor Fernandes  <victorvalenca@gmail.com>
Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>

---------

Signed-off-by: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Co-authored-by: Victor Fernandes <victorvalenca@gmail.com>
2025-06-27 20:56:56 +00:00
CXM
3520421757 fix: determine bind network from bind address (#714)
* fix: determine bind network from bind address

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-27 17:57:37 +00:00
Laurent Laffont
ad5430612f feat: implement localization system (#716)
* lib/localization: implement localization system

Locale files are placed in lib/localization/locales/. If you add a
locale, update manifest.json with available locales.

* Exclude locales from check spelling

* tests(lib/localization): add comprehensive translations test

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(challenge/metarefresh): enable localization

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix: use simple syntax for localization in templ

Also localize CELPHASE into French according to the wishes of the
artist.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore:(js): fix forbidden patterns

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: add goi18n to tools

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/localization): dynamically determine the list of supported languages

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-27 17:49:15 +00:00
Xe Iaso
c2423d0688 chore: release v1.20.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-27 12:06:22 -04:00
Xe Iaso
a1b7d2ccda feat: dynamic cookie domains (#722)
* feat: dynamic cookie domains

Replaces #685

I was having weird testing issues when trying to merge #685, so I
rewrote it from scratch to be a lot more minimal.

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-26 12:11:59 +00:00
msporleder
7cf6ac5de6 remove incorrect module mentions (#687)
mod_proxy_html is for modifying html content in response bodies. The example configs are using mod_proxy_http.

https://httpd.apache.org/docs/2.4/mod/mod_proxy_html.html
vs
https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html

And anyway mod_proxy + mod_proxy_http should already be installed on almost all systems.

Signed-off-by: msporleder <msporleder@gmail.com>
2025-06-26 10:47:30 +00:00
Martin
59f5b07281 feat: Add option to use HS512 secret for JWT instead of ED25519 (#680)
* Add functionality for HS512 JWT tokens

* Add HS512_SECRET to installation docs

* Update CHANGELOG.md regarding HS512

* Move HS512_SECRET to advenced section in docs

* Move token Keyfunc logic to Server function

* Add Keyfunc to spelling

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Martin Weidenauer <mweidenauer@nanx0as46153.anx.local>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-26 10:06:44 +00:00
Jason Cameron
1562f88c35 chore: Remove unused/dead code (#703)
* chore(xess): remove unused xess templates

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore(checker): remove unused staticHashChecker implementation

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat: add pinact and deadcode to go tools (pinact is used for the gha pinning)

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore: update Docker and kubectl actions to latest versions

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore: update Homebrew action from master to main in workflow files

See  df537ec97f

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore: remove unused go-colorable and tools dependencies from go.sum

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore: update postcss-import and other dependencies to latest versions

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore: update Docusaurus dependencies to version 3.8.1

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* chore: downgrade playwright and playwright-core to version 1.52.0

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-06-25 09:31:33 -04:00
Outvi V
15bd9b6a44 Populate OpenGraph configurations to Opens.OpenGraph (#717)
* chore: read OpenGraph configurations

* docs: update CHANGELOG
2025-06-24 15:12:26 +00:00
dependabot[bot]
1ca531b930 build(deps): bump the gomod group with 4 updates (#709)
Bumps the gomod group with 4 updates: [github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus](https://github.com/grpc-ecosystem/go-grpc-middleware), [github.com/grpc-ecosystem/go-grpc-middleware/v2](https://github.com/grpc-ecosystem/go-grpc-middleware), [google.golang.org/grpc](https://github.com/grpc/grpc-go) and [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery).


Updates `github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus` from 1.0.1 to 1.1.0
- [Release notes](https://github.com/grpc-ecosystem/go-grpc-middleware/releases)
- [Commits](https://github.com/grpc-ecosystem/go-grpc-middleware/compare/providers/prometheus/v1.0.1...v1.1.0)

Updates `github.com/grpc-ecosystem/go-grpc-middleware/v2` from 2.1.0 to 2.3.2
- [Release notes](https://github.com/grpc-ecosystem/go-grpc-middleware/releases)
- [Commits](https://github.com/grpc-ecosystem/go-grpc-middleware/compare/v2.1.0...v2.3.2)

Updates `google.golang.org/grpc` from 1.72.2 to 1.73.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.2...v1.73.0)

Updates `k8s.io/apimachinery` from 0.33.1 to 0.33.2
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.1...v0.33.2)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/grpc-ecosystem/go-grpc-middleware/v2
  dependency-version: 2.3.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: google.golang.org/grpc
  dependency-version: 1.73.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: k8s.io/apimachinery
  dependency-version: 0.33.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-23 15:59:08 -04:00
Xe Iaso
f9259299b9 chore: release v1.20.0-pre2
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-23 15:17:13 -04:00
Xe Iaso
16a4e04027 fix(lib): fix invalid response after success in Chrome (#711)
Closes #564

This one is really dumb. Take a seat and listen to my tale of woe.

While @victorvalenca was working on #693 we ran into a strange issue.
The tests would consistently pass on Firefox but instantly failed on
Chrome. After adding increasingly desperate debugging logs to the mix,
we found out that somehow Chrome was randomizing the contents of its
Accept-Language header. This was making the challenge string get
calculated differently, thus making things spuriously fail. I cannot
figure out what causes Chrome to do this other than you being in an
environment where you have more than one "system language" set.

Either way, this should finally fix this issue and bring peace to the
land forever*.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-23 15:11:56 -04:00
dependabot[bot]
8c79870edb build(deps): bump the github-actions group with 3 updates (#708)
Bumps the github-actions group with 3 updates: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action), [actions-hub/kubectl](https://github.com/actions-hub/kubectl) and [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `docker/setup-buildx-action` from 3.10.0 to 3.11.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](b5ca514318...e468171a9d)

Updates `actions-hub/kubectl` from 1.33.1 to 1.33.2
- [Release notes](https://github.com/actions-hub/kubectl/releases)
- [Commits](f632a31512...d50394b7d7)

Updates `astral-sh/setup-uv` from 6.1.0 to 6.3.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](f0ec1fc3b3...445689ea25)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 3.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions-hub/kubectl
  dependency-version: 1.33.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-23 08:41:04 -04:00
Eric T. Johnson
060b10ea2d fix(web/js): broken progress bar with slow algo (#673)
This was revealed by the reformat in #546.

Signed-off-by: Eric T. Johnson <yut23@users.noreply.github.com>
2025-06-22 20:05:37 -04:00
Xe Iaso
4c74934e9f fix(default-config): Techaro -> Zombocom
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-22 20:04:40 -04:00
Xe Iaso
5870f7072c feat: implement imprint/impressum support (#706)
* feat: implement imprint/impressum support

Closes #362

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(docs/anubis): enable an imprint

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: fix the end of the sentence, comment out a default impressum

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: link back to impressum page

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-22 18:09:37 -04:00
Xe Iaso
3c1d95d61e fix(default-config): off-by-one error in the default thresholds (#701)
I don't know how I missed this in testing.
2025-06-20 11:47:34 -04:00
Jan Alexander Steffens
ab801a3597 Makefile: Build robots2policy (#699)
* Makefile: Build robots2policy

* Update metadata

check-spelling run (pull_request) for build-robots2policy

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-06-20 11:08:56 -04:00
Xe Iaso
ecc716940e chore: release v1.20.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-19 19:32:49 -04:00
Xe Iaso
4948036f39 feat: add default OpenGraph tags to configuration file (#694)
* feat(config): opengraph passthrough configuration

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(ogtags): use config.OpenGraph for configuration

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: wire up ogtags config in most of the app

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(ogtags): return default tags if they are supplied

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: make OpenGraph legal so we have some sanity in reviewing

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): use OpenGraph.Enabled

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): load default config file if one is not specified in spawnAnubis

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(config): fix ST1005

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document open graph defaults and its new home in the policy file

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(installation): point to weight threshold new home

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: rename default to override

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(default-config): add off-by-default opengraph settings to bot policy file

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(anubis): make build

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): fix build

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-19 18:00:44 -04:00
Xe Iaso
7aa732c700 fix(config): actually load threshold config (#696)
* fix(config): actually load threshold config

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): fix test failures

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-19 17:13:01 -04:00
Xe Iaso
226cf36bf7 feat(config): custom weight thresholds via CEL (#688)
* feat(config): add Thresholds to the top level config file

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(config): make String() on ExpressionOrList join the component expressions

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(config): ensure unparseable json fails

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(config): if no thresholds are set, use the default thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(policy): half implement thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(policy): continue wiring things up

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib): wire up thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): handle behavior from legacy configurations

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG, refer to threshold configuration

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): fix build

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(lib): fix U1000

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-06-18 16:58:31 -04:00
Dryusdan
1d5fa49eb0 Bump ai.robots.txt to v1.37 (#689)
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-06-18 13:30:53 -04:00
Lothar Serra Mari
97c1d4f353 docs(known-instances): add extensions.typo3.org (#691)
Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-06-18 08:06:23 -04:00
hydrargyrum
244f1c505a fix(geo): correct typo "counties" to "countries" (#678) 2025-06-17 23:50:42 -04:00
Jason Cameron
ae4d3b0ce5 chore: remove duplicate CHANGELOG entry (#684)
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-06-17 22:49:30 +00:00
prettysunflower
e60c43cdd2 docs(known-instances): add wiki.koha-community.org (#683)
Signed-off-by: prettysunflower <me@prettysunflower.moe>
2025-06-17 12:14:15 -04:00
Jason Cameron
b2b2679bae perf: replace cidranger with bart for significant performance improvements (#675)
* feat: replace cidranger with bart improving performance by 3-20x

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* perf: replace cidranger with bart for IP range checking

- Replace cidranger.Ranger with bart.Lite in RemoteAddrChecker
- Use netip.ParsePrefix instead of net.ParseCIDR for modern IP handling
- Improve performance: 3-20x faster lookups with zero heap allocations
- Update imports to use github.com/gaissmai/bart and net/netip
- Remove cidranger dependency from go.mod

Benchmark results:
- IPv4 lookups: 4x faster (15.58ns vs 63.25ns, 0 vs 2 allocs)
- IPv6 lookups: 3x faster (26.51ns vs 76.96ns, 0 vs 2 allocs)
- Insertions: 20x faster (976ns vs 19,191ns)
- Large tables: 14x faster (5.2ns vs 74.85ns)

* docs: clarify CHANGELOG to not give false impressions

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* perf: optimize string concatenation in RemoteAddrChecker hash generation

Replace fmt.Fprintln with strings.Join for 7x faster performance:
- Before: 935.1 ns/op, 784 B/op, 22 allocs/op
- After: 133.2 ns/op, 192 B/op, 1 alloc/op

The hash is used for JWT cookie validation and error code generation.
Comma separation provides the same deterministic uniqueness as newlines
but with significantly better performance during policy initialization.

* chore: remove accidentally commited string benchmark

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* style: apply Copilot suggestions

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* fix: reference the right var name

i cannot write a merge commit

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-06-17 11:57:55 -04:00
Jason Cameron
e2b46fc5e7 perf: Replace internal SHA256 hashing with xxhash for 4-6x performance improvement (#676)
* perf(internal): Use FastHash for internal hashing
docs: Add xxhash performance improvement to changelog entry
feat(hash): Add fast non-cryptographic hash function

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* test(hash): add xxhash benchmarks and collision tests

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* Update metadata

check-spelling run (pull_request) for json/hash

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-06-16 22:53:53 -04:00
hyperdefined
3437e575d4 chore(sponsors): update canine.tools logo (#672) 2025-06-16 14:09:35 -04:00
Xe Iaso
ae064be710 chore(docs/manifest): it helps if you terminate strings properly
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-16 12:11:04 -04:00
Xe Iaso
e3826df3ab feat: implement a client for Thoth, the IP reputation database for Anubis (#637)
* feat(internal): add Thoth client and simple ASN checker

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(thoth): cached ip to asn checker

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: go mod tidy

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(thoth): minor testing fixups, ensure ASNChecker is Checker

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(thoth): make ASNChecker instances

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(thoth): add GeoIP checker

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(thoth): store a thoth client in a context

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: refactor Checker type to its own package

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(thoth): add thoth mocking package, ignore context deadline exceeded errors

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(thoth): pre-cache private ranges

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib/policy/config): enable thoth ASNs and GeoIP checker parsing

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(thoth): refactor to move checker creation to the checker files

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(policy): enable thoth checks

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(thothmock): test helper function for loading a mock thoth instance

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat: wire up Thoth, make thoth checks part of the default config

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(thoth): mend staticcheck errors

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(admin): add Thoth docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(policy): update Thoth links in error messages

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(docs/manifest): enable Thoth

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: add THOTH_INSECURE for contacting Thoth over plain TCP in extreme circumstances

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(thoth): use mock thoth when credentials aren't detected in the environment

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(cmd/anubis): better warnings for half-configured Thoth setups

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(botpolicies): link to Thoth geoip docs

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-16 11:57:32 -04:00
Xe Iaso
823d1be5d1 chore(docs/manifest): explicitly allow blog RSS feed
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-16 11:50:53 -04:00
Xe Iaso
0c6a820372 chore(docs/manifest): enable OG_PASSTHROUGH
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-16 09:31:56 -04:00
Xe Iaso
81f6380dd4 Add the blog section back (#670)
* Revert "docs/blog: remove (#273)"

This reverts commit df3509ec99.

* chore: intro to the blog post

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-16 09:28:21 -04:00
dependabot[bot]
e5455c02d8 build(deps): bump the github-actions group with 3 updates (#666)
Bumps the github-actions group with 3 updates: [docker/login-action](https://github.com/docker/login-action), [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `docker/login-action` from 3.0.0 to 3.4.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...74a5d142397b4f367a81961eba4e8cd7edddf772)

Updates `actions/attest-build-provenance` from 2.3.0 to 2.4.0
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](db473fddc0...e8998f9491)

Updates `github/codeql-action` from 3.28.19 to 3.29.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](fca7ace96b...ce28f5bb42)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/attest-build-provenance
  dependency-version: 2.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-06-15 21:13:56 -04:00
Colin Finck
1d8033d69e Add ReactOS to known-instances.md (#664)
Signed-off-by: Colin Finck <colin@reactos.org>
2025-06-15 15:30:54 +00:00
Jason Cameron
e0781e4560 feat: add robots2policy CLI to convert robots.txt to Anubis CEL (#657)
* feat: add robots2policy CLI utility to convert robots.txt to Anubis challenge policies

* feat: add documentation for robots2policy CLI tool

* feat: implement crawl delay handling as weight adjustment in Anubis rules

* feat: add various robots.txt and YAML configurations for user agent handling and crawl delays

* test: add comprehensive tests for robots2policy conversion and parsing

* fix: update example URL in usage instructions for robots2policy CLI

* Update metadata

check-spelling run (pull_request) for json/robots2policycli

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* docs: add crawl delay weight adjustment and deny user agents option to robots2policy CLI

* Update cmd/robots2policy/main.go

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* Update cmd/robots2policy/main.go

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* fix(robots2policy): use sigs.k8s.io/yaml

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(config): properly marshal bot policy rules

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(yeetfile): expose robots2policy in libexec

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(yeetfile): put robots2policy in $PATH

Signed-off-by: Xe Iaso <me@xeiaso.net>

* Update metadata

check-spelling run (pull_request) for json/robots2policycli

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* style: reorder imports

* refactor: use preexisting structs in config

* fix: correct flag check in main function

* fix: reorder fields in AnubisRule struct for better alignment

* style: improve alignment of struct fields in AnubisRule and OGTagCache

* Update metadata

check-spelling run (pull_request) for json/robots2policycli

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* fix: add validation for generated Anubis rules from robots.txt

* feat: add batch processing for robots.txt files to generate Anubis CEL policies

* fix: improve usage message and error handling for input file requirement

* refactor: update AnubisRule structure to use ExpressionOrList for improved expression handling

* refactor: reorganize policy definitions in YAML files for consistency and clarity

* fix: correct indentation in blacklist and complex YAML files for consistency

* test: enhance output comparison in robots2policy tests for YAML and JSON formats

* Revert "fix: improve usage message and error handling for input file requirement"

This reverts commit ddcde1f2a3.

* fix: improve usage message and error handling in robots2policy

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-14 23:41:00 -04:00
Lothar Serra Mari
7a195f1595 docs(known-instances): add bugs.scummvm.org and gitlab.postmarketos.org (#661)
* docs(known-instances): add bugs.scummvm.org and gitlab.postmarketos.org

Signed-off-by: Lothar Serra Mari <mail@serra.me>

* chore: clean uri

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Lothar Serra Mari <mail@serra.me>
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
2025-06-14 13:55:55 +00:00
Jason Cameron
2904ff974b refactor(ogtags): optimize URL construction and memory allocations (#647)
* refactor(ogtags): optimize URL construction and memory allocations

* test(ogtags): add benchmarks and memory usage tests for OGTagCache

* refactor(ogtags): optimize OGTags subsystem to reduce allocations and improve request runtime by up to 66%

* Update docs/docs/CHANGELOG.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* refactor(ogtags): optimize URL string construction to reduce allocations

* Update internal/ogtags/ogtags.go

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>

* test(ogtags): add fuzz tests for getTarget and extractOGTags functions

* fix(ogtags): update memory calculation logic

Prev it would say that we had allocated 18pb

=== RUN   TestMemoryUsage
    mem_test.go:107: Memory allocated for 10k getTarget calls: 18014398509481904.00 KB
    mem_test.go:135: Memory allocated for 1k extractOGTags calls: 18014398509481978.00

    Now it's fixed with

    === RUN   TestMemoryUsage
    mem_test.go:109: Memory allocated for 10k getTarget calls:
    mem_test.go:110:   Total: 630.56 KB (0.62 MB)
    mem_test.go:111:   Per operation: 64.57 bytes
    mem_test.go:140: Memory allocated for 1k extractOGTags calls:
    mem_test.go:141:   Total: 328.17 KB (0.32 MB)
    mem_test.go:142:   Per operation: 336.05 bytes

* refactor(ogtags): optimize meta tag extraction for improved performance

* Update metadata

check-spelling run (pull_request) for json/ogmem

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

* chore: update CHANGELOG for recent optimizations and version bump

* refactor: improve URL construction and meta tag extraction logic

* style:  cleanup fuzz tests

---------

Signed-off-by: Jason Cameron <jasoncameron.all@gmail.com>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-13 09:53:10 -04:00
Jason Cameron
3b3080d497 feat: add a strip-base-prefix option (#655)
* style: fix formatting in .air.toml and installation.mdx

* feat: add --strip-base-prefix flag to modify request paths when forwarding

Closes: #638

* refactor: apply structpacking (betteralign)

* fix: add validation for strip-base-prefix and base-prefix configuration

* fix: improve request path handling by cloning request and modifying URL path

* chore: remove integration tests as they are too annoying to debug on my system
2025-06-12 17:46:08 -04:00
Jason Cameron
60ba8e9557 fix(ci): conditionally run SSH jobs for TecharoHQ/anubis repository (#654)
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-06-11 21:18:43 +00:00
Jason Cameron
14c80483a9 fix(gitattributes): update pattern for generated files (#652)
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-06-11 21:00:37 +00:00
Xe Iaso
d1452b6d39 test(ssh-ci): re-enable GOARCH=ppc64le (#651)
This reverts commit 5e95da6b6c.
2025-06-11 14:01:48 -04:00
Xe Iaso
5e95da6b6c test(ssh-ci): disable GOARCH=ppc64le for now
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-11 12:58:32 -04:00
dependabot[bot]
988fc0941b build(deps): bump github.com/cloudflare/circl from 1.6.0 to 1.6.1 (#650)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 16:52:10 +00:00
Xe Iaso
f5140ae57b test: introduce SSH based CI for non-native test hosts (#644)
* feat: ssh based CI

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test: implement SSH ci with caches and github actions

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): fix known hosts secret

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): clone the repo, that's important

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): speed up ci by prebaking the SSH CI image

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): set -euo

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): enable pull_request_target so things work

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): oh goody it's broken

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): add cronjob to rebuild ci runner image

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): also run yeet

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): force git version for yeet

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): run set -x in the container

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): fix yeet?

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): remove yeet for now

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(ssh-ci): disable for PRs for now

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-11 12:50:01 -04:00
Jason Cameron
bbdee34f37 fix(anubis): improve challenge handling and error reporting (#645) 2025-06-11 12:47:06 -04:00
Stephanie Gawroriski
6e2eeb9e65 Update known-instances.md to include SquirrelJME (#643)
Include SquirrelJME, which is an emulator for Java ME 8.

Signed-off-by: Stephanie Gawroriski <xer@multiphasicapps.net>
2025-06-10 23:20:50 +00:00
Xe Iaso
c638653172 feat(lib): implement request weight (#621)
* feat(lib): implement request weight

Replaces #608

This is a big one and will be what makes Anubis a generic web
application firewall. This introduces the WEIGH option, allowing
administrators to have facets of request metadata add or remove
"weight", or the level of suspicion. This really makes Anubis weigh
the soul of requests.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): maintain legacy challenge behavior

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): make weight have dedicated checkers for the hashes

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(data): convert some rules over to weight points

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document request weight

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(CHANGELOG): spelling error

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: fix links to challenge information

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs(policies): fix formatting

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(config): make default weight adjustment 5

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-09 15:25:04 -04:00
Fierelier
0fe46b48cf Make progress bar styling more compatible (UXP, etc) (#636)
* Make progress bar styling more compatible (UXP, etc)

* Add 'Make progress bar styling more compatible (UXP, etc)'

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Fierelier <fier@airmail.cc>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-09 12:19:38 -04:00
David Chandek-Stark
d6e5561768 Adds ability to toggle off stripping of private addrs from XFF (#619)
* Adds ability to toggle off stripping of private addrs from XFF

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: refactor to flow better

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-09 13:33:19 +00:00
dependabot[bot]
6594ae0eef build(deps): bump github/codeql-action in the github-actions group (#635)
Bumps the github-actions group with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.28.18 to 3.28.19
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](ff0a06e83c...fca7ace96b)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.28.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 08:56:41 -04:00
Lothar Serra Mari
ad09f82c3c docs(admin/environments): Prefer IPv6 over IPv4 for apache2 listener directive (#628)
Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-06-09 08:56:30 -04:00
Xe Iaso
372b797f64 chore: go generate
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-08 20:52:22 -04:00
dependabot[bot]
6eaf0e13a2 build(deps): bump the gomod group with 2 updates (#634)
Bumps the gomod group with 2 updates: [github.com/a-h/templ](https://github.com/a-h/templ) and [golang.org/x/net](https://github.com/golang/net).


Updates `github.com/a-h/templ` from 0.3.887 to 0.3.898
- [Release notes](https://github.com/a-h/templ/releases)
- [Changelog](https://github.com/a-h/templ/blob/main/.goreleaser.yaml)
- [Commits](https://github.com/a-h/templ/compare/v0.3.887...v0.3.898)

Updates `golang.org/x/net` from 0.40.0 to 0.41.0
- [Commits](https://github.com/golang/net/compare/v0.40.0...v0.41.0)

---
updated-dependencies:
- dependency-name: github.com/a-h/templ
  dependency-version: 0.3.898
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: golang.org/x/net
  dependency-version: 0.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-08 20:44:25 -04:00
Dryusdan
281b6c5c00 Bump ai.robots.txt to v1.34 (#632) 2025-06-08 14:54:47 -04:00
Jason Cameron
9539668049 style: Some minor fixes (#548)
* chore(deps): update dependencies in go.mod and go.sum

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* refactor: rename variables for clarity in anubis.go and main.go

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* fix(checker): handle error when inserting IP range in ranger

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* fix(tests): simplify boolean checks in header and URL value tests

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* refactor(api): remove unused /test-error endpoint and restrict /make-challenge to development

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* build(deps): update golang-set to v2.8.0 in go.sum

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* Update metadata

check-spelling run (pull_request) for json/stuff

Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
2025-06-07 18:21:22 +00:00
Xe Iaso
8eff57fcb6 chore(docs/manifest): try no-js challenge to see how it impacts false positive rate
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-06 21:40:28 -04:00
Xe Iaso
4ac59c3a79 feat(lib/challenge): HTTP meta refresh challenge method (#623)
* feat(lib/challenge): HTTP meta refresh challenge method

Closes #95

This challenge method enables users that don't (or won't) support
JavaScript to pass Anubis challenges. It works by using HTML meta
refresh directives to ensure that the client is a browser.

This is OFF by default. In order to enable it, an administrator MUST
choose to make the default challenge method `metarefresh`.

TODO(Xe):

- [ ] Documentation on this challenge method
- [ ] Amend wording around Anubis being a proof of work proxy in the docs
- [ ] Add configuration file syntax for the default challenge method and settings
- [ ] Test with early customers

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib/challenge/metarefresh): use this value of err

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: add metarefresh challenge info, Web AI Firewall Utility

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-06 21:18:55 -04:00
Lothar Serra Mari
bee1c22b96 docs(known-instances): add wiki.dolphin-emu.org to known instances (#626)
Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-06-06 13:35:24 -04:00
Xe Iaso
5a7499ea3b fix(lib/challenge): allow challenges to register HTTP routes (#620)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-06 00:26:23 +00:00
Jan Pieter Waagmeester
5f3861ab37 docs: Adjust the name of the cookie to the current "techaro.lol-anubis-auth" (#615)
* docs: Adjust the name of the cookie to the current "techaro.lol-anubis-auth"

Name definition:

76fa3e01a5/anubis.go (L12-L14)

The name changed in 6c0ff3f4d5


Signed-off-by: Jan Pieter Waagmeester <jieter@jieter.nl>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Jan Pieter Waagmeester <jieter@jieter.nl>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-05 20:59:16 +00:00
foosinn
9f1d791991 docs(subrequest-auth): document required policy changes (#613)
* docs(subrequest-auth): document required policy changes

Signed-off-by: foosinn <foosinn@f2o.io>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: foosinn <foosinn@f2o.io>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-05 16:53:18 -04:00
Markus Sommer
76fa3e01a5 docs(known-instances): add Alliance of Hessian Libraries (#611)
Signed-off-by: Markus Sommer <markus@splork.de>
2025-06-04 02:03:57 +00:00
Xe Iaso
f2db43ad4b feat: implement challenge registry (#607)
* feat: implement challenge method registry

This paves the way for implementing a no-js check method (#95) by making
the challenge providers more generic.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib/challenge): rename proof-of-work package to proofofwork

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): make validated challenges a CounterVec

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): annotate jwts with challenge method

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib/challenge/proofofwork): implement tests

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): add smoke tests for known good and known bad config files

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): use challenge.Impl#Issue when issuing challenges

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-04 02:01:58 +00:00
Xe Iaso
ba4412c907 chore(sponsors): add Raptor Computing Systems
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-03 17:49:28 -04:00
Xe Iaso
f184cd81e7 docs(faq): anubis does not mine bitcoin (#609)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-03 07:14:41 -04:00
Xe Iaso
59bfced8bf docs(admin/environments): update suggested HTTP headers
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-03 06:57:37 -04:00
Xe Iaso
780a935cb8 chore(sponsors): add wildbase
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-03 06:18:40 -04:00
Xe Iaso
f4bc1df797 chore(sponsors): add Uberspace
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-02 09:42:13 -04:00
dependabot[bot]
b496c90e86 build(deps): bump github.com/a-h/templ in the gomod group (#601)
Bumps the gomod group with 1 update: [github.com/a-h/templ](https://github.com/a-h/templ).


Updates `github.com/a-h/templ` from 0.3.865 to 0.3.887
- [Release notes](https://github.com/a-h/templ/releases)
- [Changelog](https://github.com/a-h/templ/blob/main/.goreleaser.yaml)
- [Commits](https://github.com/a-h/templ/compare/v0.3.865...v0.3.887)

---
updated-dependencies:
- dependency-name: github.com/a-h/templ
  dependency-version: 0.3.887
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-01 23:39:42 -04:00
dependabot[bot]
ec73bcbaf1 build(deps): bump docker/build-push-action in the github-actions group (#602)
Bumps the github-actions group with 1 update: [docker/build-push-action](https://github.com/docker/build-push-action).


Updates `docker/build-push-action` from 6.17.0 to 6.18.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](1dc7386353...263435318d)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-01 23:39:05 -04:00
dependabot[bot]
8d19eed200 build(deps-dev): bump esbuild from 0.25.4 to 0.25.5 in the npm group (#600)
Bumps the npm group with 1 update: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.25.4 to 0.25.5
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.4...v0.25.5)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-01 23:38:45 -04:00
Xe Iaso
ec733e93a5 v1.19.1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-01 17:17:24 -04:00
Xe Iaso
51c384eefd fix(data/bots): bring back ai-robots-txt.yaml
Closes #599

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-01 17:15:00 -04:00
Xe Iaso
44d5ec0b6e chore: release version v1.19.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-01 16:35:03 -04:00
Xe Iaso
3bc9040a96 chore: bump yeet to v0.6.0
Gives us many nice things like:

* Windows support for yeet (modulo TecharoHQ/yeet#29)
* Removes the dependency on /bin/sh or /bin/bash thanks to
  mvdan.cc/sh/v3
* Checksum-compliant reproducible builds by default

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-06-01 16:33:08 -04:00
Corry Haines
de7dbfe6d6 Split up AI filtering files (#592)
* Split up AI filtering files

Create aggressive/moderate/permissive policies to allow administrators to choose their AI/LLM stance.

Aggressive policy matches existing default in Anubis.

Removes `Google-Extended` flag from `ai-robots-txt.yaml` as it doesn't exist in requests.

Rename `ai-robots-txt.yaml` to `ai-catchall.yaml` as the file is no longer a copy of the source repo/file.

* chore: spelling

* chore: fix embeds

* chore: fix data includes

* chore: fix file name typo

* chore: Ignore READMEs in configs

* chore(lib/policy/config): go tool goimports -w

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-06-01 20:21:18 +00:00
minihoot
77e0bbbce9 add my site to known-instances.md (#595)
Signed-off-by: minihoot <70825884+minihoot@users.noreply.github.com>
2025-06-01 15:28:16 +00:00
Zohiu
b4b5d2f82e docs(known-instances): add catgirl.click (#597)
Signed-off-by: Zohiu <102434603+Zohiu@users.noreply.github.com>
2025-06-01 14:55:02 +00:00
Aleksei
988fff77f1 docs(known-instances): add openwrt.org (#594)
Signed-off-by: Aleksei <Aloki@users.noreply.github.com>
2025-06-01 13:13:52 +00:00
Corry Haines
0d9ebebff6 Opt-in policies for OpenAI and MistralAI bots (#590)
* Define OpenAI bot ALLOW policies

Allows OpenAI bots to be allowlisted at the choice of the Anubis administrator. None are enabled by default.

* Define MistralAI bot ALLOW policy

* chore: spelling
2025-05-31 16:48:57 -04:00
Jason
ba00cdacd2 docs(known-instances): Add Gitea to the known instances list (#591)
Signed-off-by: Jason <57271945+jesentz@users.noreply.github.com>
2025-05-31 14:20:39 -04:00
Corry Haines
68a71c6a99 Add Applebot definition (#589)
* Add Applebot definition

Adds Apple's search indexing bot, and allowlists it by default.

Allowlisted by default because it is equivalent to Googlebot/Bingbot. Remove Applebot from `ai-robots-txt.yaml` for the same reasons.

Remove `Applebot-Extended` from `ai-robots-txt.yaml` as it has no effect.

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-31 10:18:32 -04:00
Xe Iaso
fbbab5a035 feat(lib): annotate cookies with what rule was passed (#576)
* feat(lib): annotate cookies with what rule was passed

Anubis JWTs now contain a policyRule claim with the cryptographic hash
of the rule that it passed. This is intended to help with a future move
away from proof of work being the default.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): fix cookie storage logic

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-30 14:42:02 -04:00
Jason Cameron
28ab29389c style(bench): small cleanup (#546)
* fix(bench): await benchmark loop and adjust outline styles in templates

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* refactor: remove unused showContinueBar function and clean up video error handling

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* style: format code for consistency and readability using prettier

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-05-30 17:57:56 +00:00
Xe Iaso
497005ce3e fix(lib): only use the first five characters of Accept-Language header values (#588)
For some reason, Google Chrome will randomly send a "full"
Accept-Language header, and other times it will send a "partial"
Accept-Language header. This makes the challenge construction
inconsistent.

This commit fixes this issue by only considering up to the first five
characters of the Accept-Language header when making a challenge string.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-30 13:15:03 -04:00
Xe Iaso
669eb4ba4b fix(web): show Anubis version number on challenge pages (#587)
Closes #565

The page already had the version number embedded into it, but that was
not printed to the page. This prints the version number set at compile
time to the page.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-30 16:23:27 +00:00
Kian Kasad
6c4e739b0b feat(lib): Add anubis_proxied_requests_total metric (#570)
Adds a new counter metric which counts the number of requests proxied to
the upstream target, labeled with the host name of the request.
2025-05-30 12:21:04 -04:00
Xe Iaso
c8635357dc feat(yeetfile): build GOARCH=ppc64le packages (#583)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-30 00:35:56 -04:00
Xe Iaso
0ed905fd4e fix(internal/test): skip integration tests if SKIP_INTEGRATION is set (#586)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-30 00:49:53 +00:00
Xe Iaso
cd8a7eb2e2 feat(data): add x-firefox-ai default challenge rule (#580)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-28 21:08:39 +00:00
Xe Iaso
22c47f40d1 feat(expressions): add randInt function to allow making rules nondeterministic (#578)
This seems counter-intuitive at first glance, but let me cook.

One of the problems with Anubis is that the rule matching is super
deterministic. This means that attackers can figure out what patterns
they are hitting and change things to bypass them.

The randInt function lets you have rulesets behave nondeterministically.
This is a very easy way to hang yourself, but can be great to
psychologically mess with scraper operators. Consider this rule:

```yaml
- name: deny-lightpanda-sometimes
  action: DENY
  expression:
    all:
      - userAgent.matches("LightPanda")
      - randInt(16) >= 4
```

It would match about 75% of the time.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-28 16:36:27 -04:00
Xe Iaso
669671bd46 fix(internal): register mime type for .mjs files (#577)
Closes #575

I'm gonna be totally honest, I'm not sure if this is needed. However,
measure twice, cut once.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-28 13:52:48 +00:00
dependabot[bot]
6c247cdec8 build(deps): bump k8s.io/apimachinery in the gomod group (#524)
Bumps the gomod group with 1 update: [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery).


Updates `k8s.io/apimachinery` from 0.33.0 to 0.33.1
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.0...v0.33.1)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-version: 0.33.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 09:41:25 -04:00
Kian Kasad
eeae28f459 feat(cli): Add --version flag (#572) 2025-05-28 04:16:44 +00:00
jordigh
9ba10262e3 add Weblate to known-instances.md (#571)
Signed-off-by: jordigh <jordigh@octave.org>
2025-05-28 00:03:04 +00:00
dependabot[bot]
a28a3d155a build(deps): bump astral-sh/setup-uv in the github-actions group (#558)
Bumps the github-actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 6.0.1 to 6.1.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](6b9c6063ab...f0ec1fc3b3)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 11:12:31 -04:00
Anna
086f43e3ca Create Anubis OpenRC init.d script (#561)
Signed-off-by: Anna @CyberTailor <cyber@sysrq.in>
2025-05-27 01:58:59 +00:00
Xe Iaso
fa1f2355ea v1.19.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-25 14:10:22 -04:00
Xe Iaso
0a56194825 docs(admin): add wordpress docs (#552)
Closes #551

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-24 17:00:37 -04:00
Jason Cameron
93e2447ba2 fix(expression): add validation for empty expression list in CEL (#545)
* fix(expression): add validation for empty ExpressionOrList

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* fix(imports): block empty file imports with improved error checking logic

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* docs(expression): improve validation to error on empty CEL expressions

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-05-23 18:14:31 -04:00
Xe Iaso
51f875ff6f docs(native-install): vague gesturing at distribution package managers (#544)
Closes #530

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-23 16:51:45 +00:00
Xe Iaso
555a188dc3 fix(lib): record challenges issused over embedded HTML (#543)
Closes #531

This changes `anubis_challenges_issued` to be a vector counter that
records the challenge issuance method.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-23 12:45:41 -04:00
James Renken
6f08bcb481 feat: add TARGET_SNI to allow overriding the TLS handshake hostname when forwarding requests (#529)
* feat: add TARGET_SNI to allow overriding the TLS handshake hostname when forwarding requests

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-23 16:27:35 +00:00
Dryusdan
11081aac08 Bump AI-robots.txt rules to version 1.31 (#538)
* Bump AI-robots.txt rules to version 1.31

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-23 16:15:12 +00:00
Nathan Price
c78d830ecb docs/docs/admin/native-install.mdx: correct the path for the default configuration file installation (#535)
Using the native-install instructions, default.env was installed as /etc/anubis rather than /etc/anubis/default.env
2025-05-22 18:34:06 +00:00
Max Chernoff
5e7bfa5ec2 docs: REDIRECT_DOMAINS must include port numbers (#521)
For websites hosted on non-standard ports (`https://example:com:8443`,
`http://www.example.net:8080`, etc.), the domains listed in
`REDIRECT_DOMAINS` must contain the port number. This commit documents
this requirement on the Installation page.

Fixes #517.

Signed-off-by: Max Chernoff <git@maxchernoff.ca>
2025-05-19 00:38:46 +00:00
dependabot[bot]
7b8953303d build(deps): bump the github-actions group with 4 updates (#523)
Bumps the github-actions group with 4 updates: [docker/build-push-action](https://github.com/docker/build-push-action), [actions-hub/kubectl](https://github.com/actions-hub/kubectl), [check-spelling/check-spelling](https://github.com/check-spelling/check-spelling) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `docker/build-push-action` from 6.16.0 to 6.17.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](14487ce63c...1dc7386353)

Updates `actions-hub/kubectl` from 1.33.0 to 1.33.1
- [Release notes](https://github.com/actions-hub/kubectl/releases)
- [Commits](e81783053d...f632a31512)

Updates `check-spelling/check-spelling` from 0.0.24 to 0.0.25
- [Release notes](https://github.com/check-spelling/check-spelling/releases)
- [Commits](67debf5066...c635c2f3f7)

Updates `github/codeql-action` from 3.28.17 to 3.28.18
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](60168efe1c...ff0a06e83c)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions-hub/kubectl
  dependency-version: 1.33.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: check-spelling/check-spelling
  dependency-version: 0.0.25
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.28.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 00:35:59 +00:00
Xe Iaso
a6045d6698 fix(lib): properly clear out test cookie (#522)
Closes #520

For some reason, Chrome and Firefox are very picky over what they use to
match cookies that need to be deleted. Listen to me for my tale of woe:

The basic problem here is that cookies were an early hack added on the
side of the HTTP spec and they're basically impossible to upgrade or
change because who knows what relies on the exact behavior cookies use.
As a result, cookies don't just match by name, but by every setting that
exists on them. You can also have two cookies with the same name but
different values. This spec is a nightmare lol.

Even more fun: browsers will make up values for cookies if they aren't
set, meaning that getting a challenge token at `/docs` is semantically
different than a challenge token you got from `/`.

This PR fixes this issue by explicitly setting the "make sure cookie
support is working" cookie's path to `/`, meaning that it will always be
sent. Additionally, cookies are expired by setting the expiry time to
one minute in the past.

Hopefully this will fix it. I'm testing this locally and it seems to
work fine.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-18 22:41:26 +00:00
Lenni
e31e1ca5e7 Add reddit.nerdvpn.de to known instances (#518)
Signed-off-by: Lenni <87639068+Lenni-builder@users.noreply.github.com>
2025-05-18 20:27:36 +00:00
Xe Iaso
50e030d17e chore(docs/deploy): move to new cluster (#519)
* chore(docs/deploy): move to new cluster

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-18 20:25:12 +00:00
Xe Iaso
b640c567da feat(lib): ensure that clients store cookies (#501)
* feat(lib): ensure that clients store cookies

If a client is misconfigured and does not store cookies, then they can
get into a proof of work death spiral with Anubis. This fixes the
problem by setting a test cookie whenever the user gets hit with a
challenge page. If the test cookie is not there at challenge pass time,
then they are blocked. Administrators will also get a log message
explaining that the user intentionally broke cookie support and that this
behavior is not an Anubis bug.

Additionally, this ensures that clients being shown a challenge support
gzip-compressed responses by showing the challenge page at gzip level 1.
This level is intentionally chosen in order to minimize system impacts.

The ClearCookie function is made more generic to account for cookie
names as an argument. A correlating SetCookie function was also added to
make it easier to set cookies.

* chore(lib): clean up test code

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-16 13:03:40 -04:00
Dryusdan
9e9982ab5d feat(apps): Make SASL login work on bookstack with Anubis (#502)
* Make SASL login work on bookstack with Anubis

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-16 17:01:34 +00:00
Xe Iaso
3b98368aa9 feat(apps): add SearXNG instance tracker policy and Qualys Labs SSL testing rules (#512)
* feat(apps): add SearXNG instance tracker policy

* feat(apps): add Qualys SSL Labs policy

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: hyperdefined <contact@hyper.lol>
2025-05-16 16:59:15 +00:00
OatmealDome
76849531cd feat: add TARGET_HOST to allow overriding the Host header when forwarding requests (#507)
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-16 16:46:47 +00:00
Dryusdan
961320540b Bump AI-robots.txt rules to version 1.30 (#509)
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-16 16:40:25 +00:00
Xe Iaso
91c21fbb4b docs: add HTMX workaround (#511)
* docs: add HTMX workaround

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore: spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-16 16:37:39 +00:00
Xe Iaso
caf69be97b fix(systemd): add RuntimeDirectory (#510)
Closes #508

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-16 16:17:41 +00:00
Xe Iaso
6a12efee08 fix(lib): make ClearCookie respect the dynamic cookie name (#500)
Previously this made ClearCookie always clear cookies by name even when
CookieDomain was set. This change fixes this and adds tests to make sure
that this doesn't happen again.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-13 15:29:39 -04:00
Xe Iaso
5e1abdd31c docs(known-instances): untypo proxmox
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-13 11:16:55 -04:00
Xe Iaso
cb3bbbd4c8 docs(known-instances): add some entries to the list (#497)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-13 14:59:33 +00:00
Xe Iaso
d51b7ec0aa chore(spelling): add weblate
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-13 10:04:30 -04:00
Xe Iaso
b164048dcf chore(sponsors): add weblate
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-13 10:02:42 -04:00
Xe Iaso
6c0ff3f4d5 fix(lib): use a new cookie per domain when COOKIE_DOMAIN is set (#490)
Also properly re-brand the cookies so that some of the /x/ heritage is
lost.

This will invalidate existing cookies and probably affects tests.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-12 09:23:42 -04:00
dependabot[bot]
9009596ded build(deps-dev): bump the npm group with 3 updates (#496)
Bumps the npm group with 3 updates: [cssnano](https://github.com/cssnano/cssnano), [cssnano-preset-advanced](https://github.com/cssnano/cssnano) and [esbuild](https://github.com/evanw/esbuild).


Updates `cssnano` from 7.0.6 to 7.0.7
- [Release notes](https://github.com/cssnano/cssnano/releases)
- [Commits](https://github.com/cssnano/cssnano/compare/cssnano@7.0.6...cssnano@7.0.7)

Updates `cssnano-preset-advanced` from 7.0.6 to 7.0.7
- [Release notes](https://github.com/cssnano/cssnano/releases)
- [Commits](https://github.com/cssnano/cssnano/compare/cssnano-preset-advanced@7.0.6...cssnano-preset-advanced@7.0.7)

Updates `esbuild` from 0.25.3 to 0.25.4
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.3...v0.25.4)

---
updated-dependencies:
- dependency-name: cssnano
  dependency-version: 7.0.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: cssnano-preset-advanced
  dependency-version: 7.0.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: esbuild
  dependency-version: 0.25.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 00:19:52 -04:00
Xe Iaso
f4298b993f fix(bots/phrik): add IPv6 address for phrik (#494)
Tracks https://gitlab.archlinux.org/archlinux/infrastructure/-/merge_requests/950
2025-05-11 14:04:44 -04:00
Jason Cameron
659b577e0e feat(ci): use dynamic repository owner and name in Docker actions (#487)
* feat(ci): use dynamic repository owner and name in Docker actions

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): support forks

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): support forks

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): add debug output for Docker repository information

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): update Docker image naming convention in workflow

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): set lowercase image name in Docker workflow

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): remove json/gha branch from Docker workflow triggers

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(ci): simplify Docker registry configuration in workflow

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-05-09 20:18:53 -04:00
Jason Cameron
2b103a9ec7 fix(jwt): update nonce value in challenge JWT cookie to be a string (#486)
Closes https://github.com/TecharoHQ/anubis/issues/468

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-05-09 20:10:28 -04:00
Xe Iaso
a0805cad16 chore(go.mod): move yeet to be a go tool (#485)
This means that yeet's version will be managed by `go.mod` and
auto-bumped with dependabot. This removes human error from the equation
and ensures that Anubis is always built with the newest version of yeet.

This also makes it trivial to make your own local packages for testing:

```text
go tool yeet
```

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-09 18:33:44 +00:00
Henri Vasserman
22ada6251f test(playwright): Add Docker and Podman support (#433)
* test(playwright): Add support to run tests in Docker/Podman

* fix command name

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Henri Vasserman <henv@hot.ee>

* up the pw version as it is in package.json

* add convenience npm scripts

* chore: changelog update

Also removed a period from my other item.

* chore: fix spelling

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Henri Vasserman <henv@hot.ee>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-09 13:58:55 -04:00
Xe Iaso
092b80ba55 ci(check-spelling): allow release names in spelling allowlists (#483)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-09 17:22:26 +00:00
Paul Wilde
3bd2e4a584 Overhaul anubis.freebsd (#427)
* Overhaul anubis.freebsd

Some changes here to reflect the discussion in pull request 274 regarding the `anubis_env`, `anubis_env_file` and `anubis_args` variables.
At the risk of improving personal choices in configuration with a minor amount more complexity, this new script now allows for the use of all three of these, together, with no interference between them all 
i.e. 
- if `anubis_env_file` is set, environment variables will be taken from this file
- if `anubis_env` is set, environment variables will be taken from this string of variables, and override matching variables set in `anubis_env_file`
- if `anubis_args` is set, runtime parameters will be taken from this string and override matching ones in both `anubis_env_file` and `anubis_env`

Thanks to @dlangille for the advice with this.

Signed-off-by: Paul Wilde <31094984+pswilde@users.noreply.github.com>

* Update CHANGELOG.md

Signed-off-by: Paul Wilde <31094984+pswilde@users.noreply.github.com>

* Remove unnecessary comment line

Signed-off-by: Paul Wilde <31094984+pswilde@users.noreply.github.com>

* Correct helper information for anubis_env_file

Signed-off-by: Paul Wilde <31094984+pswilde@users.noreply.github.com>

---------

Signed-off-by: Paul Wilde <31094984+pswilde@users.noreply.github.com>
2025-05-09 17:10:06 +00:00
Josh Soref
39dc3c0317 ci: add check-spelling (#462)
This is a basic spell checker to make sure words are spelled correctly.

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-09 17:02:41 +00:00
Xe Iaso
624b935ecc feat: add TARGET_INSECURE_SKIP_VERIFY setting to allow self-signed HTTPS backends (#426)
Also discourage the use of this by putting it in a "scary" section of
the configuration docs.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-09 16:56:24 +00:00
Jason Cameron
529f65674e style: apply structpack & goimport (#469)
* refactor: reorder import statements in fetch.go and fetch_test.go

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* fix: optimize struct field alignment to reduce memory usage

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-05-09 12:54:15 -04:00
Xe Iaso
8c7640aa09 v1.18.0: Varis zos Galvus
The big ticket feature in this release is [CEL expression matching support](https://anubis.techaro.lol/docs/admin/configuration/expressions). This allows you to tailor your approach for the individual services you are protecting.

These can be as simple as:

```yaml
- name: allow-api-requests
  action: ALLOW
  expression:
    all:
      - '"Accept" in headers'
      - 'headers["Accept"] == "application/json"'
      - 'path.startsWith("/api/")'
```

Or as complicated as:

```yaml
- name: allow-git-clients
  action: ALLOW
  expression:
    all:
      - >-
        (
          userAgent.startsWith("git/") ||
          userAgent.contains("libgit") ||
          userAgent.startsWith("go-git") ||
          userAgent.startsWith("JGit/") ||
          userAgent.startsWith("JGit-")
        )
      - '"Git-Protocol" in headers'
      - headers["Git-Protocol"] == "version=2"
```

The docs have more information, but here's a tl;dr of the variables you have access to in expressions:

| Name            | Type                  | Explanation                                                                                                                               | Example                                                      |
| :-------------- | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------- |
| `headers`       | `map[string, string]` | The [headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers) of the request being processed.                        | `{"User-Agent": "Mozilla/5.0 Gecko/20100101 Firefox/137.0"}` |
| `host`          | `string`              | The [HTTP hostname](https://web.dev/articles/url-parts#host) the request is targeted to.                                                  | `anubis.techaro.lol`                                         |
| `method`        | `string`              | The [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods) in the request being processed.                    | `GET`, `POST`, `DELETE`, etc.                                |
| `path`          | `string`              | The [path](https://web.dev/articles/url-parts#pathname) of the request being processed.                                                   | `/`, `/api/memes/create`                                     |
| `query`         | `map[string, string]` | The [query parameters](https://web.dev/articles/url-parts#query) of the request being processed.                                          | `?foo=bar` -> `{"foo": "bar"}`                               |
| `remoteAddress` | `string`              | The IP address of the client.                                                                                                             | `1.1.1.1`                                                    |
| `userAgent`     | `string`              | The [`User-Agent`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent) string in the request being processed. | `Mozilla/5.0 Gecko/20100101 Firefox/137.0`                   |

This will be made more elaborate in the future. Give me time. This is a [simple, lovable, and complete](https://longform.asmartbear.com/slc/) implementation of this feature so that administrators can get hacking ASAP.

Other changes:

- Use CSS variables to deduplicate styles
- Fixed native packages not containing the stdlib and botPolicies.yaml
- Change import syntax to allow multi-level imports
- Changed the startup logging to use JSON formatting as all the other logs do.
- Added the ability to do [expression matching with CEL](./admin/configuration/expressions.mdx)
- Add a warning for clients that don't store cookies
- Disable Open Graph passthrough by default ([#435](https://github.com/TecharoHQ/anubis/issues/435))
- Clarify the license of the mascot images ([#442](https://github.com/TecharoHQ/anubis/issues/442))
- Started Suppressing 'Context canceled' errors from http in the logs ([#446](https://github.com/TecharoHQ/anubis/issues/446))

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-09 12:24:23 -04:00
Xe Iaso
b1c276db9f Revert "fix(js): use pure JS SHA256 library, refactor (#471)" (#475)
This reverts commit 7b84904d15.
2025-05-08 22:22:08 +00:00
Xe Iaso
7b84904d15 fix(js): use pure JS SHA256 library, refactor (#471)
* fix(js): use pure JS SHA256 library, refactor

Closes #458

Additionally, I made a horrifying discovery: Firefox seems to actively
hinder performance if you are using more than one Worker per page. It
does not spread the load out across cores like I expected. Instead it
seems to make that one Worker thrash and have to constantly context
switch, which caused a lot of slowdown.

The benchmarks in #155 continue to be the best contribution ever made to
Anubis. What clued me into there being a problem here was the fact that
the "slow" algorithm was faster than the "fast" algorithm on my laptop.
This made no intuitive sense to me so I dug further.

Either way I think this is a Firefox bug at its core, but for now we
have to work around it by doing the hacky terrible thing that I hate.

I also swapped the SHA256 operations to @aws-crypto/sha256-js on the
advice of a trusted cryptography expert. I don't know what performance
differences this makes, but I'm getting 150-225 kilohashes per second,
which is pretty dang good.

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(js): apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(js): use fast algo for fast worker

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-08 17:38:51 -04:00
David Chandek-Stark
7f0f691ba5 Trim spaces from elements of split XFF string (#459)
* Trim spaces from elements of split XFF string

* Adds test to verify that spaces in original XFF header are handled
2025-05-08 03:35:42 +00:00
Jason Cameron
1c6c07939a feat(log): implement custom error log filter to suppress "context can… (#470)
* feat(log): implement custom error log filter to suppress "context canceled" messages

fixes #446

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

* feat(log): suppress 'context canceled' errors in HTTP logs

Signed-off-by: Jason Cameron <git@jasoncameron.dev>

---------

Signed-off-by: Jason Cameron <git@jasoncameron.dev>
2025-05-07 23:28:50 -04:00
Michal Čihař
c633b3349e docs: add missing subrequest auth configuration (#463)
* The IP address and Host should be included
* The Content-Length removed to avoid Anubis waiting for the body, which is not passed because subrequest is always using GET.

Signed-off-by: Michal Čihař <michal@weblate.org>
2025-05-07 23:28:51 +00:00
dependabot[bot]
2e54e839f1 build(deps): bump the gomod group across 1 directory with 4 updates (#457)
* build(deps): bump the gomod group across 1 directory with 4 updates

Bumps the gomod group with 4 updates in the / directory: [github.com/a-h/templ](https://github.com/a-h/templ), [github.com/playwright-community/playwright-go](https://github.com/playwright-community/playwright-go), [golang.org/x/net](https://github.com/golang/net) and [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery).


Updates `github.com/a-h/templ` from 0.3.857 to 0.3.865
- [Release notes](https://github.com/a-h/templ/releases)
- [Changelog](https://github.com/a-h/templ/blob/main/.goreleaser.yaml)
- [Commits](https://github.com/a-h/templ/compare/v0.3.857...v0.3.865)

Updates `github.com/playwright-community/playwright-go` from 0.5101.0 to 0.5200.0
- [Release notes](https://github.com/playwright-community/playwright-go/releases)
- [Commits](https://github.com/playwright-community/playwright-go/compare/v0.5101.0...v0.5200.0)

Updates `golang.org/x/net` from 0.39.0 to 0.40.0
- [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0)

Updates `k8s.io/apimachinery` from 0.32.3 to 0.33.0
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.3...v0.33.0)

---
updated-dependencies:
- dependency-name: github.com/a-h/templ
  dependency-version: 0.3.865
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/playwright-community/playwright-go
  dependency-version: 0.5200.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: golang.org/x/net
  dependency-version: 0.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: k8s.io/apimachinery
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: go mod tidy && npm run assets

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: use playwright managed by npm

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-07 17:48:10 -04:00
Xe Iaso
3701b2bc3d ci(go): fix govulncheck (#464)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-07 13:42:28 +00:00
Xe Iaso
6200c4c123 docs(known-instances): add gitlab.freedesktop.org
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-07 08:57:26 -04:00
Xe Iaso
16412a8bf9 ci: add govulncheck (#456)
This is intended to catch low-hanging fruit.

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-06 14:07:55 +00:00
hyperdefined
2e9b18a510 chore(sponsors): add canine.tools (#450)
* chore(sponsors): add canine.tools

* chore(sponsors): update canine.tools logo
2025-05-05 20:31:10 -04:00
Xe Iaso
e64987ef90 Pre-release: v1.18.0-pre1
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-05 17:07:10 -04:00
Xe Iaso
8ff28fbb33 chore(static/img): add mascot attributions to the repo (#448)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-05 16:29:16 +00:00
Xe Iaso
e953b514fa feat(js): stop execution if the client disabled cookies (#438)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-05 11:10:26 -04:00
Josh Soref
52a6a65cc4 Spelling (#445)
* link: stackoverflow explanation of cookies

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: bazaar

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: enabling

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expressions

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implicitly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: intermediate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: nonexistent

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: open graph

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: really, really,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: receive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-05-05 10:52:02 -04:00
Xe Iaso
99f645a590 fix(anubis): disable opengraph passthru by default (#447)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-05 14:37:38 +00:00
Patrick Linnane
3b50b4c6c0 zizmor: add config file to silence unpinned-uses of Homebrew/actions (#441) 2025-05-05 01:22:36 +00:00
dependabot[bot]
8ee0529321 build(deps): bump the github-actions group with 3 updates (#439)
Bumps the github-actions group with 3 updates: [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance), [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `actions/attest-build-provenance` from 2.2.3 to 2.3.0
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](c074443f1a...db473fddc0)

Updates `astral-sh/setup-uv` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](c7f87aa956...6b9c6063ab)

Updates `github/codeql-action` from 3.28.16 to 3.28.17
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](28deaeda66...60168efe1c)

---
updated-dependencies:
- dependency-name: actions/attest-build-provenance
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 3.28.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-04 20:46:48 -04:00
Xe Iaso
799f47efbf chore(sponsors): add Terminal Trove
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-04 09:59:54 -04:00
Xe Iaso
865d513e35 feat(checker): add CEL for matching complicated expressions (#421)
* feat(lib/policy): add support for CEL checkers

This adds the ability for administrators to use Common Expression
Language[0] (CEL) for more advanced check logic than Anubis previously
offered.

These can be as simple as:

```yaml
- name: allow-api-routes
  action: ALLOW
  expression:
    and:
    - '!(method == "HEAD" || method == "GET")'
    - path.startsWith("/api/")
```

or get as complicated as:

```yaml
- name: allow-git-clients
  action: ALLOW
  expression:
    and:
    - userAgent.startsWith("git/") || userAgent.contains("libgit") || userAgent.startsWith("go-git") || userAgent.startsWith("JGit/") || userAgent.startsWith("JGit-")
    - >
      "Git-Protocol" in headers && headers["Git-Protocol"] == "version=2"
```

Internally these are compiled and evaluated with cel-go[1]. This also
leaves room for extensibility should that be desired in the future. This
will intersect with #338 and eventually intersect with TLS fingerprints
as in #337.

[0]: https://cel.dev/
[1]: https://github.com/google/cel-go

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(data/apps): add API route allow rule for non-HEAD/GET

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document expression syntax

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix: fixes in review

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-03 14:26:54 -04:00
mans17
af07691139 Update apache.mdx (#430)
I guess the whole purpose is to avoid having 3001 opened to the world. This is the easyest way to do it (iptables might be an option too)

Signed-off-by: mans17 <github@spontex.org>
2025-05-03 13:29:30 +00:00
Xe Iaso
74dcebf20b docs: add caddy docs (#423)
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-02 19:15:05 +00:00
Xe Iaso
92d3dd361b docs(user): add frequently asked questions page (#422)
Closes #400
2025-05-02 18:53:53 +00:00
Benjamin Armintor
9e760b1c16 deduplicate css rules by using media query to set variables (#420)
* deduplicate css rules by using media query to set variables

* Update xess/xess.css

Co-authored-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Benjamin Armintor <armintor@gmail.com>

---------

Signed-off-by: Benjamin Armintor <armintor@gmail.com>
Co-authored-by: Xe Iaso <me@xeiaso.net>
2025-05-02 14:17:27 -04:00
Kurt Kremitzki
fc54e95208 Update nginx.mdx upstream syntax (#397)
Remove http:// prefix from commented-out TCP socket nginx upstream example

Signed-off-by: Kurt Kremitzki <kkremitzki@users.noreply.github.com>
2025-05-02 18:15:13 +00:00
Henri Vasserman
f879e0d307 fix(cmd/anubis): print "Rule error IDs" in JSON (#408)
* fix(cmd/anubis): print "Rule error IDs" in JSON

amend: add new gpg key

* chore: changelog
2025-05-02 18:05:41 +00:00
Xe Iaso
6e82373718 feat(config): allow multi-level imports (#402)
* feat(config): allow multi-level imports

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(data): fix spelling of Marginalia

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-02 13:57:20 -04:00
Xe Iaso
f8e1000ab0 fix(yeetfile): copy all docs, data files, and botPolicies.yaml (#419)
* fix(yeetfile): copy all docs, data files, and botPolicies.yaml

Closes #415

Signed-off-by: Xe Iaso <me@xeiaso.net>

* ci: bump yeet

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-05-02 08:43:19 -04:00
Thomas Schuster
fa362c8ec9 docs(known-instances): Add FreeCAD Wiki to known instances (#414)
Update to #407 in accordance with https://blog.freecad.org/2025/04/30/forum-and-wiki-performance-anubis-deployed/

Signed-off-by: Thomas Schuster <twihno@gmail.com>
2025-05-02 08:39:01 -04:00
Jan Alexander Steffens
76f2029fb5 fix(web): Avoid timestamping main.mjs.gz (#412)
Improves reproducibility.
2025-05-01 19:52:50 +00:00
Lothar Serra Mari
5d9cc40e34 docs(known-instances): add ScummVM (#411)
Signed-off-by: Lothar Serra Mari <mail@serra.me>
2025-05-01 18:12:45 +00:00
552 changed files with 34082 additions and 5522 deletions

12
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM ghcr.io/xe/devcontainer-base/pre/go
WORKDIR /app
COPY go.mod go.sum package.json package-lock.json ./
RUN apt-get update \
&& apt-get -y install zstd brotli redis \
&& mkdir -p /home/vscode/.local/share/fish \
&& chown -R vscode:vscode /home/vscode/.local/share/fish \
&& chown -R vscode:vscode /go
CMD ["/usr/bin/sleep", "infinity"]

13
.devcontainer/README.md Normal file
View File

@@ -0,0 +1,13 @@
# Anubis Dev Container
Anubis offers a [development container](https://containers.dev/) image in order to make it easier to contribute to the project. This image is based on [Xe/devcontainer-base/go](https://github.com/Xe/devcontainer-base/tree/main/src/go), which is based on Debian Bookworm with the following customizations:
- [Fish](https://fishshell.com/) as the shell complete with a custom theme
- [Go](https://go.dev) at the most recent stable version
- [Node.js](https://nodejs.org/en) at the most recent stable version
- [Atuin](https://atuin.sh/) to sync shell history between your host OS and the development container
- [Docker](https://docker.com) to manage and build Anubis container images from inside the development container
- [Ko](https://ko.build/) to build production-ready Anubis container images
- [Neovim](https://neovim.io/) for use with Git
This development container is tested and known to work with [Visual Studio Code](https://code.visualstudio.com/). If you run into problems with it outside of VS Code, please file an issue and let us know what editor you are using.

View File

@@ -0,0 +1,34 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/debian
{
"name": "Dev",
"dockerComposeFile": [
"./docker-compose.yaml"
],
"service": "workspace",
"workspaceFolder": "/workspace/anubis",
"postStartCommand": "bash ./.devcontainer/poststart.sh",
"features": {
"ghcr.io/xe/devcontainer-features/ko:1.1.0": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"initializeCommand": "mkdir -p ${localEnv:HOME}${localEnv:USERPROFILE}/.local/share/atuin",
"customizations": {
"vscode": {
"extensions": [
"esbenp.prettier-vscode",
"ms-azuretools.vscode-containers",
"golang.go",
"unifiedjs.vscode-mdx",
"a-h.templ",
"redhat.vscode-yaml",
"streetsidesoftware.code-spell-checker"
],
"settings": {
"chat.instructionsFilesLocations": {
".github/copilot-instructions.md": true
}
}
}
}
}

View File

@@ -0,0 +1,26 @@
services:
playwright:
image: mcr.microsoft.com/playwright:v1.52.0-noble
init: true
network_mode: service:workspace
command:
- /bin/sh
- -c
- npx -y playwright@1.52.0 run-server --port 9001 --host 0.0.0.0
valkey:
image: valkey/valkey:8
pull_policy: always
# VS Code workspace service
workspace:
image: ghcr.io/techarohq/anubis/devcontainer
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ../:/workspace/anubis:cached
environment:
VALKEY_URL: redis://valkey:6379/0
#entrypoint: ["/usr/bin/sleep", "infinity"]
user: vscode

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
pwd
npm ci &
go mod download &
go install ./utils/cmd/... &
wait

2
.gitattributes vendored
View File

@@ -1 +1 @@
web/index_templ.go linguist-generated
**/*_templ.go linguist-generated=true

1
.github/FUNDING.yml vendored
View File

@@ -1,2 +1,3 @@
patreon: cadey
github: xe
liberapay: Xe

61
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: Bug report
description: Create a report to help us improve
body:
- type: textarea
id: description-of-bug
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
placeholder: I can reliably get an error when...
validations:
required: true
- type: textarea
id: steps-to-reproduce
attributes:
label: Steps to reproduce
description: |
Steps to reproduce the behavior.
placeholder: |
1. Go to the following url...
2. Click on...
3. You get the following error: ...
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected behavior
description: |
A clear and concise description of what you expected to happen.
Ideally also describe *why* you expect it to happen.
placeholder: Instead of displaying an error, it would...
validations:
required: true
- type: input
id: version-os
attributes:
label: Your operating system and its version.
description: Unsure? Visit https://whatsmyos.com/
placeholder: Android 13
validations:
required: true
- type: input
id: version-browser
attributes:
label: Your browser and its version.
description: Unsure? Visit https://www.whatsmybrowser.org/
placeholder: Firefox 142
validations:
required: true
- type: textarea
id: additional-context
attributes:
label: Additional context
description: Add any other context about the problem here.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security
url: https://techaro.lol/contact
about: Do not file security reports here. Email security@techaro.lol.

View File

@@ -0,0 +1,39 @@
name: Feature request
description: Suggest an idea for this project
title: '[Feature request] '
body:
- type: textarea
id: description-of-bug
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is that made you submit this report.
placeholder: I am always frustrated, when...
validations:
required: true
- type: textarea
id: description-of-solution
attributes:
label: Solution you would like.
description: A clear and concise description of what you want to happen.
placeholder: Instead of behaving like this, there should be...
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Describe alternatives you have considered.
description: A clear and concise description of any alternative solutions or features you have considered.
placeholder: Another workaround that would work, is...
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context
description: Add any other context (such as mock-ups, proof of concepts or screenshots) about the feature request here.
validations:
required: false

View File

@@ -9,3 +9,4 @@ Checklist:
- [ ] Added a description of the changes to the `[Unreleased]` section of docs/docs/CHANGELOG.md
- [ ] Added test cases to [the relevant parts of the codebase](https://anubis.techaro.lol/docs/developer/code-quality)
- [ ] Ran integration tests `npm run test:integration` (unsupported on Windows, please use WSL)
- [ ] All of my commits have [verified signatures](https://anubis.techaro.lol/docs/developer/signed-commits)

17
.github/actions/spelling/README.md vendored Normal file
View File

@@ -0,0 +1,17 @@
# check-spelling/check-spelling configuration
File | Purpose | Format | Info
-|-|-|-
[dictionary.txt](dictionary.txt) | Replacement dictionary (creating this file will override the default dictionary) | one word per line | [dictionary](https://github.com/check-spelling/check-spelling/wiki/Configuration#dictionary)
[allow.txt](allow.txt) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow)
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
[only.txt](only.txt) | Only check matching files (applied after excludes) | perl regular expression | [only](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-only)
[patterns.txt](patterns.txt) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[expect.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
Note: you can replace any of these files with a directory by the same name (minus the suffix)
and then include multiple files inside that directory (with that suffix) to merge multiple files together.

31
.github/actions/spelling/advice.md vendored Normal file
View File

@@ -0,0 +1,31 @@
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
<details><summary>If the flagged items are :exploding_head: false positives</summary>
If items relate to a ...
* binary file (or some other file you wouldn't want to check at all).
Please add a file path to the `excludes.txt` file matching the containing file.
File paths are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files.
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
../tree/HEAD/README.md) (on whichever branch you're using).
* well-formed pattern.
If you can write a [pattern](
https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
) that would match it,
try adding it to the `patterns.txt` file.
Patterns are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
Note that patterns can't match multiline strings.
</details>
<!-- adoption information-->
:steam_locomotive: If you're seeing this message and your PR is from a branch that doesn't have check-spelling,
please merge to your PR's base branch to get the version configured for your repository.

20
.github/actions/spelling/allow.txt vendored Normal file
View File

@@ -0,0 +1,20 @@
github
https
ssh
ubuntu
workarounds
rjack
msgbox
xeact
ABee
tencent
maintnotifications
azurediamond
cooldown
verifyfcrdns
Spintax
spintax
clampip
pseudoprofound
reimagining
iocaine

View File

@@ -0,0 +1,779 @@
# Repeated letters
#\b([a-z])\g{-1}{2,}\b
# marker to ignore all code on line
^.*/\* #no-spell-check-line \*/.*$
# marker to ignore all code on line
^.*\bno-spell-check(?:-line|)(?:\s.*|)$
# https://cspell.org/configuration/document-settings/
# cspell inline
^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
# copyright
Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
# patch hunk comments
^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .*
# git index header
index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
# file permissions
['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
# css fonts
\bfont(?:-family|):[^;}]+
# css url wrappings
\burl\([^)]+\)
# cid urls
(['"])cid:.*?\g{-1}
# data url in parens
\(data:(?:[^) ][^)]*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
# data url in quotes
([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
# data url
\bdata:[-a-zA-Z=;:/0-9+]*,\S*
# https/http/file urls
(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|]
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@._]{3,}
# magnet urls
magnet:[?=:\w]+
# magnet urls
"magnet:[^"]+"
# obs:
"obs:[^"]*"
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
# In this examples content, I'm using a number of different ways to match things to show various approaches
# asciinema
\basciinema\.org/a/[0-9a-zA-Z]+
# asciinema v2
^\[\d+\.\d+, "[io]", ".*"\]$
# apple
\bdeveloper\.apple\.com/[-\w?=/]+
# Apple music
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
# appveyor api
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
# appveyor project
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
# Amazon
# Amazon
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
# AWS ARN
arn:aws:[-/:\w]+
# AWS S3
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
# AWS execute-api
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
# AWS ELB
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
# AWS SNS
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
# AWS VPC
vpc-\w+
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
# YouTube url
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
# YouTube music
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
# YouTube tag
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
# YouTube image
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
# Google Accounts
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
# Google Analytics
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
# Google APIs
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
# Google Artifact Registry
\.pkg\.dev(?:/[-\w]+)+(?::[-\w]+|)
# Google Storage
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
# Google Calendar
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
\w+\@group\.calendar\.google\.com\b
# Google DataStudio
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
# The leading `/` here is as opposed to the `\b` above
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
# Google Docs
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
# Google Drive
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
# Google Groups
\bgroups\.google\.com(?:/[a-z]+/(?:#!|)[^/\s"]+)*
# Google Maps
\bmaps\.google\.com/maps\?[\w&;=]*
# Google themes
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
# Google CDN
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
# Goo.gl
/goo\.gl/[a-zA-Z0-9]+
# Google Chrome Store
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
# Google Books
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
# Google Fonts
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
# Google Forms
\bforms\.gle/\w+
# Google Scholar
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
# Google Colab Research Drive
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
# Google Cloud regions
(?:us|(?:north|south)america|europe|asia|australia|me|africa)-(?:north|south|east|west|central){1,2}\d+
# GitHub SHAs (api)
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
# GitHub SHAs (markdown)
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
# GitHub SHAs
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
# GitHub SHA refs
\[([0-9a-f]+)\]\(https://(?:www\.|)github.com/[-\w]+/[-\w]+/commit/\g{-1}[0-9a-f]*
# GitHub wiki
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
# githubusercontent
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
# githubassets
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
# gist github
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
# git.io
\bgit\.io/[0-9a-zA-Z]+
# GitHub JSON
"node_id": "[-a-zA-Z=;:/0-9+_]*"
# Contributor
\[[^\]]+\]\(https://github\.com/[^/\s"]+/?\)
# GHSA
GHSA(?:-[0-9a-z]{4}){3}
# GitHub actions
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
# GitLab commit
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
# GitLab merge requests
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
# GitLab uploads
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
# GitLab commits
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
# #includes
^\s*#include\s*(?:<.*?>|".*?")
# #pragma lib
^\s*#pragma comment\(lib, ".*?"\)
# binance
accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
# bitbucket diff
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
# bitbucket repositories commits
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
# bitbucket commits
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
# bit.ly
\bbit\.ly/\w+
# bitrise
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
# bootstrapcdn.com
\bbootstrapcdn\.com/[-./\w]+
# cdn.cloudflare.com
\bcdnjs\.cloudflare\.com/[./\w]+
# circleci
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
# gitter
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
# gravatar
\bgravatar\.com/avatar/[0-9a-f]+
# ibm
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
# imgur
\bimgur\.com/[^.]+
# Internet Archive
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
# discord
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
# Disqus
\bdisqus\.com/[-\w/%.()!?&=_]*
# medium link
\blink\.medium\.com/[a-zA-Z0-9]+
# medium
\bmedium\.com/@?[^/\s"]+/[-\w]+
# microsoft
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
# powerbi
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
# vs devops
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
# microsoft store
\bmicrosoft\.com/store/apps/\w+
# mvnrepository.com
\bmvnrepository\.com/[-0-9a-z./]+
# now.sh
/[0-9a-z-.]+\.now\.sh\b
# oracle
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
# chromatic.com
/\S+.chromatic.com\S*[")]
# codacy
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
# compai
\bcompai\.pub/v1/png/[0-9a-f]+
# mailgun api
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
# mailgun
\b[0-9a-z]+.mailgun.org
# /message-id/
/message-id/[-\w@./%]+
# Reddit
\breddit\.com/r/[/\w_]*
# requestb.in
\brequestb\.in/[0-9a-z]+
# sched
\b[a-z0-9]+\.sched\.com\b
# Slack url
slack://[a-zA-Z0-9?&=]+
# Slack
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
# Slack edge
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
# Slack images
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
# shields.io
\bshields\.io/[-\w/%?=&.:+;,]*
# stackexchange -- https://stackexchange.com/feeds/sites
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
# Sentry
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
# Twitter markdown
\[@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
# Twitter hashtag
\btwitter\.com/hashtag/[\w?_=&]*
# Twitter status
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
# Twitter profile images
\btwimg\.com/profile_images/[_\w./]*
# Twitter media
\btwimg\.com/media/[-_\w./?=]*
# Twitter link shortened
\bt\.co/\w+
# facebook
\bfburl\.com/[0-9a-z_]+
# facebook CDN
\bfbcdn\.net/[\w/.,]*
# facebook watch
\bfb\.watch/[0-9A-Za-z]+
# dropbox
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
# ipfs protocol
ipfs://[0-9a-zA-Z]{3,}
# ipfs url
/ipfs/[0-9a-zA-Z]{3,}
# w3
\bw3\.org/[-0-9a-zA-Z/#.]+
# loom
\bloom\.com/embed/[0-9a-f]+
# regex101
\bregex101\.com/r/[^/\s"]+/\d+
# figma
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
# freecodecamp.org
\bfreecodecamp\.org/[-\w/.]+
# image.tmdb.org
\bimage\.tmdb\.org/[/\w.]+
# mermaid
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
# Wikipedia
\ben\.wikipedia\.org/wiki/[-\w%.#]+
# gitweb
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
# HyperKitty lists
/archives/list/[^@/]+@[^/\s"]*/message/[^/\s"]*/
# lists
/thread\.html/[^"\s]+
# list-management
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
# kubectl.kubernetes.io/last-applied-configuration
"kubectl.kubernetes.io/last-applied-configuration": ".*"
# pgp
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
# Spotify
\bopen\.spotify\.com/embed/playlist/\w+
# Mastodon
\bmastodon\.[-a-z.]*/(?:media/|@)[?&=0-9a-zA-Z_]*
# scastie
\bscastie\.scala-lang\.org/[^/]+/\w+
# images.unsplash.com
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
# pastebin
\bpastebin\.com/[\w/]+
# heroku
\b\w+\.heroku\.com/source/archive/\w+
# quip
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
# badgen.net
\bbadgen\.net/badge/[^")\]'\s]+
# statuspage.io
\w+\.statuspage\.io\b
# media.giphy.com
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
# tinyurl
\btinyurl\.com/\w+
# codepen
\bcodepen\.io/[\w/]+
# registry.npmjs.org
\bregistry\.npmjs\.org/(?:@[^/"']+/|)[^/"']+/-/[-\w@.]+
# getopts
\bgetopts\s+(?:"[^"]+"|'[^']+')
# ANSI color codes
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m
# URL escaped characters
%[0-9A-F][A-F](?=[A-Za-z])
# lower URL escaped characters
%[0-9a-f][a-f](?=[a-z]{2,})
# IPv6
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
# c99 hex digits (not the full format, just one I've seen)
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
# Punycode
\bxn--[-0-9a-z]+
# sha
sha\d+:[0-9a-f]*?[a-f]{3,}[0-9a-f]*
# sha-... -- uses a fancy capture
(\\?['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hex runs
\b[0-9a-fA-F]{16,}\b
# hex in url queries
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
# ssh
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
# PGP
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
# GPG keys
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
# Well known gpg keys
.well-known/openpgpkey/[\w./]+
# pki
-----BEGIN.*-----END
# pki (base64)
LS0tLS1CRUdJT.*
# C# includes
^\s*using [^;]+;
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
# integrity
integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1}
# https://www.gnu.org/software/groff/manual/groff.html
# man troff content
\\f[BCIPR]
# '/"
\\\([ad]q
# .desktop mime types
^MimeTypes?=.*$
# .desktop localized entries
^[A-Z][a-z]+\[[a-z]+\]=.*$
# Localized .desktop content
Name\[[^\]]+\]=.*
# IServiceProvider / isAThing
(?:(?:\b|_|(?<=[a-z]))I|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
# crypt
(['"])\$2[ayb]\$.{56}\g{-1}
# apache/old crypt
(['"]|)\$+(?:apr|)1\$+.{8}\$+.{22}\g{-1}
# sha1 hash
\{SHA\}[-a-zA-Z=;:/0-9+]{3,}
# machine learning (?)
\b(?i)ml(?=[a-z]{2,})
# python
#\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
# scrypt / argon
\$(?:scrypt|argon\d+[di]*)\$\S+
# go.sum
\bh1:\S+
# imports
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+
# scala modules
("[^"]+"\s*%%?\s*){2,3}"[^"]+"
# container images
image: [-\w./:@]+
# Docker images
^\s*(?i)FROM\s+\S+:\S+(?:\s+AS\s+\S+|)
# `docker images` REPOSITORY TAG IMAGE ID CREATED SIZE
\s*\S+/\S+\s+\S+\s+[0-9a-f]{8,}\s+\d+\s+(?:hour|day|week)s ago\s+[\d.]+[KMGT]B
# Intel intrinsics
_mm_(?!dd)\w+
# Input to GitHub JSON
content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
# This does not cover multiline strings, if your repository has them,
# you'll want to remove the `(?=.*?")` suffix.
# The `(?=.*?")` suffix should limit the false positives rate
# printf
%(?:(?:(?:hh?|ll?|[jzt])?[diuoxn]|l?[cs]|L?[fega]|p)(?=[a-z]{2,})|(?:X|L?[FEGA])(?=[a-zA-Z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%)\b)(?=.*?['"])
# Alternative printf
# %s
%(?:s(?=[a-z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%[^s])\b)(?=.*?['"])
# Python string prefix / binary prefix
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
(?<!['"])\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)['"](?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
# Regular expressions for (P|p)assword
\([A-Z]\|[a-z]\)[a-z]+
# JavaScript regular expressions
# javascript test regex
/.{3,}/[gim]*\.test\(
# javascript match regex
\.match\(/[^/\s"]{3,}/[gim]*\s*
# javascript match regex
\.match\(/\\[b].{3,}?/[gim]*\s*\)(?:;|$)
# javascript regex
^\s*/\\[b].{3,}?/[gim]*\s*(?:\)(?:;|$)|,$)
# javascript replace regex
\.replace\(/[^/\s"]{3,}/[gim]*\s*,
# assign regex
= /[^*].*?(?:[a-z]{3,}|[A-Z]{3,}|[A-Z][a-z]{2,}).*/[gim]*(?=\W|$)
# perl regex test
[!=]~ (?:/.*/|m\{.*?\}|m<.*?>|m([|!/@#,;']).*?\g{-1})
# perl qr regex
(?<!\$)\bqr(?:\{.*?\}|<.*?>|\(.*?\)|([|!/@#,;']).*?\g{-1})
# perl run
perl(?:\s+-[a-zA-Z]\w*)+
# C network byte conversions
(?:\d|\bh)to(?!ken)(?=[a-z])|to(?=[adhiklpun]\()
# Go regular expressions
regexp?\.MustCompile\((?:`[^`]*`|".*"|'.*')\)
# regex choice
\(\?:[^)]+\|[^)]+\)
# proto
^\s*(\w+)\s\g{-1} =
# sed regular expressions
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
# node packages
(["'])@[^/'" ]+/[^/'" ]+\g{-1}
# go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+
# pom.xml
<(?:group|artifact)Id>.*?<
# jetbrains schema https://youtrack.jetbrains.com/issue/RSRP-489571
urn:shemas-jetbrains-com
# Debian changelog severity
[-\w]+ \(.*\) (?:\w+|baseline|unstable|experimental); urgency=(?:low|medium|high|emergency|critical)\b
# kubernetes pod status lists
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
# kubectl - pods in CrashLoopBackOff
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
# kubernetes applications
\.apps/[-\w]+
# kubernetes object suffix
-[0-9a-f]{10}-\w{5}\s
# kubernetes crd patterns
^\s*pattern: .*$
# posthog secrets
([`'"])phc_[^"',]+\g{-1}
# xcode
# xcodeproject scenes
(?:Controller|destination|(?:first|second)Item|ID|id)="\w{3}-\w{2}-\w{3}"
# xcode api botches
customObjectInstantitationMethod
# msvc api botches
PrependWithABINamepsace
# configure flags
.* \| --\w{2,}.*?(?=\w+\s\w+)
# font awesome classes
\.fa-[-a-z0-9]+
# bearer auth
(['"])[Bb]ear[e][r] .{3,}?\g{-1}
# bearer auth
\b[Bb]ear[e][r]:? [-a-zA-Z=;:/0-9+.]{3,}
# basic auth
(['"])[Bb]asic [-a-zA-Z=;:/0-9+]{3,}\g{-1}
# basic auth
: [Bb]asic [-a-zA-Z=;:/0-9+.]{3,}
# base64 encoded content
([`'"])[-a-zA-Z=;:/0-9+]{3,}=\g{-1}
# base64 encoded content in xml/sgml
>[-a-zA-Z=;:/0-9+]{3,}=</
# base64 encoded content, possibly wrapped in mime
#(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
# base64 encoded json
\beyJ[-a-zA-Z=;:/0-9+]+
# base64 encoded pkcs
\bMII[-a-zA-Z=;:/0-9+]+
# uuencoded
#[!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_]{40,}
# DNS rr data
(?:\d+\s+){3}(?:[-+/=.\w]{2,}\s*){1,2}
# encoded-word
=\?[-a-zA-Z0-9"*%]+\?[BQ]\?[^?]{0,75}\?=
# numerator
\bnumer\b(?=.*denom)
# Time Zones
\b(?:Africa|Atlantic|America|Antarctica|Arctic|Asia|Australia|Europe|Indian|Pacific)(?:/[-\w]+)+
# linux kernel info
^(?:bugs|flags|Features)\s+:.*
# systemd mode
systemd.*?running in system mode \([-+].*\)$
# Lorem
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
# ... Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
# ... You could manually change `(?i)X...` to use `[Xx]...`
# ... or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
(?:(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*)
# Non-English
# Even repositories expecting pure English content can unintentionally have Non-English content... People will occasionally mistakenly enter [homoglyphs](https://en.wikipedia.org/wiki/Homoglyph) which are essentially typos, and using this pattern will mean check-spelling will not complain about them.
#
# If the content to be checked should be written in English and the only Non-English items will be people's names, then you can consider adding this.
#
# Alternatively, if you're using check-spelling v0.0.25+, and you would like to _check_ the Non-English content for spelling errors, you can. For information on how to do so, see:
# https://docs.check-spelling.dev/Feature:-Configurable-word-characters.html#unicode
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
# highlighted letters
\[[A-Z]\][a-z]+
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# latex (check-spelling >= 0.0.22)
\\\w{2,}\{
# American Mathematical Society (AMS) / Doxygen
TeX/AMS
# File extensions
\*\.[+\w]+,
# eslint
"varsIgnorePattern": ".+"
# nolint
nolint:\s*[\w,]+
# Windows short paths
[/\\][^/\\]{5,6}~\d{1,2}(?=[/\\])
# Windows Resources with accelerators
\b[A-Z]&[a-z]+\b(?!;)
# signed off by
(?i)Signed-off-by: .*
# cygwin paths
/cygdrive/[a-zA-Z]/(?:Program Files(?: \(.*?\)| ?)(?:/[-+.~\\/()\w ]+)*|[-+.~\\/()\w])+
# in check-spelling@v0.0.22+, printf markers aren't automatically consumed
# printf markers
(?<!\\)\\[nrt](?=[a-z]{2,})
# alternate printf markers if you run into latex and friends
(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*['"`])
# Markdown anchor links
\(#\S*?[a-zA-Z]\S*?\)
# apache
a2(?:en|dis)
# weak e-tag
W/"[^"]+"
# authors/credits
^\*(?: [A-Z](?:\w+|\.)){2,} (?=\[|$)
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
\\(?:necessary|r(?:elease|eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
# ignore long runs of a single character:
\b([A-Za-z])\g{-1}{3,}\b
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# Compiler flags (Unix, Java/Scala)
# Use if you have things like `-Pdocker` and want to treat them as `docker`
#(?:^|[\t ,>"'`=(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags (Windows / PowerShell)
# This is a subset of the more general compiler flags pattern.
# It avoids matching `-Path` to prevent it from being treated as `ath`
#(?:^|[\t ,"'`=(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
# Compiler flags (linker)
,-B
# libraries
(?:\b|_)[Ll]ib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
# WWNN/WWPN (NAA identifiers)
\b(?:0x)?10[0-9a-f]{14}\b|\b(?:0x|3)?[25][0-9a-f]{15}\b|\b(?:0x|3)?6[0-9a-f]{31}\b
# iSCSI iqn (approximate regex)
\biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b
# curl arguments
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
# set arguments
\b(?:bash|sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)*
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
# macOS temp folders
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
# github runner temp folders
/home/runner/work/_temp/[-_/a-z0-9]+

96
.github/actions/spelling/excludes.txt vendored Normal file
View File

@@ -0,0 +1,96 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)(?i)third[-_]?party/
(?:^|/)3rdparty/
(?:^|/)generated/
(?:^|/)go\.sum$
(?:^|/)package(?:-lock|)\.json$
(?:^|/)Pipfile$
(?:^|/)pyproject.toml
(?:^|/)vendor/
(?:^|/|\b)requirements(?:-dev|-doc|-test|)\.txt$
\.a$
\.ai$
\.all-contributorsrc$
\.avi$
\.bmp$
\.bz2$
\.cert?$|\.crt$
\.class$
\.coveragerc$
\.crl$
\.csr$
\.dll$
\.docx?$
\.drawio$
\.DS_Store$
\.eot$
\.eps$
\.exe$
\.gif$
\.git-blame-ignore-revs$
\.gitattributes$
\.gitkeep$
\.graffle$
\.gz$
\.icns$
\.ico$
\.ipynb$
\.jar$
\.jks$
\.jpe?g$
\.key$
\.lib$
\.lock$
\.map$
\.min\..
\.mo$
\.mod$
\.mp[34]$
\.o$
\.ocf$
\.otf$
\.p12$
\.parquet$
\.pdf$
\.pem$
\.pfx$
\.png$
\.psd$
\.pyc$
\.pylintrc$
\.qm$
\.s$
\.sig$
\.so$
\.svgz?$
\.sys$
\.tar$
\.tgz$
\.tiff?$
\.ttf$
\.wav$
\.webm$
\.webp$
\.woff2?$
\.xcf$
\.xlsx?$
\.xpm$
\.xz$
\.zip$
^\.github/actions/spelling/
^\Q.github/FUNDING.yml\E$
^\Q.github/workflows/spelling.yml\E$
^data/crawlers/
^docs/blog/tags\.yml$
^docs/docs/user/known-instances.md$
^docs/manifest/.*$
^docs/static/\.nojekyll$
^lib/policy/config/testdata/bad/unparseable\.json$
^internal/glob/glob_test.go$
ignore$
robots.txt
^lib/localization/locales/.*\.json$
^lib/localization/.*_test.go$
^test/.*$

409
.github/actions/spelling/expect.txt vendored Normal file
View File

@@ -0,0 +1,409 @@
acs
Actorified
actorifiedstore
actorify
Aibrew
alibaba
alrest
amazonbot
anthro
anubis
anubistest
apnic
APNICRANDNETAU
Applebot
archlinux
arpa
asnc
asnchecker
asns
aspirational
atuin
azuretools
badregexes
bbolt
bdba
berr
bezier
bingbot
Bitcoin
bitrate
Bluesky
blueskybot
boi
Bokm
botnet
botstopper
BPort
Brightbot
broked
buildah
byteslice
Bytespider
cachebuster
cachediptoasn
Caddyfile
caninetools
Cardyb
celchecker
celphase
cerr
certresolver
cespare
CGNAT
cgr
chainguard
chall
challengemozilla
challengetest
checkpath
checkresult
chibi
cidranger
ckie
cloudflare
Codespaces
confd
connnection
containerbuild
containerregistry
coreutils
Cotoyogi
Cromite
crt
Cscript
daemonizing
dayjob
DDOS
Debian
debrpm
decaymap
devcontainers
Diffbot
discordapp
discordbot
distros
dnf
dnsbl
dnserr
DNSTTL
domainhere
dracula
dronebl
droneblresponse
dropin
dsilence
duckduckbot
eerror
ellenjoe
emacs
enbyware
etld
everyones
evilbot
evilsite
expressionorlist
externalagent
externalfetcher
extldflags
facebookgo
Factset
fahedouch
fastcgi
FCr
fcrdns
fediverse
ffprobe
financials
finfos
Firecrawl
flagenv
Fordola
forgejo
forwardauth
fsys
fullchain
gaissmai
Galvus
geoip
geoipchecker
gha
GHSA
Ghz
gipc
gitea
godotenv
goland
gomod
goodbot
googlebot
gopsutil
govulncheck
goyaml
GPG
GPT
gptbot
Graphene
grpcprom
grw
gzw
Hashcash
hashrate
headermap
healthcheck
healthz
hec
helpdesk
Hetzner
hmc
homelab
hostable
htmlc
htmx
httpdebug
huawei
hypertext
iaskspider
iaso
iat
ifm
Imagesift
imgproxy
impressum
inbox
ingressed
inp
internets
IPTo
iptoasn
isp
iss
isset
ivh
Jenomis
JGit
jhjj
joho
journalctl
jshelter
JWTs
kagi
kagibot
Keyfunc
keypair
KHTML
kinda
KUBECONFIG
lcj
ldflags
letsencrypt
Lexentale
lfc
lgbt
licend
licstart
lightpanda
limsa
Linting
listor
LLU
loadbalancer
lol
lominsa
maintainership
malware
mcr
memes
metarefresh
metrix
mimi
Minfilia
mistralai
mnt
Mojeek
mojeekbot
mozilla
myclient
mymaster
mypass
myuser
nbf
nepeat
netsurf
nginx
nicksnyder
nobots
NONINFRINGEMENT
nosleep
nullglob
oci
OCOB
ogtag
oklch
omgili
omgilibot
openai
opendns
opengraph
openrc
oswald
pag
palemoon
Pangu
parseable
passthrough
Patreon
pgrep
phrik
pidfile
pids
pipefail
pki
podkova
podman
Postgre
poststart
prebaked
privkey
promauto
promhttp
proofofwork
publicsuffix
purejs
pwcmd
pwuser
qualys
qwant
qwantbot
rac
rawler
rcvar
redhat
redir
redirectscheme
refactors
remoteip
reputational
risc
ruleset
runlevels
RUnlock
runtimedir
runtimedirectory
Ryzen
sas
sasl
screenshots
searchbot
searx
sebest
secretplans
Semrush
Seo
setsebool
shellcheck
shirou
shopt
Sidetrade
simprint
sitemap
sls
sni
snipster
Spambot
sparkline
spyderbot
srv
stackoverflow
startprecmd
stoppostcmd
storetest
subgrid
subr
subrequest
SVCNAME
tagline
tarballs
tarrif
taviso
tbn
tbr
techaro
techarohq
telegrambot
templ
templruntime
testarea
Thancred
thoth
thothmock
Tik
Timpibot
TLog
traefik
trunc
uberspace
Unbreak
unbreakdocker
unifiedjs
unmarshal
unparseable
uvx
UXP
valkey
Varis
Velen
vendored
verify
vhosts
vkbot
VKE
vnd
VPS
Vultr
weblate
webmaster
webpage
websecure
websites
Webzio
whois
wildbase
withthothmock
wolfbeast
wordpress
workaround
workdir
wpbot
XCircle
xeiaso
xeserv
xesite
xess
xff
XForwarded
XNG
XOB
XOriginal
XReal
yae
YAMLTo
Yda
yeet
yeetfile
yourdomain
yyz
Zenos
zizmor
zombocom
zos
GLM
iocaine
nikandfor
pagegen
pseudoprofound
reimagining
Rhul
shoneypot
spammer
Y'shtola

View File

@@ -0,0 +1,463 @@
# reject `m_data` as VxWorks defined it and that breaks things if it's used elsewhere
# see [fprime](https://github.com/nasa/fprime/commit/d589f0a25c59ea9a800d851ea84c2f5df02fb529)
# and [Qt](https://github.com/qtproject/qt-solutions/blame/fb7bc42bfcc578ff3fa3b9ca21a41e96eb37c1c7/qtscriptclassic/src/qscriptbuffer_p.h#L46)
#\bm_data\b
# Were you debugging using a framework with `fit()`?
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
# you might not want to check in code where you skip all the other tests.
#\bfit\(
# English does not use a hyphen between adverbs and nouns
# https://twitter.com/nyttypos/status/1894815686192685239
(?:^|\s)[A-Z]?[a-z]+ly-(?=[a-z]{3,})(?:[.,?!]?\s|$)
# Don't use `requires that` + `to be`
# https://twitter.com/nyttypos/status/1894816551435641027
\brequires that \w+\b[^.]+to be\b
# A fully parenthetical sentences period goes inside the parentheses, not outside.
# https://twitter.com/nyttypos/status/1898844061873639490
#\([A-Z][a-z]{2,}(?: [a-z]+){3,}\)\.\s
# Complete sentences in parentheticals should not have a space before the period.
\s\.\)(?!.*\}\})
# Should be `HH:MM:SS`
\bHH:SS:MM\b
# Should be `86400` (seconds in a standard day)
\b84600\b(?:.*\bday\b)
# Should probably be `2006-01-02` (yyyy-mm-dd)
# Assuming that the time is being passed to https://go.dev/src/time/format.go
\b2006-02-01\b
# Should probably be `YYYYMMDD`
\b[Yy]{4}[Dd]{2}[Mm]{2}(?!.*[Yy]{4}[Dd]{2}[Mm]{2}).*$
# Should be `a priori` or `and prior`
(?i)(?<!posteriori)\sand priori\s
# Should be `a`
\san (?=(?:[b-df-gj-np-rtv-xz]|h(?!our|tml|ttp)|s(?!sh|vg))[a-z])
# Should only be one of `a`, `an`, or `the`
\b(?:(?:an?|the)\s+){2,}\b
# Should only be `are` or `can`, not both
\b(?:(?:are|can)\s+){2,}\b
# Should probably be `ABCDEFGHIJKLMNOPQRSTUVWXYZ`
(?i)(?!ABCDEFGHIJKLMNOPQRSTUVWXYZ)ABC[A-Z]{21}YZ
# Should be `anymore`
\bany more[,.]
# Should be `Ask`
(?:^|[.?]\s+)As\s+[A-Z][a-z]{2,}\s[^.?]*?(?:how|if|wh\w+)\b
# Should be `at one fell swoop`
# and only when talking about killing, not some other completion
# Act 4 Scene 3, Macbeth
# https://www.opensourceshakespeare.org/views/plays/play_view.php?WorkID=macbeth&Act=4&Scene=3&Scope=scene
\bin one fell s[lw]?oop\b
# Should be `'`
(?i)\b(?:(?:i|s?he|they|what|who|you)[`"]ll|(?:are|ca|did|do|does|ha[ds]|have|is|should|were|wo|would)n[`"]t|(?:s?he|let|that|there|what|where|who)[`"]s|(?:i|they|we|what|who|you)[`"]ve)\b
# Should be `background` / `intro text` / `introduction` / `prologue` unless it's a brand or relates to _subterfuge_
(?i)\bpretext\b
# Should be `branches`
# ... unless it's really about the meal that replaces breakfast and lunch.
\b[Bb]runches\b
# Should be `briefcase`
\bbrief-case\b
# Should be `by far` or `far and away`
\bby far and away\b
# Should be `can, not only ..., ... also...`
\bcan not only.*can also\b
# Should be `cannot` (or `can't`)
# See https://www.grammarly.com/blog/cannot-or-can-not/
# > Don't use `can not` when you mean `cannot`. The only time you're likely to see `can not` written as separate words is when the word `can` happens to precede some other phrase that happens to start with `not`.
# > `Can't` is a contraction of `cannot`, and it's best suited for informal writing.
# > In formal writing and where contractions are frowned upon, use `cannot`.
# > It is possible to write `can not`, but you generally find it only as part of some other construction, such as `not only . . . but also.`
# - if you encounter such a case, add a pattern for that case to patterns.txt.
\b[Cc]an not\b(?! only\b)
# Should be `chart`
(?i)\bhelm\b.*\bchard\b
# Do not use `(click) here` links
# For more information, see:
# * https://www.w3.org/QA/Tips/noClickHere
# * https://webaim.org/techniques/hypertext/link_text
# * https://granicus.com/blog/why-click-here-links-are-bad/
# * https://heyoka.medium.com/dont-use-click-here-f32f445d1021
(?i)(?:>|\[)(?:(?:click |)here|link|(?:read |)more)(?:</|\]\()
# Including "image of" or "picture of" in alt text is unnecessary.
\balt=['"](?:an? |)(?:image|picture) of
# Alt text should be short
\balt=(?:'[^']{126,}'|"[^"]{126,}")
# Should be `equals` to `is equal to`
\bequals to\b
# Should be `ECMA` 262 (JavaScript)
(?i)\bTS\/EMCA\b|\bEMCA(?: \d|\s*Script)|\bEMCA\b(?=.*\bTS\b)
# Should be `ECMA` 340 (Near Field Communications)
(?i)EMCA[- ]340
# Should be `fall back`
\bfallback(?= to)\b
# Should be `GitHub`
(?<![&*.]|// |\b(?:from|import|type) )\bGithub\b(?![{()])
# Should be `GitLab`
(?<![&*.]|// |\b(?:from|import|type) )\bGitlab\b(?![{()])
# Should probably be `https://`...
# Markdown generally doesn't assume that links are to urls
\]\(www\.\w
# Should be `JavaScript`
\bJavascript\b
# Should be `macOS` or `Mac OS X` or ...
\bMacOS\b
# Should be `Microsoft`
\bMicroSoft\b
# Should be `OAuth`
(?:^|[^-/*$])[ '"]oAuth(?: [a-z]|\d+ |[^ a-zA-Z0-9:;_.()])
# Should be `RabbitMQ`
\bRabbitmq\b
# Should be `TensorFlow`
\bTensorflow\b
# Should be `TypeScript`
\bTypescript\b
# Should be `another`
\ban[- ]other(?!-)\b
# Should be `case-(in)sensitive`
\bcase (?:in|)sensitive\b
# Should be `coinciding`
\bco-inciding\b
# Should be `deprecation warning(s)`
\b[Dd]epreciation [Ww]arnings?\b
# Should be `greater than`
\bgreater then\b
# Should be `has`
\b[Ii]t only have\b
# Should be `here-in`, `the`, `them`, `this`, `these` or reworded in some other way
\bthe here(?:\.|,| (?!and|defined))
# Should be `greater than`
\bhigher than\b
# Should be `ID` (unless it's a flag/property)
(?<![-\.])\bId\b(?![(])
# Should be `in front of`
\bin from of\b
# Should be `into`
# when not phrasal and when `in order to` would be wrong:
# https://thewritepractice.com/into-vs-in-to/
\sin to\s(?!if\b)
# Should be `use`
\sin used by\b
# Should be `in-depth` if used as an adjective (but `in depth` when used as an adverb)
\bin depth\s(?!rather\b)\w{6,}
# Should be `in-flight` or `on the fly` (unless actually talking about airline flights)
\bon[- ]flight\b(?!=\s+(?:(?:\w{2}|)\d+|availability|booking|computer|data|delay|departure|management|performance|radar|reservation|scheduling|software|status|ticket|time|type|.*(?:hotel|taxi)))
# Should be `is obsolete`
\bis obsolescent\b
# Should be `it's` or `its`
\bits[']
# Should be `its`
\bit's(?= own\b)
# Should be `its`
\bit's(?= only purpose\b)
# Should be `for its` (possessive) or `because it is`
\bfor it(?:'s| is)\b
# Should be `log in`
\blogin to the
# Should be `long-standing`
\blong standing\b
# `apt-key` is deprecated
# ... instead you should be writing a pair of files:
# ... * the gpg key added to a distinct key ring file based on your project/distro/key...
# ... * the sources.list in a district file -- not simply appended to `/etc/apt/sources.list` -- (there is a newer format [DEB822](https://manpages.debian.org/bookworm/dpkg-dev/deb822.5.en.html)) that references the gpg key.
# Consider:
# ````sh
# curl http://download.something.example.com/$DISTRO/Release.key | \
# gpg --dearmor --yes --output /usr/share/keyrings/something-distro.gpg
# echo "deb [signed-by=/usr/share/keyrings/something-distro.gpg] http://download.something.example.com/repositories/home:/$DISTRO ./" \
# >> /etc/apt/sources.list.d/something-distro.list
# ````
\bapt-key add\b
# Should be `nearby`
\bnear by\b
# Should probably be a person named `Nick` or the abbreviation `NIC`
\bNic\b
# Should be `not supposed`
\bsupposed not\b
# Should probably be `much more`
\bmore much\b
# Should be `perform its`
\bperform it's\b
# Should be `opt-in`
(?<!\scan|for)(?<!\smust)(?<!\sif)\sopt in\s
# Should be `less than`
\bless then\b
# Should be `load balancer`
\b[Ll]oud balancer
# Should be `moot`
\bmute point\b
# Should be `one of`
(?<!-)\bon of\b
# Should be `on the other hand`
\b(?i)on another hand\b
# Reword to `on at runtime` or `enabled at launch`
# The former if you mean it can be changed dynamically.
# The latter if you mean that it can be changed without recompiling but not after the program starts.
\bswitched on runtime\b
# Should be `Of course,`
[?.!]\s+Of course\s(?=[-\w\s]+[.?;!,])
# Most people only have two hands. Reword.
\b(?i)on the third hand\b
# Should be `OpenShift`
\bOpenshift\b
# Should be `otherwise`
\bother[- ]wise\b
# Should be `; otherwise` or `. Otherwise`
# https://study.com/learn/lesson/otherwise-in-a-sentence.html
, [Oo]therwise\b
# Should probably be `Otherwise,`
(?<=\. )Otherwise\s
# Should be `or (more|less)`
\bore (?:more|less)\b
# Should be `rather than`
\brather then\b
# Should be `Red Hat`
\bRed[Hh]at\b
# Should be `regardless, ...` or `regardless of (whether)`
\b[Rr]egardless if you\b
# Should be `self-signed`
\bself signed\b
# Should be `SendGrid`
\bSendgrid\b
# Should be `set up` (`setup` is a noun / `set up` is a verb)
\b[Ss]etup(?= (?:an?|the)\b)
# Should be `state`
\bsate(?=\b|[A-Z])|(?<=[a-z])Sate(?=\b|[A-Z])|(?<=[A-Z]{2})Sate(?=\b|[A-Z])
# Should be `no longer needed`
\bno more needed\b(?! than\b)
# Should be `<see|look> below for the`
(?i)\bfind below the\b
# Should be `then any` unless there's a comparison before the `,`
, than any\b
# Should be `did not exist`
\bwere not existent\b
# Should be `nonexistent`
\bnon existing\b
# Should be `nonexistent`
\b[Nn]o[nt][- ]existent\b
# Should be `our`
\bspending out time\b
# Should be `@brief` / `@details` / `@param` / `@return` / `@retval`
(?:^\s*|(?:\*|//|/*)\s+`)[\\@](?:breif|(?:detail|detials)|(?:params(?!\.)|prama?)|ret(?:uns?)|retvl)\b
# Should be `more than` or `more, then`
\bmore then\b
# Should be `Pipeline`/`pipeline`
(?:(?<=\b|[A-Z])p|P)ipeLine(?:\b|(?=[A-Z]))
# Should be `preexisting`
[Pp]re[- ]existing
# Should be `preempt`
[Pp]re[- ]empt\b
# Should be `preemptively`
[Pp]re[- ]emptively
# Should be `prepopulate`
[Pp]re[- ]populate
# Should be `prerequisite`
[Pp]re[- ]requisite
# Should be `recently changed` or `recent changes`
[Rr]ecent changed
# Should be `reentrancy`
[Rr]e[- ]entrancy
# Should be `reentrant`
[Rr]e[- ]entrant
# Should be `room for`
\brooms for (?!lease|rent|sale)
# Should be `socioeconomic`
# https://dictionary.cambridge.org/us/dictionary/english/socioeconomic
socio-economic
# Should be `strong suit`
\b(?:my|his|her|their) strong suite\b
# Should probably be `temperatures` unless actually talking about thermal drafts (things birds may fly on)
\bthermals\b
# Should be `there are` or `they are` (or `they're`)
(?i)\btheir are\b
# Should be `understand`
\bunder stand\b
# Should be `URI` or `uri` unless it refers to a person named `Uri` (or a flag)
(?<![-\.])\bUri\b(?![(])
# Should be `it uses is`
/\bis uses is\b/
# Should be `uses it as`
(?:^|\. |and )uses is as (?!an?\b|follows|livestock|[^.]+\s+as\b)
# Should be `was`
\bhas been(?= removed in v?\d)
# Should be `where`
\bwere they are\b
# Should be `why`
, way(?= is [^.]*\?)
# should be `vCenter`
\bV[Cc]enter\b
# Should be `VM`
\bVm\b
# Should be `walkthrough(s)`
\bwalk-throughs?\b
# Should be `we'll`
\bwe 'll\b
# Should be `whereas`
\bwhere as\b
# Should be `WinGet`
\bWinget\b
# Should be `without` (unless `out` is a modifier of the next word)
\bwith out\b(?!-)
# Should be `work around`
\b[Ww]orkaround(?= an?\b)
# Should be `workarounds`
\bwork[- ]arounds\b
# Should be `workaround`
(?:(?:[Aa]|[Tt]he|ugly)\swork[- ]around\b|\swork[- ]around\s+for)
# Should be `worst`
(?i)worse-case
# Should be `you are not` or reworded
\byour not\b
# Should be `(coarse|fine)-grained`
\b(?:coarse|fine) grained\b
# Homoglyph (Cyrillic) should be `A`/`B`/`C`/`E`/`H`/`I`/`I`/`J`/`K`/`M`/`O`/`P`/`S`/`T`/`Y`
# It's possible that your content is intentionally mixing Cyrillic and Latin scripts, but if it isn't, you definitely want to correct this.
(?<=[A-Z]{2})[АВСЕНІӀЈКМОРЅТУ]|[АВСЕНІӀЈКМОРЅТУ](?=[A-Z]+(?:\b|[a-z]+)|[a-z]+(?:[^a-z]|$))
# Homoglyph (Cyrillic) should be `a`/`b`/`c`/`e`/`o`/`p`/`x`/`y`
# It's possible that your content is intentionally mixing Cyrillic and Latin scripts, but if it isn't, you definitely want to correct this.
[авсеорху](?=[A-Za-z]{2,})|(?<=[A-Za-z]{2})[авсеорху]|(?<=[A-Za-z])[авсеорху](?=[A-Za-z])
# Should be `neither/nor` -- or reword
(?!<do )\bnot\b([^.?!"/(](?!neither|,.*?,))+\bnor\b
# Should be `neither/nor` (plus rewording the beginning)
# This is probably a double negative...
\bnot\b[^.?!"/(]*\bneither\b[^.?!"/(]*\bnor\b
# In English, duplicated words are generally mistakes
# There are a few exceptions (e.g. "that that").
# If the highlighted doubled word pair is in:
# * code, write a pattern to mask it.
# * prose, have someone read the English before you dismiss this error.
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s

138
.github/actions/spelling/patterns.txt vendored Normal file
View File

@@ -0,0 +1,138 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
# Automatically suggested patterns
# hit-count: 198 file-count: 52
# https/http/file urls
(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|]
# hit-count: 22 file-count: 8
# GitHub actions
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
# hit-count: 19 file-count: 5
# libraries
(?:\b|_)[Ll]ib(?:re(?=office)|era(?![lt])|)(?!ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
# hit-count: 17 file-count: 8
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# hit-count: 15 file-count: 7
# container images
image: [-\w./:@]+
# hit-count: 14 file-count: 9
# imports
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+
# hit-count: 11 file-count: 2
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
# hit-count: 8 file-count: 5
# node packages
(["'])@[^/'" ]+/[^/'" ]+\g{-1}
# hit-count: 5 file-count: 2
# css fonts
\bfont(?:-family|):[^;}]+
# hit-count: 4 file-count: 4
# set arguments
\b(?:bash|sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)*
# hit-count: 4 file-count: 2
# css url wrappings
\burl\([^)]+\)
# hit-count: 2 file-count: 2
# C network byte conversions
(?:\d|\bh)to(?!ken)(?=[a-z])|to(?=[adhiklpun]\()
# hit-count: 2 file-count: 1
# GitHub SHA refs
\[([0-9a-f]+)\]\(https://(?:www\.|)github.com/[-\w]+/[-\w]+/commit/\g{-1}[0-9a-f]*
# hit-count: 1 file-count: 1
# copyright
Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
# hit-count: 1 file-count: 1
# IPv6
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
# hit-count: 1 file-count: 1
# Docker images
^\s*(?i)FROM\s+\S+:\S+(?:\s+AS\s+\S+|)
# hit-count: 1 file-count: 1
# perl run
perl(?:\s+-[a-zA-Z]\w*)+
# hit-count: 1 file-count: 1
# go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+
# hit-count: 1 file-count: 1
# in check-spelling@v0.0.22+, printf markers aren't automatically consumed
# printf markers
(?<!\\)\\[nrt](?=[a-z]{2,})
# hit-count: 1 file-count: 1
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# Questionably acceptable forms of `in to`
# Personally, I prefer `log into`, but people object
# https://www.tprteaching.com/log-into-log-in-to-login/
\b(?:(?:[Ll]og(?:g(?=[a-z])|)|[Ss]ign)(?:ed|ing)?) in to\b
# to opt in
\bto opt in\b
# pass(ed|ing) in
\bpass(?:ed|ing) in\b
# acceptable duplicates
# ls directory listings
[-bcdlpsw](?:[-r][-w][-SsTtx]){3}[\.+*]?\s+\d+\s+\S+\s+\S+\s+[.\d]+(?:[KMGT]|)\s+
# mount
\bmount\s+-t\s+(\w+)\s+\g{-1}\b
# C types and repeated CSS values
\s(auto|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s
# C enum and struct
\b(?:enum|struct)\s+(\w+)\s+\g{-1}\b
# go templates
\s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml):
# doxygen / javadoc / .net
(?:[\\@](?:brief|defgroup|groupname|link|t?param|return|retval)|(?:public|private|\[Parameter(?:\(.+\)|)\])(?:\s+(?:static|override|readonly|required|virtual))*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s
# macOS file path
(?:Contents\W+|(?!iOS)/)MacOS\b
# Python package registry has incorrect spelling for macOS / Mac OS X
"Operating System :: MacOS :: MacOS X"
# "company" in Germany
\bGmbH\b
# IntelliJ
\bIntelliJ\b
# Commit message -- Signed-off-by and friends
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
# Autogenerated revert commit message
^This reverts commit [0-9a-f]{40}\.$
# ignore long runs of a single character:
\b([A-Za-z])\g{-1}{3,}\b
# hit-count: 1 file-count: 1
# microsoft
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
# hit-count: 1 file-count: 1
# data url
\bdata:[-a-zA-Z=;:/0-9+]*,\S*

23
.github/actions/spelling/reject.txt vendored Normal file
View File

@@ -0,0 +1,23 @@
^attache$
^bellows?$
benefitting
occurences?
^dependan.*
^develope$
^developement$
^developpe
^Devers?$
^devex
^devide
^Devinn?[ae]
^devisal
^devisor
^diables?$
^oer$
Sorce
^[Ss]pae.*
^Teh$
^untill$
^untilling$
^venders?$
^wether.*

View File

@@ -8,6 +8,8 @@ updates:
github-actions:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: gomod
directory: /
@@ -17,6 +19,8 @@ updates:
gomod:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: npm
directory: /
@@ -26,3 +30,5 @@ updates:
npm:
patterns:
- "*"
cooldown:
default-days: 7

View File

@@ -0,0 +1,72 @@
name: Asset Build Verification
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions:
contents: read
jobs:
asset_verification:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: build essential
run: |
sudo apt-get update
sudo apt-get install -y build-essential
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: '24.11.0'
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version: '1.25.4'
- name: install node deps
run: |
npm ci
- name: Check for uncommitted changes before asset build
id: check-changes-before
run: |
if [[ -n $(git status --porcelain) ]]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
echo "has_changes=false" >> $GITHUB_OUTPUT
fi
- name: Fail if there are uncommitted changes before build
if: steps.check-changes-before.outputs.has_changes == 'true'
run: |
echo "There are uncommitted changes before running npm run assets"
git status
exit 1
- name: Run asset build
run: |
npm run assets
- name: Check for uncommitted changes after asset build
id: check-changes-after
run: |
if [[ -n $(git status --porcelain) ]]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
else
echo "has_changes=false" >> $GITHUB_OUTPUT
fi
- name: Fail if assets generated changes
if: steps.check-changes-after.outputs.has_changes == 'true'
run: |
echo "npm run assets generated uncommitted changes. This indicates the repository has outdated generated files."
echo "Please run 'npm run assets' locally and commit the changes."
git status
git diff
exit 1

View File

@@ -15,41 +15,31 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-tags: true
fetch-depth: 0
persist-credentials: false
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Setup Homebrew cellar cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/var
key: ${{ runner.os }}-go-homebrew-cellar-${{ hashFiles('go.sum') }}
restore-keys: |
${{ runner.os }}-go-homebrew-cellar-
- name: Install Brew dependencies
- name: build essential
run: |
brew bundle
sudo apt-get update
sudo apt-get install -y build-essential
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: '24.11.0'
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version: '1.25.4'
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ghcr.io/techarohq/anubis
images: ghcr.io/${{ github.repository }}
- name: Build and push
id: build
@@ -58,7 +48,7 @@ jobs:
npm run container
env:
PULL_REQUEST_ID: ${{ github.event.number }}
DOCKER_REPO: ghcr.io/techarohq/anubis
DOCKER_REPO: ghcr.io/${{ github.repository }}
SLOG_LEVEL: debug
- run: |

View File

@@ -21,48 +21,42 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-tags: true
fetch-depth: 0
persist-credentials: false
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Setup Homebrew cellar cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/var
key: ${{ runner.os }}-go-homebrew-cellar-${{ hashFiles('go.sum') }}
restore-keys: |
${{ runner.os }}-go-homebrew-cellar-
- name: Install Brew dependencies
- name: build essential
run: |
brew bundle
sudo apt-get update
sudo apt-get install -y build-essential
- name: Set lowercase image name
run: |
echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: '24.11.0'
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version: '1.25.4'
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
- name: Log into registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: techarohq
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ghcr.io/techarohq/anubis
images: ${{ env.IMAGE }}
- name: Build and push
id: build
@@ -70,12 +64,12 @@ jobs:
npm ci
npm run container
env:
DOCKER_REPO: ghcr.io/techarohq/anubis
DOCKER_REPO: ${{ env.IMAGE }}
SLOG_LEVEL: debug
- name: Generate artifact attestation
uses: actions/attest-build-provenance@c074443f1aee8d4aeeae555aebba3282517141b2 # v2.2.3
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
with:
subject-name: ghcr.io/techarohq/anubis
subject-name: ${{ env.IMAGE }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true

View File

@@ -13,18 +13,19 @@ permissions:
jobs:
build:
if: github.repository == 'TecharoHQ/anubis'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Log into registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: techarohq
@@ -32,13 +33,16 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ghcr.io/techarohq/anubis/docs
tags: |
type=sha,enable=true,priority=100,prefix=,suffix=,format=long
main
- name: Build and push
id: build
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: ./docs
cache-to: type=gha
@@ -48,16 +52,16 @@ jobs:
platforms: linux/amd64
push: true
- name: Apply k8s manifests to aeacus
uses: actions-hub/kubectl@e81783053d902f50d752d21a6d99cf9689a652e1 # v1.33.0
- name: Apply k8s manifests to limsa lominsa
uses: actions-hub/kubectl@f6d776bd78f4523e36d6c74d34f9941c242b2213 # v1.35.0
env:
KUBE_CONFIG: ${{ secrets.AEACUS_KUBECONFIG }}
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
with:
args: apply -k docs/manifest
- name: Apply k8s manifests to aeacus
uses: actions-hub/kubectl@e81783053d902f50d752d21a6d99cf9689a652e1 # v1.33.0
- name: Apply k8s manifests to limsa lominsa
uses: actions-hub/kubectl@f6d776bd78f4523e36d6c74d34f9941c242b2213 # v1.35.0
env:
KUBE_CONFIG: ${{ secrets.AEACUS_KUBECONFIG }}
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
with:
args: rollout restart -n default deploy/anubis-docs

View File

@@ -13,22 +13,25 @@ jobs:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ghcr.io/techarohq/anubis/docs
tags: |
type=sha,enable=true,priority=100,prefix=,suffix=,format=long
main
- name: Build and push
id: build
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: ./docs
cache-to: type=gha

76
.github/workflows/go-mod-tidy-check.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: Go Mod Tidy Check
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions:
contents: read
jobs:
go_mod_tidy_check:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version: '1.25.4'
- name: Check go.mod and go.sum in main directory
run: |
# Store original file state
cp go.mod go.mod.orig
cp go.sum go.sum.orig
# Run go mod tidy
go mod tidy
# Check if files changed
if ! diff -q go.mod.orig go.mod > /dev/null 2>&1; then
echo "ERROR: go.mod in main directory has changed after running 'go mod tidy'"
echo "Please run 'go mod tidy' locally and commit the changes"
diff go.mod.orig go.mod
exit 1
fi
if ! diff -q go.sum.orig go.sum > /dev/null 2>&1; then
echo "ERROR: go.sum in main directory has changed after running 'go mod tidy'"
echo "Please run 'go mod tidy' locally and commit the changes"
diff go.sum.orig go.sum
exit 1
fi
echo "SUCCESS: go.mod and go.sum in main directory are tidy"
- name: Check go.mod and go.sum in test directory
run: |
cd test
# Store original file state
cp go.mod go.mod.orig
cp go.sum go.sum.orig
# Run go mod tidy
go mod tidy
# Check if files changed
if ! diff -q go.mod.orig go.mod > /dev/null 2>&1; then
echo "ERROR: go.mod in test directory has changed after running 'go mod tidy'"
echo "Please run 'go mod tidy' locally and commit the changes"
diff go.mod.orig go.mod
exit 1
fi
if ! diff -q go.sum.orig go.sum > /dev/null 2>&1; then
echo "ERROR: go.sum in test directory has changed after running 'go mod tidy'"
echo "Please run 'go mod tidy' locally and commit the changes"
diff go.sum.orig go.sum
exit 1
fi
echo "SUCCESS: go.mod and go.sum in test directory are tidy"

View File

@@ -15,7 +15,7 @@ jobs:
#runs-on: alrest-techarohq
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
@@ -24,57 +24,29 @@ jobs:
sudo apt-get update
sudo apt-get install -y build-essential
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Setup Homebrew cellar cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
path: |
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/var
key: ${{ runner.os }}-go-homebrew-cellar-${{ hashFiles('go.sum') }}
restore-keys: |
${{ runner.os }}-go-homebrew-cellar-
- name: Install Brew dependencies
run: |
brew bundle
- name: Setup Golang caches
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
node-version: '24.11.0'
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-golang-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-golang-
go-version: '1.25.4'
- name: Cache playwright binaries
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
id: playwright-cache
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/go.sum') }}
- name: install playwright browsers
run: |
npx --yes playwright@1.51.1 install --with-deps
npx --yes playwright@1.51.1 run-server --port 9001 &
- name: install node deps
run: |
npm ci
npm run assets
- name: install playwright browsers
run: |
npx --no-install playwright@1.52.0 install --with-deps
npx --no-install playwright@1.52.0 run-server --port 9001 &
- name: Build
run: npm run build
@@ -82,6 +54,11 @@ jobs:
- name: Test
run: npm run test
- uses: dominikh/staticcheck-action@fe1dd0c3658873b46f8c9bb3291096a617310ca6 # v1.3.1
- name: Lint with staticcheck
uses: dominikh/staticcheck-action@024238d2898c874f26d723e7d0ff4308c35589a2 # v1.4.0
with:
version: "latest"
- name: Govulncheck
run: |
go tool govulncheck ./...

View File

@@ -1,8 +1,9 @@
name: Package builds (stable)
on:
release:
types: [published]
workflow_dispatch:
# release:
# types: [published]
permissions:
contents: write
@@ -13,7 +14,7 @@ jobs:
#runs-on: alrest-techarohq
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
fetch-tags: true
@@ -24,39 +25,12 @@ jobs:
sudo apt-get update
sudo apt-get install -y build-essential
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Setup Homebrew cellar cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
path: |
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/var
key: ${{ runner.os }}-go-homebrew-cellar-${{ hashFiles('go.sum') }}
restore-keys: |
${{ runner.os }}-go-homebrew-cellar-
- name: Install Brew dependencies
run: |
brew bundle
- name: Setup Golang caches
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
node-version: '24.11.0'
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-golang-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-golang-
go-version: '1.25.4'
- name: install node deps
run: |
@@ -64,10 +38,7 @@ jobs:
- name: Build Packages
run: |
wget https://github.com/TecharoHQ/yeet/releases/download/v0.2.1/yeet_0.2.1_amd64.deb -O var/yeet.deb
sudo apt -y install -f ./var/yeet.deb
rm ./var/yeet.deb
yeet
go tool yeet
- name: Upload released artifacts
env:

View File

@@ -15,7 +15,7 @@ jobs:
#runs-on: alrest-techarohq
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
fetch-tags: true
@@ -26,39 +26,12 @@ jobs:
sudo apt-get update
sudo apt-get install -y build-essential
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Setup Homebrew cellar cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
path: |
/home/linuxbrew/.linuxbrew/Cellar
/home/linuxbrew/.linuxbrew/bin
/home/linuxbrew/.linuxbrew/etc
/home/linuxbrew/.linuxbrew/include
/home/linuxbrew/.linuxbrew/lib
/home/linuxbrew/.linuxbrew/opt
/home/linuxbrew/.linuxbrew/sbin
/home/linuxbrew/.linuxbrew/share
/home/linuxbrew/.linuxbrew/var
key: ${{ runner.os }}-go-homebrew-cellar-${{ hashFiles('go.sum') }}
restore-keys: |
${{ runner.os }}-go-homebrew-cellar-
- name: Install Brew dependencies
run: |
brew bundle
- name: Setup Golang caches
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
node-version: '24.11.0'
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-golang-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-golang-
go-version: '1.25.4'
- name: install node deps
run: |
@@ -66,12 +39,9 @@ jobs:
- name: Build Packages
run: |
wget https://github.com/TecharoHQ/yeet/releases/download/v0.2.1/yeet_0.2.1_amd64.deb -O var/yeet.deb
sudo apt -y install -f ./var/yeet.deb
rm ./var/yeet.deb
yeet
go tool yeet
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: packages
path: var/*

64
.github/workflows/smoke-tests.yml vendored Normal file
View File

@@ -0,0 +1,64 @@
name: Smoke tests
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions:
contents: read
jobs:
smoke-test:
strategy:
matrix:
test:
- default-config-macro
- docker-registry
- double_slash
- forced-language
- git-clone
- git-push
- healthcheck
- i18n
- log-file
- nginx
- palemoon/amd64
#- palemoon/i386
- robots_txt
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: "24.11.0"
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version: "1.25.4"
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
- name: Install utils
run: |
go install ./utils/cmd/...
- name: Run test
run: |
cd test/${{ matrix.test }}
backoff-retry --try-count 10 ./test.sh
- name: Sanitize artifact name
if: always()
run: echo "ARTIFACT_NAME=${{ matrix.test }}" | sed 's|/|-|g' >> $GITHUB_ENV
- name: Upload artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
if: always()
with:
name: ${{ env.ARTIFACT_NAME }}
path: test/${{ matrix.test }}/var

118
.github/workflows/spelling.yml vendored Normal file
View File

@@ -0,0 +1,118 @@
name: Check Spelling
# Comment management is handled through a secondary job, for details see:
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
#
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
# (in odd cases, it might actually run just to collapse a comment, but that's fairly rare)
# it needs `contents: write` in order to add a comment.
#
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
# it needs `pull-requests: write` in order to manipulate those comments.
# Updating pull request branches is managed via comment handling.
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
#
# These elements work together to make it happen:
#
# `on.issue_comment`
# This event listens to comments by users asking to update the metadata.
#
# `jobs.update`
# This job runs in response to an issue_comment and will push a new commit
# to update the spelling metadata.
#
# `with.experimental_apply_changes_via_bot`
# Tells the action to support and generate messages that enable it
# to make a commit to update the spelling metadata.
#
# `with.ssh_key`
# In order to trigger workflows when the commit is made, you can provide a
# secret (typically, a write-enabled github deploy key).
#
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
# SARIF reporting
#
# Access to SARIF reports is generally restricted (by GitHub) to members of the repository.
#
# Requires enabling `security-events: write`
# and configuring the action with `use_sarif: 1`
#
# For information on the feature, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-SARIF-output
# Minimal workflow structure:
#
# on:
# push:
# ...
# pull_request_target:
# ...
# jobs:
# # you only want the spelling job, all others should be omitted
# spelling:
# # remove `security-events: write` and `use_sarif: 1`
# # remove `experimental_apply_changes_via_bot: 1`
# ... otherwise adjust the `with:` as you wish
on:
push:
branches:
- '**'
tags-ignore:
- '**'
pull_request:
branches:
- '**'
types:
- 'opened'
- 'reopened'
- 'synchronize'
jobs:
spelling:
name: Check Spelling
permissions:
contents: read
pull-requests: read
actions: read
security-events: write
outputs:
followup: ${{ steps.spelling.outputs.followup }}
runs-on: ubuntu-latest
if: ${{ contains(github.event_name, 'pull_request') || github.event_name == 'push' }}
concurrency:
group: spelling-${{ github.event.pull_request.number || github.ref }}
# note: If you use only_check_changed_files, you do not want cancel-in-progress
cancel-in-progress: true
steps:
- name: check-spelling
id: spelling
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
with:
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
checkout: true
check_file_names: 1
post_comment: 0
use_magic_file: 1
warnings: bad-regex,binary-file,deprecated-feature,ignored-expect-variant,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check,unclosed-block-ignore-begin,unclosed-block-ignore-end
use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }}
check_extra_dictionaries: ""
dictionary_source_prefixes: >
{
"cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20241114/dictionaries/"
}
extra_dictionaries: |
cspell:software-terms/softwareTerms.txt
cspell:golang/go.txt
cspell:npm/npm.txt
cspell:k8s/k8s.txt
cspell:python/python/python-lib.txt
cspell:aws/aws.txt
cspell:node/node.txt
cspell:html/html.txt
cspell:filetypes/filetypes.txt
cspell:python/common/extra.txt
cspell:docker/docker-words.txt
cspell:fullstack/fullstack.txt

View File

@@ -0,0 +1,37 @@
name: Regenerate ssh ci runner image
on:
# pull_request:
# branches: ["main"]
schedule:
- cron: "0 0 1,8,15,22 * *"
workflow_dispatch:
permissions:
pull-requests: write
contents: write
packages: write
jobs:
ssh-ci-rebuild:
if: github.repository == 'TecharoHQ/anubis'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-tags: true
fetch-depth: 0
persist-credentials: false
- name: Log into registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Build and push
run: |
cd ./test/ssh-ci
docker buildx bake --push

45
.github/workflows/ssh-ci.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: SSH CI
on:
push:
branches: ["main"]
# pull_request:
# branches: ["main"]
permissions:
contents: read
jobs:
ssh:
if: github.repository == 'TecharoHQ/anubis'
runs-on: alrest-techarohq
strategy:
matrix:
host:
- riscv64
- ppc64le
- aarch64-4k
- aarch64-16k
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-tags: true
fetch-depth: 0
persist-credentials: false
- name: Install CI target SSH key
uses: shimataro/ssh-key-action@d4fffb50872869abe2d9a9098a6d9c5aa7d16be4 # v2.7.0
with:
key: ${{ secrets.CI_SSH_KEY }}
name: id_rsa
known_hosts: ${{ secrets.CI_SSH_KNOWN_HOSTS }}
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version: '1.25.4'
- name: Run CI
run: go run ./utils/cmd/backoff-retry bash test/ssh-ci/rigging.sh ${{ matrix.host }}
env:
GITHUB_RUN_ID: ${{ github.run_id }}

View File

@@ -16,12 +16,12 @@ jobs:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6.0.0
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
- name: Run zizmor 🌈
run: uvx zizmor --format sarif . > results.sarif
@@ -29,7 +29,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
with:
sarif_file: results.sarif
category: zizmor

5
.github/zizmor.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
rules:
unpinned-uses:
config:
policies:
Homebrew/actions/*: any

2
.gitignore vendored
View File

@@ -20,3 +20,5 @@ node_modules
# how does this get here
doc/VERSION
web/static/locales/*.json

11
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"ms-azuretools.vscode-containers",
"golang.go",
"unifiedjs.vscode-mdx",
"a-h.templ",
"redhat.vscode-yaml",
"streetsidesoftware.code-spell-checker"
]
}

27
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,27 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}"
},
{
"name": "Anubis [dev]",
"command": "npm run dev",
"request": "launch",
"type": "node-terminal"
},
{
"name": "Start Docs",
"command": "cd docs && npm ci && npm run start",
"request": "launch",
"type": "node-terminal"
}
]
}

34
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,34 @@
{
"github.copilot.enable": {
"*": false,
"plaintext": false,
"markdown": false,
"mdx": false,
"json": false,
"scminput": false,
"yaml": false,
"go": false,
"zig": false,
"javascript": false,
"properties": false
},
"[markdown]": {
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"editor.wordBasedSuggestions": "off"
},
"[mdx]": {
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"editor.wordBasedSuggestions": "off"
},
"[nunjucks]": {
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"editor.wordBasedSuggestions": "off"
},
"cSpell.enabledFileTypes": {
"mdx": true,
"md": true
}
}

View File

@@ -18,14 +18,17 @@ assets: deps
build: assets
$(GO) build -o ./var/anubis ./cmd/anubis
$(GO) build -o ./var/robots2policy ./cmd/robots2policy
@echo "Anubis is now built to ./var/anubis"
lint: assets
$(GO) vet ./...
$(GO) tool staticcheck ./...
$(GO) tool govulncheck ./...
prebaked-build:
$(GO) build -o ./var/anubis -ldflags "-X 'github.com/TecharoHQ/anubis.Version=$(VERSION)'" ./cmd/anubis
$(GO) build -o ./var/robots2policy -ldflags "-X 'github.com/TecharoHQ/anubis.Version=$(VERSION)'" ./cmd/robots2policy
test: assets
$(GO) test ./...

View File

@@ -9,16 +9,56 @@
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/TecharoHQ/anubis)
![language count](https://img.shields.io/github/languages/count/TecharoHQ/anubis)
![repo size](https://img.shields.io/github/repo-size/TecharoHQ/anubis)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/Xe)](https://github.com/sponsors/Xe)
## Sponsors
Anubis is brought to you by sponsors and donors like:
[![Distrust](./docs/static/img/sponsors/distrust-logo.webp)](https://distrust.co)
### Diamond Tier
<a href="https://www.raptorcs.com/content/base/products.html">
<img src="./docs/static/img/sponsors/raptor-computing-logo.webp" alt="Raptor Computing Systems" height=64 />
</a>
### Gold Tier
<a href="https://distrust.co?utm_campaign=github&utm_medium=referral&utm_content=anubis">
<img src="./docs/static/img/sponsors/distrust-logo.webp" alt="Distrust" height="64">
</a>
<a href="https://terminaltrove.com/?utm_campaign=github&utm_medium=referral&utm_content=anubis&utm_source=abgh">
<img src="./docs/static/img/sponsors/terminal-trove.webp" alt="Terminal Trove" height="64">
</a>
<a href="https://canine.tools?utm_campaign=github&utm_medium=referral&utm_content=anubis">
<img src="./docs/static/img/sponsors/caninetools-logo.webp" alt="canine.tools" height="64">
</a>
<a href="https://weblate.org/">
<img src="./docs/static/img/sponsors/weblate-logo.webp" alt="Weblate" height="64">
</a>
<a href="https://uberspace.de/">
<img src="./docs/static/img/sponsors/uberspace-logo.webp" alt="Uberspace" height="64">
</a>
<a href="https://wildbase.xyz/">
<img src="./docs/static/img/sponsors/wildbase-logo.webp" alt="Wildbase" height="64">
</a>
<a href="https://emma.pet">
<img
src="./docs/static/img/sponsors/nepeat-logo.webp"
alt="Cat eyes over the word Emma in a serif font"
height="64"
/>
</a>
<a href="https://fabulous.systems/">
<img
src="./docs/static/img/sponsors/fabulous-systems.webp"
alt="Cat eyes over the word Emma in a serif font"
height="64"
/>
</a>
## Overview
Anubis [weighs the soul of your connection](https://en.wikipedia.org/wiki/Weighing_of_souls) using a proof-of-work challenge in order to protect upstream resources from scraper bots.
Anubis is a Web AI Firewall Utility that [weighs the soul of your connection](https://en.wikipedia.org/wiki/Weighing_of_souls) using one or more challenges in order to protect upstream resources from scraper bots.
This program is designed to help protect the small internet from the endless storm of requests that flood in from AI companies. Anubis is as lightweight as possible to ensure that everyone can afford to protect the communities closest to them.
@@ -26,7 +66,7 @@ Anubis is a bit of a nuclear response. This will result in your website being bl
In most cases, you should not need this and can probably get by using Cloudflare to protect a given origin. However, for circumstances where you can't or won't use Cloudflare, Anubis is there for you.
If you want to try this out, connect to [anubis.techaro.lol](https://anubis.techaro.lol).
If you want to try this out, visit the Anubis documentation site at [anubis.techaro.lol](https://anubis.techaro.lol).
## Support

13
SECURITY.md Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
Techaro follows the [Semver 2.0 scheme](https://semver.org/).
## Supported Versions
Techaro strives to support the two most recent minor versions of Anubis. Patches to those versions will be published as patch releases.
## Reporting a Vulnerability
Email security@techaro.lol with details on the vulnerability and reproduction steps. You will get a response as soon as possible.
Please take care to send your email as a mixed plaintext and HTML message. Messages with GPG signatures or that are plaintext only may be blocked by the spam filter.

View File

@@ -1 +1 @@
1.17.1
1.24.0

View File

@@ -11,7 +11,11 @@ var Version = "devel"
// CookieName is the name of the cookie that Anubis uses in order to validate
// access.
const CookieName = "within.website-x-cmd-anubis-auth"
var CookieName = "techaro.lol-anubis"
// TestCookieName is the name of the cookie that Anubis uses in order to check
// if cookies are enabled on the client's browser.
var TestCookieName = "techaro.lol-anubis-cookie-verification"
// CookieDefaultExpirationTime is the amount of time before the cookie/JWT expires.
const CookieDefaultExpirationTime = 7 * 24 * time.Hour
@@ -19,6 +23,9 @@ const CookieDefaultExpirationTime = 7 * 24 * time.Hour
// BasePrefix is a global prefix for all Anubis endpoints. Can be emptied to remove the prefix entirely.
var BasePrefix = ""
// PublicUrl is the externally accessible URL for this Anubis instance.
var PublicUrl = ""
// StaticPath is the location where all static Anubis assets are located.
const StaticPath = "/.within.website/x/cmd/anubis/"
@@ -28,3 +35,10 @@ const APIPrefix = "/.within.website/x/cmd/anubis/api/"
// DefaultDifficulty is the default "difficulty" (number of leading zeroes)
// that must be met by the client in order to pass the challenge.
const DefaultDifficulty = 4
// ForcedLanguage is the language being used instead of the one of the request's Accept-Language header
// if being set.
var ForcedLanguage = ""
// UseSimplifiedExplanation can be set to true for using the simplified explanation
var UseSimplifiedExplanation = false

View File

@@ -5,6 +5,7 @@ import (
"context"
"crypto/ed25519"
"crypto/rand"
"crypto/tls"
"embed"
"encoding/hex"
"errors"
@@ -30,11 +31,14 @@ import (
"github.com/TecharoHQ/anubis/data"
"github.com/TecharoHQ/anubis/internal"
libanubis "github.com/TecharoHQ/anubis/lib"
"github.com/TecharoHQ/anubis/lib/config"
botPolicy "github.com/TecharoHQ/anubis/lib/policy"
"github.com/TecharoHQ/anubis/lib/policy/config"
"github.com/TecharoHQ/anubis/lib/thoth"
"github.com/TecharoHQ/anubis/web"
"github.com/facebookgo/flagenv"
_ "github.com/joho/godotenv/autoload"
"github.com/prometheus/client_golang/prometheus/promhttp"
healthv1 "google.golang.org/grpc/health/grpc_health_v1"
)
var (
@@ -43,8 +47,16 @@ var (
bindNetwork = flag.String("bind-network", "tcp", "network family to bind HTTP to, e.g. unix, tcp")
challengeDifficulty = flag.Int("difficulty", anubis.DefaultDifficulty, "difficulty of the challenge")
cookieDomain = flag.String("cookie-domain", "", "if set, the top-level domain that the Anubis cookie will be valid for")
cookieDynamicDomain = flag.Bool("cookie-dynamic-domain", false, "if set, automatically set the cookie Domain value based on the request domain")
cookieExpiration = flag.Duration("cookie-expiration-time", anubis.CookieDefaultExpirationTime, "The amount of time the authorization cookie is valid for")
cookiePrefix = flag.String("cookie-prefix", anubis.CookieName, "prefix for browser cookies created by Anubis")
cookiePartitioned = flag.Bool("cookie-partitioned", false, "if true, sets the partitioned flag on Anubis cookies, enabling CHIPS support")
difficultyInJWT = flag.Bool("difficulty-in-jwt", false, "if true, adds a difficulty field in the JWT claims")
useSimplifiedExplanation = flag.Bool("use-simplified-explanation", false, "if true, replaces the text when clicking \"Why am I seeing this?\" with a more simplified text for a non-tech-savvy audience.")
forcedLanguage = flag.String("forced-language", "", "if set, this language is being used instead of the one from the request's Accept-Language header")
hs512Secret = flag.String("hs512-secret", "", "secret used to sign JWTs, uses ed25519 if not set")
cookieSecure = flag.Bool("cookie-secure", true, "if true, sets the secure flag on Anubis cookies")
cookieSameSite = flag.String("cookie-same-site", "None", "sets the same site option on Anubis cookies, will auto-downgrade None to Lax if cookie-secure is false. Valid values are None, Lax, Strict, and Default.")
ed25519PrivateKeyHex = flag.String("ed25519-private-key-hex", "", "private key used to sign JWTs, if not set a random one will be assigned")
ed25519PrivateKeyHexFile = flag.String("ed25519-private-key-hex-file", "", "file name containing value for ed25519-private-key-hex")
metricsBind = flag.String("metrics-bind", ":9090", "network address to bind metrics to")
@@ -54,15 +66,29 @@ var (
policyFname = flag.String("policy-fname", "", "full path to anubis policy document (defaults to a sensible built-in policy)")
redirectDomains = flag.String("redirect-domains", "", "list of domains separated by commas which anubis is allowed to redirect to. Leaving this unset allows any domain.")
slogLevel = flag.String("slog-level", "INFO", "logging level (see https://pkg.go.dev/log/slog#hdr-Levels)")
stripBasePrefix = flag.Bool("strip-base-prefix", false, "if true, strips the base prefix from requests forwarded to the target server")
target = flag.String("target", "http://localhost:3923", "target to reverse proxy to, set to an empty string to disable proxying when only using auth request")
targetSNI = flag.String("target-sni", "", "if set, TLS handshake hostname when forwarding requests to the target, if set to auto, use Host header")
targetHost = flag.String("target-host", "", "if set, the value of the Host header when forwarding requests to the target")
targetInsecureSkipVerify = flag.Bool("target-insecure-skip-verify", false, "if true, skips TLS validation for the backend")
targetDisableKeepAlive = flag.Bool("target-disable-keepalive", false, "if true, disables HTTP keep-alive for the backend")
healthcheck = flag.Bool("healthcheck", false, "run a health check against Anubis")
useRemoteAddress = flag.Bool("use-remote-address", false, "read the client's IP address from the network request, useful for debugging and running Anubis on bare metal")
debugBenchmarkJS = flag.Bool("debug-benchmark-js", false, "respond to every request with a challenge for benchmarking hashrate")
ogPassthrough = flag.Bool("og-passthrough", true, "enable Open Graph tag passthrough")
ogPassthrough = flag.Bool("og-passthrough", false, "enable Open Graph tag passthrough")
ogTimeToLive = flag.Duration("og-expiry-time", 24*time.Hour, "Open Graph tag cache expiration time")
ogCacheConsiderHost = flag.Bool("og-cache-consider-host", false, "enable or disable the use of the host in the Open Graph tag cache")
extractResources = flag.String("extract-resources", "", "if set, extract the static resources to the specified folder")
webmasterEmail = flag.String("webmaster-email", "", "if set, displays webmaster's email on the reject page for appeals")
versionFlag = flag.Bool("version", false, "print Anubis version")
publicUrl = flag.String("public-url", "", "the externally accessible URL for this Anubis instance, used for constructing redirect URLs (e.g., for forwardAuth).")
xffStripPrivate = flag.Bool("xff-strip-private", true, "if set, strip private addresses from X-Forwarded-For")
customRealIPHeader = flag.String("custom-real-ip-header", "", "if set, read remote IP from header of this name (in case your environment doesn't set X-Real-IP header)")
thothInsecure = flag.Bool("thoth-insecure", false, "if set, connect to Thoth over plain HTTP/2, don't enable this unless support told you to")
thothURL = flag.String("thoth-url", "", "if set, URL for Thoth, the IP reputation database for Anubis")
thothToken = flag.String("thoth-token", "", "if set, API token for Thoth, the IP reputation database for Anubis")
jwtRestrictionHeader = flag.String("jwt-restriction-header", "X-Real-IP", "If set, the JWT is only valid if the current value of this header matched the value when the JWT was created")
)
func keyFromHex(value string) (ed25519.PrivateKey, error) {
@@ -79,7 +105,7 @@ func keyFromHex(value string) (ed25519.PrivateKey, error) {
}
func doHealthCheck() error {
resp, err := http.Get("http://localhost" + *metricsBind + anubis.BasePrefix + "/metrics")
resp, err := http.Get("http://localhost" + *metricsBind + "/healthz")
if err != nil {
return fmt.Errorf("failed to fetch metrics: %w", err)
}
@@ -92,8 +118,57 @@ func doHealthCheck() error {
return nil
}
// parseBindNetFromAddr determine bind network and address based on the given network and address.
func parseBindNetFromAddr(address string) (string, string) {
defaultScheme := "http://"
if !strings.Contains(address, "://") {
if strings.HasPrefix(address, ":") {
address = defaultScheme + "localhost" + address
} else {
address = defaultScheme + address
}
}
bindUri, err := url.Parse(address)
if err != nil {
log.Fatal(fmt.Errorf("failed to parse bind URL: %w", err))
}
switch bindUri.Scheme {
case "unix":
return "unix", bindUri.Path
case "tcp", "http", "https":
return "tcp", bindUri.Host
default:
log.Fatal(fmt.Errorf("unsupported network scheme %s in address %s", bindUri.Scheme, address))
}
return "", address
}
func parseSameSite(s string) http.SameSite {
switch strings.ToLower(s) {
case "none":
return http.SameSiteNoneMode
case "lax":
return http.SameSiteLaxMode
case "strict":
return http.SameSiteStrictMode
case "default":
return http.SameSiteDefaultMode
default:
log.Fatalf("invalid cookie same-site mode: %s, valid values are None, Lax, Strict, and Default", s)
}
return http.SameSiteDefaultMode
}
func setupListener(network string, address string) (net.Listener, string) {
formattedAddress := ""
if network == "" {
// keep compatibility
network, address = parseBindNetFromAddr(address)
}
switch network {
case "unix":
formattedAddress = "unix:" + address
@@ -133,7 +208,7 @@ func setupListener(network string, address string) (net.Listener, string) {
return listener, formattedAddress
}
func makeReverseProxy(target string) (http.Handler, error) {
func makeReverseProxy(target string, targetSNI string, targetHost string, insecureSkipVerify bool, targetDisableKeepAlive bool) (http.Handler, error) {
targetUri, err := url.Parse(target)
if err != nil {
return nil, fmt.Errorf("failed to parse target URL: %w", err)
@@ -141,6 +216,10 @@ func makeReverseProxy(target string) (http.Handler, error) {
transport := http.DefaultTransport.(*http.Transport).Clone()
if targetDisableKeepAlive {
transport.DisableKeepAlives = true
}
// https://github.com/oauth2-proxy/oauth2-proxy/blob/4e2100a2879ef06aea1411790327019c1a09217c/pkg/upstream/http.go#L124
if targetUri.Scheme == "unix" {
// clean path up so we don't use the socket path in proxied requests
@@ -155,31 +234,57 @@ func makeReverseProxy(target string) (http.Handler, error) {
transport.RegisterProtocol("unix", libanubis.UnixRoundTripper{Transport: transport})
}
if insecureSkipVerify || targetSNI != "" {
transport.TLSClientConfig = &tls.Config{}
}
if insecureSkipVerify {
slog.Warn("TARGET_INSECURE_SKIP_VERIFY is set to true, TLS certificate validation will not be performed", "target", target)
transport.TLSClientConfig.InsecureSkipVerify = true
}
if targetSNI != "" && targetSNI != "auto" {
transport.TLSClientConfig.ServerName = targetSNI
}
rp := httputil.NewSingleHostReverseProxy(targetUri)
rp.Transport = transport
if targetHost != "" || targetSNI == "auto" {
originalDirector := rp.Director
rp.Director = func(req *http.Request) {
originalDirector(req)
if targetHost != "" {
req.Host = targetHost
}
if targetSNI == "auto" {
transport.TLSClientConfig.ServerName = req.Host
}
}
}
return rp, nil
}
func startDecayMapCleanup(ctx context.Context, s *libanubis.Server) {
ticker := time.NewTicker(1 * time.Hour)
defer ticker.Stop()
for {
select {
case <-ticker.C:
s.CleanupDecayMap()
case <-ctx.Done():
return
}
}
}
func main() {
flagenv.Parse()
flag.Parse()
internal.InitSlog(*slogLevel)
if *versionFlag {
fmt.Println("Anubis", anubis.Version)
return
}
internal.SetHealth("anubis", healthv1.HealthCheckResponse_NOT_SERVING)
lg := internal.InitSlog(*slogLevel, os.Stderr)
lg.Info("starting up Anubis")
if *healthcheck {
log.Println("running healthcheck")
if err := doHealthCheck(); err != nil {
log.Fatal(err)
}
return
}
if *extractResources != "" {
if err := extractEmbedFS(data.BotPolicies, ".", *extractResources); err != nil {
@@ -192,31 +297,75 @@ func main() {
return
}
// install signal handler
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
wg := new(sync.WaitGroup)
if *metricsBind != "" {
wg.Add(1)
go metricsServer(ctx, *lg.With("subsystem", "metrics"), wg.Done)
}
var rp http.Handler
// when using anubis via Systemd and environment variables, then it is not possible to set targe to an empty string but only to space
if strings.TrimSpace(*target) != "" {
var err error
rp, err = makeReverseProxy(*target)
rp, err = makeReverseProxy(*target, *targetSNI, *targetHost, *targetInsecureSkipVerify, *targetDisableKeepAlive)
if err != nil {
log.Fatalf("can't make reverse proxy: %v", err)
}
}
policy, err := libanubis.LoadPoliciesOrDefault(*policyFname, *challengeDifficulty)
if *cookieDomain != "" && *cookieDynamicDomain {
log.Fatalf("you can't set COOKIE_DOMAIN and COOKIE_DYNAMIC_DOMAIN at the same time")
}
// Thoth configuration
switch {
case *thothURL != "" && *thothToken == "":
lg.Warn("THOTH_URL is set but no THOTH_TOKEN is set")
case *thothURL == "" && *thothToken != "":
lg.Warn("THOTH_TOKEN is set but no THOTH_URL is set")
case *thothURL != "" && *thothToken != "":
lg.Debug("connecting to Thoth")
thothClient, err := thoth.New(ctx, *thothURL, *thothToken, *thothInsecure)
if err != nil {
log.Fatalf("can't dial thoth at %s: %v", *thothURL, err)
}
ctx = thoth.With(ctx, thothClient)
}
lg.Info("loading policy file", "fname", *policyFname)
policy, err := libanubis.LoadPoliciesOrDefault(ctx, *policyFname, *challengeDifficulty, *slogLevel)
if err != nil {
log.Fatalf("can't parse policy file: %v", err)
}
lg = policy.Logger
lg.Debug("swapped to new logger")
slog.SetDefault(lg)
fmt.Println("Rule error IDs:")
// Warn if persistent storage is used without a configured signing key
if policy.Store.IsPersistent() {
if *hs512Secret == "" && *ed25519PrivateKeyHex == "" && *ed25519PrivateKeyHexFile == "" {
lg.Warn("[misconfiguration] persistent storage backend is configured, but no private key is set. " +
"Challenges will be invalidated when Anubis restarts. " +
"Set HS512_SECRET, ED25519_PRIVATE_KEY_HEX, or ED25519_PRIVATE_KEY_HEX_FILE to ensure challenges survive service restarts. " +
"See: https://anubis.techaro.lol/docs/admin/installation#key-generation")
}
}
ruleErrorIDs := make(map[string]string)
for _, rule := range policy.Bots {
if rule.Action != config.RuleDeny {
continue
}
hash := rule.Hash()
fmt.Printf("* %s: %s\n", rule.Name, hash)
ruleErrorIDs[rule.Name] = hash
}
fmt.Println()
// replace the bot policy rules with a single rule that always benchmarks
if *debugBenchmarkJS {
@@ -231,12 +380,20 @@ func main() {
} else if strings.HasSuffix(*basePrefix, "/") {
log.Fatalf("[misconfiguration] base-prefix must not end with a slash")
}
if *stripBasePrefix && *basePrefix == "" {
log.Fatalf("[misconfiguration] strip-base-prefix is set to true, but base-prefix is not set, " +
"this may result in unexpected behavior")
}
var priv ed25519.PrivateKey
if *ed25519PrivateKeyHex != "" && *ed25519PrivateKeyHexFile != "" {
var ed25519Priv ed25519.PrivateKey
if *hs512Secret != "" && (*ed25519PrivateKeyHex != "" || *ed25519PrivateKeyHexFile != "") {
log.Fatal("do not specify both HS512 and ED25519 secrets")
} else if *hs512Secret != "" {
ed25519Priv = ed25519.PrivateKey(*hs512Secret)
} else if *ed25519PrivateKeyHex != "" && *ed25519PrivateKeyHexFile != "" {
log.Fatal("do not specify both ED25519_PRIVATE_KEY_HEX and ED25519_PRIVATE_KEY_HEX_FILE")
} else if *ed25519PrivateKeyHex != "" {
priv, err = keyFromHex(*ed25519PrivateKeyHex)
ed25519Priv, err = keyFromHex(*ed25519PrivateKeyHex)
if err != nil {
log.Fatalf("failed to parse and validate ED25519_PRIVATE_KEY_HEX: %v", err)
}
@@ -246,17 +403,17 @@ func main() {
log.Fatalf("failed to read ED25519_PRIVATE_KEY_HEX_FILE %s: %v", *ed25519PrivateKeyHexFile, err)
}
priv, err = keyFromHex(string(bytes.TrimSpace(hexFile)))
ed25519Priv, err = keyFromHex(string(bytes.TrimSpace(hexFile)))
if err != nil {
log.Fatalf("failed to parse and validate content of ED25519_PRIVATE_KEY_HEX_FILE: %v", err)
}
} else {
_, priv, err = ed25519.GenerateKey(rand.Reader)
_, ed25519Priv, err = ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Fatalf("failed to generate ed25519 key: %v", err)
}
slog.Warn("generating random key, Anubis will have strange behavior when multiple instances are behind the same load balancer target, for more information: see https://anubis.techaro.lol/docs/admin/installation#key-generation")
lg.Warn("generating random key, Anubis will have strange behavior when multiple instances are behind the same load balancer target, for more information: see https://anubis.techaro.lol/docs/admin/installation#key-generation")
}
var redirectDomainsList []string
@@ -270,49 +427,64 @@ func main() {
redirectDomainsList = append(redirectDomainsList, strings.TrimSpace(domain))
}
} else {
slog.Warn("REDIRECT_DOMAINS is not set, Anubis will only redirect to the same domain a request is coming from, see https://anubis.techaro.lol/docs/admin/configuration/redirect-domains")
lg.Warn("REDIRECT_DOMAINS is not set, Anubis will only redirect to the same domain a request is coming from, see https://anubis.techaro.lol/docs/admin/configuration/redirect-domains")
}
anubis.CookieName = *cookiePrefix + "-auth"
anubis.TestCookieName = *cookiePrefix + "-cookie-verification"
anubis.ForcedLanguage = *forcedLanguage
anubis.UseSimplifiedExplanation = *useSimplifiedExplanation
// If OpenGraph configuration values are not set in the config file, use the
// values from flags / envvars.
if !policy.OpenGraph.Enabled {
policy.OpenGraph.Enabled = *ogPassthrough
policy.OpenGraph.ConsiderHost = *ogCacheConsiderHost
policy.OpenGraph.TimeToLive = *ogTimeToLive
policy.OpenGraph.Override = map[string]string{}
}
s, err := libanubis.New(libanubis.Options{
BasePrefix: *basePrefix,
StripBasePrefix: *stripBasePrefix,
Next: rp,
Policy: policy,
TargetHost: *targetHost,
TargetSNI: *targetSNI,
TargetInsecureSkipVerify: *targetInsecureSkipVerify,
ServeRobotsTXT: *robotsTxt,
PrivateKey: priv,
ED25519PrivateKey: ed25519Priv,
HS512Secret: []byte(*hs512Secret),
CookieDomain: *cookieDomain,
CookieDynamicDomain: *cookieDynamicDomain,
CookieExpiration: *cookieExpiration,
CookiePartitioned: *cookiePartitioned,
OGPassthrough: *ogPassthrough,
OGTimeToLive: *ogTimeToLive,
RedirectDomains: redirectDomainsList,
Target: *target,
WebmasterEmail: *webmasterEmail,
OGCacheConsidersHost: *ogCacheConsiderHost,
OpenGraph: policy.OpenGraph,
CookieSecure: *cookieSecure,
CookieSameSite: parseSameSite(*cookieSameSite),
PublicUrl: *publicUrl,
JWTRestrictionHeader: *jwtRestrictionHeader,
Logger: policy.Logger.With("subsystem", "anubis"),
DifficultyInJWT: *difficultyInJWT,
})
if err != nil {
log.Fatalf("can't construct libanubis.Server: %v", err)
}
wg := new(sync.WaitGroup)
// install signal handler
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
if *metricsBind != "" {
wg.Add(1)
go metricsServer(ctx, wg.Done)
}
go startDecayMapCleanup(ctx, s)
var h http.Handler
h = s
h = internal.CustomRealIPHeader(*customRealIPHeader, h)
h = internal.RemoteXRealIP(*useRemoteAddress, *bindNetwork, h)
h = internal.XForwardedForToXRealIP(h)
h = internal.XForwardedForUpdate(h)
h = internal.XForwardedForUpdate(*xffStripPrivate, h)
h = internal.JA4H(h)
srv := http.Server{Handler: h}
srv := http.Server{Handler: h, ErrorLog: internal.GetFilteredHTTPLogger()}
listener, listenerUrl := setupListener(*bindNetwork, *bind)
slog.Info(
lg.Info(
"listening",
"url", listenerUrl,
"difficulty", *challengeDifficulty,
@@ -325,6 +497,8 @@ func main() {
"og-expiry-time", *ogTimeToLive,
"base-prefix", *basePrefix,
"cookie-expiration-time", *cookieExpiration,
"rule-error-ids", ruleErrorIDs,
"public-url", *publicUrl,
)
go func() {
@@ -336,29 +510,41 @@ func main() {
}
}()
internal.SetHealth("anubis", healthv1.HealthCheckResponse_SERVING)
if err := srv.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
wg.Wait()
}
func metricsServer(ctx context.Context, done func()) {
func metricsServer(ctx context.Context, lg slog.Logger, done func()) {
defer done()
mux := http.NewServeMux()
mux.Handle(anubis.BasePrefix+"/metrics", promhttp.Handler())
srv := http.Server{Handler: mux}
listener, metricsUrl := setupListener(*metricsBindNetwork, *metricsBind)
slog.Debug("listening for metrics", "url", metricsUrl)
if *healthcheck {
log.Println("running healthcheck")
if err := doHealthCheck(); err != nil {
log.Fatal(err)
mux.Handle("/metrics", promhttp.Handler())
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
st, ok := internal.GetHealth("anubis")
if !ok {
slog.Error("health service anubis does not exist, file a bug")
}
switch st {
case healthv1.HealthCheckResponse_NOT_SERVING:
http.Error(w, "NOT OK", http.StatusInternalServerError)
return
case healthv1.HealthCheckResponse_SERVING:
fmt.Fprintln(w, "OK")
return
default:
http.Error(w, "UNKNOWN", http.StatusFailedDependency)
return
}
})
srv := http.Server{Handler: mux, ErrorLog: internal.GetFilteredHTTPLogger()}
listener, metricsUrl := setupListener(*metricsBindNetwork, *metricsBind)
lg.Debug("listening for metrics", "url", metricsUrl)
go func() {
<-ctx.Done()
@@ -391,11 +577,11 @@ func extractEmbedFS(fsys embed.FS, root string, destDir string) error {
return os.MkdirAll(destPath, 0o700)
}
data, err := fs.ReadFile(fsys, path)
embeddedData, err := fs.ReadFile(fsys, path)
if err != nil {
return err
}
return os.WriteFile(destPath, data, 0o644)
return os.WriteFile(destPath, embeddedData, 0o644)
})
}

View File

@@ -28,7 +28,7 @@ func main() {
flagenv.Parse()
flag.Parse()
internal.InitSlog(*slogLevel)
slog.SetDefault(internal.InitSlog(*slogLevel, os.Stderr))
koDockerRepo := strings.TrimSuffix(*dockerRepo, "/"+filepath.Base(*dockerRepo))
@@ -46,6 +46,11 @@ func main() {
)
}
if strings.Contains(*dockerTags, ",") {
newTags := strings.Join(strings.Split(*dockerTags, ","), "\n")
dockerTags = &newTags
}
setOutput("docker_image", strings.SplitN(*dockerTags, "\n", 2)[0])
version, err := run("git describe --tags --always --dirty")

View File

@@ -0,0 +1,78 @@
/*
Batch process robots.txt files from archives like https://github.com/nrjones8/robots-dot-txt-archive-bot/tree/master/data/cleaned
into Anubis CEL policies. Usage: go run batch_process.go <directory with robots.txt files>
*/
package main
import (
"fmt"
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run batch_process.go <cleaned_directory>")
fmt.Println("Example: go run batch_process.go ./cleaned")
os.Exit(1)
}
cleanedDir := os.Args[1]
outputDir := "generated_policies"
// Create output directory
if err := os.MkdirAll(outputDir, 0755); err != nil {
log.Fatalf("Failed to create output directory: %v", err)
}
count := 0
err := filepath.WalkDir(cleanedDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
// Skip directories
if d.IsDir() {
return nil
}
// Generate policy name from file path
relPath, _ := filepath.Rel(cleanedDir, path)
policyName := strings.ReplaceAll(relPath, "/", "-")
policyName = strings.TrimSuffix(policyName, "-robots.txt")
policyName = strings.ReplaceAll(policyName, ".", "-")
outputFile := filepath.Join(outputDir, policyName+".yaml")
cmd := exec.Command("go", "run", "main.go",
"-input", path,
"-output", outputFile,
"-name", policyName,
"-format", "yaml")
if err := cmd.Run(); err != nil {
fmt.Printf("Warning: Failed to process %s: %v\n", path, err)
return nil // Continue processing other files
}
count++
if count%100 == 0 {
fmt.Printf("Processed %d files...\n", count)
} else if count%10 == 0 {
fmt.Print(".")
}
return nil
})
if err != nil {
log.Fatalf("Error walking directory: %v", err)
}
fmt.Printf("Successfully processed %d robots.txt files\n", count)
fmt.Printf("Generated policies saved to: %s/\n", outputDir)
}

384
cmd/robots2policy/main.go Normal file
View File

@@ -0,0 +1,384 @@
package main
import (
"bufio"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"regexp"
"strings"
"github.com/TecharoHQ/anubis/lib/config"
"sigs.k8s.io/yaml"
)
var (
inputFile = flag.String("input", "", "path to robots.txt file (use - for stdin)")
outputFile = flag.String("output", "", "output file path (use - for stdout, defaults to stdout)")
outputFormat = flag.String("format", "yaml", "output format: yaml or json")
baseAction = flag.String("action", "CHALLENGE", "default action for disallowed paths: ALLOW, DENY, CHALLENGE, WEIGH")
crawlDelay = flag.Int("crawl-delay-weight", 0, "if > 0, add weight adjustment for crawl-delay (difficulty adjustment)")
policyName = flag.String("name", "robots-txt-policy", "name for the generated policy")
userAgentDeny = flag.String("deny-user-agents", "DENY", "action for specifically blocked user agents: DENY, CHALLENGE")
helpFlag = flag.Bool("help", false, "show help")
)
type RobotsRule struct {
UserAgents []string
Disallows []string
Allows []string
CrawlDelay int
IsBlacklist bool // true if this is a specifically denied user agent
}
type AnubisRule struct {
Expression *config.ExpressionOrList `yaml:"expression,omitempty" json:"expression,omitempty"`
Challenge *config.ChallengeRules `yaml:"challenge,omitempty" json:"challenge,omitempty"`
Weight *config.Weight `yaml:"weight,omitempty" json:"weight,omitempty"`
Name string `yaml:"name" json:"name"`
Action string `yaml:"action" json:"action"`
}
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
fmt.Fprintf(os.Stderr, "%s [options] -input <robots.txt>\n\n", os.Args[0])
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, "\nExamples:")
fmt.Fprintln(os.Stderr, " # Convert local robots.txt file")
fmt.Fprintln(os.Stderr, " robots2policy -input robots.txt -output policy.yaml")
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, " # Convert from URL")
fmt.Fprintln(os.Stderr, " robots2policy -input https://example.com/robots.txt -format json")
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, " # Read from stdin, write to stdout")
fmt.Fprintln(os.Stderr, " curl https://example.com/robots.txt | robots2policy -input -")
os.Exit(2)
}
}
func main() {
flag.Parse()
if len(flag.Args()) > 0 || *helpFlag || *inputFile == "" {
flag.Usage()
}
// Read robots.txt
var input io.Reader
if *inputFile == "-" {
input = os.Stdin
} else if strings.HasPrefix(*inputFile, "http://") || strings.HasPrefix(*inputFile, "https://") {
resp, err := http.Get(*inputFile)
if err != nil {
log.Fatalf("failed to fetch robots.txt from URL: %v", err)
}
defer resp.Body.Close()
input = resp.Body
} else {
file, err := os.Open(*inputFile)
if err != nil {
log.Fatalf("failed to open input file: %v", err)
}
defer file.Close()
input = file
}
// Parse robots.txt
rules, err := parseRobotsTxt(input)
if err != nil {
log.Fatalf("failed to parse robots.txt: %v", err)
}
// Convert to Anubis rules
anubisRules := convertToAnubisRules(rules)
// Check if any rules were generated
if len(anubisRules) == 0 {
log.Fatal("no valid rules generated from robots.txt - file may be empty or contain no disallow directives")
}
// Generate output
var output []byte
switch strings.ToLower(*outputFormat) {
case "yaml":
output, err = yaml.Marshal(anubisRules)
case "json":
output, err = json.MarshalIndent(anubisRules, "", " ")
default:
log.Fatalf("unsupported output format: %s (use yaml or json)", *outputFormat)
}
if err != nil {
log.Fatalf("failed to marshal output: %v", err)
}
// Write output
if *outputFile == "" || *outputFile == "-" {
fmt.Print(string(output))
} else {
err = os.WriteFile(*outputFile, output, 0644)
if err != nil {
log.Fatalf("failed to write output file: %v", err)
}
fmt.Printf("Generated Anubis policy written to %s\n", *outputFile)
}
}
func createRuleFromAccumulated(userAgents, disallows, allows []string, crawlDelay int) RobotsRule {
rule := RobotsRule{
UserAgents: make([]string, len(userAgents)),
Disallows: make([]string, len(disallows)),
Allows: make([]string, len(allows)),
CrawlDelay: crawlDelay,
}
copy(rule.UserAgents, userAgents)
copy(rule.Disallows, disallows)
copy(rule.Allows, allows)
return rule
}
func parseRobotsTxt(input io.Reader) ([]RobotsRule, error) {
scanner := bufio.NewScanner(input)
var rules []RobotsRule
var currentUserAgents []string
var currentDisallows []string
var currentAllows []string
var currentCrawlDelay int
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// Skip empty lines and comments
if line == "" || strings.HasPrefix(line, "#") {
continue
}
// Split on first colon
parts := strings.SplitN(line, ":", 2)
if len(parts) != 2 {
continue
}
directive := strings.TrimSpace(strings.ToLower(parts[0]))
value := strings.TrimSpace(parts[1])
switch directive {
case "user-agent":
// If we have accumulated rules with directives and encounter a new user-agent,
// flush the current rules
if len(currentUserAgents) > 0 && (len(currentDisallows) > 0 || len(currentAllows) > 0 || currentCrawlDelay > 0) {
rule := createRuleFromAccumulated(currentUserAgents, currentDisallows, currentAllows, currentCrawlDelay)
rules = append(rules, rule)
// Reset for next group
currentUserAgents = nil
currentDisallows = nil
currentAllows = nil
currentCrawlDelay = 0
}
currentUserAgents = append(currentUserAgents, value)
case "disallow":
if len(currentUserAgents) > 0 && value != "" {
currentDisallows = append(currentDisallows, value)
}
case "allow":
if len(currentUserAgents) > 0 && value != "" {
currentAllows = append(currentAllows, value)
}
case "crawl-delay":
if len(currentUserAgents) > 0 {
if delay, err := parseIntSafe(value); err == nil {
currentCrawlDelay = delay
}
}
}
}
// Don't forget the last group of rules
if len(currentUserAgents) > 0 {
rule := createRuleFromAccumulated(currentUserAgents, currentDisallows, currentAllows, currentCrawlDelay)
rules = append(rules, rule)
}
// Mark blacklisted user agents (those with "Disallow: /")
for i := range rules {
for _, disallow := range rules[i].Disallows {
if disallow == "/" {
rules[i].IsBlacklist = true
break
}
}
}
return rules, scanner.Err()
}
func parseIntSafe(s string) (int, error) {
var result int
_, err := fmt.Sscanf(s, "%d", &result)
return result, err
}
func convertToAnubisRules(robotsRules []RobotsRule) []AnubisRule {
var anubisRules []AnubisRule
ruleCounter := 0
// Process each robots rule individually
for _, robotsRule := range robotsRules {
userAgents := robotsRule.UserAgents
// Handle crawl delay
if robotsRule.CrawlDelay > 0 && *crawlDelay > 0 {
ruleCounter++
rule := AnubisRule{
Name: fmt.Sprintf("%s-crawl-delay-%d", *policyName, ruleCounter),
Action: "WEIGH",
Weight: &config.Weight{Adjust: *crawlDelay},
}
if len(userAgents) == 1 && userAgents[0] == "*" {
rule.Expression = &config.ExpressionOrList{
All: []string{"true"}, // Always applies
}
} else if len(userAgents) == 1 {
rule.Expression = &config.ExpressionOrList{
All: []string{fmt.Sprintf("userAgent.contains(%q)", userAgents[0])},
}
} else {
// Multiple user agents - use any block
var expressions []string
for _, ua := range userAgents {
if ua == "*" {
expressions = append(expressions, "true")
} else {
expressions = append(expressions, fmt.Sprintf("userAgent.contains(%q)", ua))
}
}
rule.Expression = &config.ExpressionOrList{
Any: expressions,
}
}
anubisRules = append(anubisRules, rule)
}
// Handle blacklisted user agents
if robotsRule.IsBlacklist {
ruleCounter++
rule := AnubisRule{
Name: fmt.Sprintf("%s-blacklist-%d", *policyName, ruleCounter),
Action: *userAgentDeny,
}
if len(userAgents) == 1 {
userAgent := userAgents[0]
if userAgent == "*" {
// This would block everything - convert to a weight adjustment instead
rule.Name = fmt.Sprintf("%s-global-restriction-%d", *policyName, ruleCounter)
rule.Action = "WEIGH"
rule.Weight = &config.Weight{Adjust: 20} // Increase difficulty significantly
rule.Expression = &config.ExpressionOrList{
All: []string{"true"}, // Always applies
}
} else {
rule.Expression = &config.ExpressionOrList{
All: []string{fmt.Sprintf("userAgent.contains(%q)", userAgent)},
}
}
} else {
// Multiple user agents - use any block
var expressions []string
for _, ua := range userAgents {
if ua == "*" {
expressions = append(expressions, "true")
} else {
expressions = append(expressions, fmt.Sprintf("userAgent.contains(%q)", ua))
}
}
rule.Expression = &config.ExpressionOrList{
Any: expressions,
}
}
anubisRules = append(anubisRules, rule)
}
// Handle specific disallow rules
for _, disallow := range robotsRule.Disallows {
if disallow == "/" {
continue // Already handled as blacklist above
}
ruleCounter++
rule := AnubisRule{
Name: fmt.Sprintf("%s-disallow-%d", *policyName, ruleCounter),
Action: *baseAction,
}
// Build CEL expression
var conditions []string
// Add user agent conditions
if len(userAgents) == 1 && userAgents[0] == "*" {
// Wildcard user agent - no user agent condition needed
} else if len(userAgents) == 1 {
conditions = append(conditions, fmt.Sprintf("userAgent.contains(%q)", userAgents[0]))
} else {
// For multiple user agents, we need to use a more complex expression
// This is a limitation - we can't easily combine any for user agents with all for path
// So we'll create separate rules for each user agent
for _, ua := range userAgents {
if ua == "*" {
continue // Skip wildcard as it's handled separately
}
ruleCounter++
subRule := AnubisRule{
Name: fmt.Sprintf("%s-disallow-%d", *policyName, ruleCounter),
Action: *baseAction,
Expression: &config.ExpressionOrList{
All: []string{
fmt.Sprintf("userAgent.contains(%q)", ua),
buildPathCondition(disallow),
},
},
}
anubisRules = append(anubisRules, subRule)
}
continue
}
// Add path condition
pathCondition := buildPathCondition(disallow)
conditions = append(conditions, pathCondition)
rule.Expression = &config.ExpressionOrList{
All: conditions,
}
anubisRules = append(anubisRules, rule)
}
}
return anubisRules
}
func buildPathCondition(robotsPath string) string {
// Handle wildcards in robots.txt paths
if strings.Contains(robotsPath, "*") || strings.Contains(robotsPath, "?") {
// Convert robots.txt wildcards to regex
regex := regexp.QuoteMeta(robotsPath)
regex = strings.ReplaceAll(regex, `\*`, `.*`) // * becomes .*
regex = strings.ReplaceAll(regex, `\?`, `.`) // ? becomes .
regex = "^" + regex
return fmt.Sprintf("path.matches(%q)", regex)
}
// Simple prefix match for most cases
return fmt.Sprintf("path.startsWith(%q)", robotsPath)
}

View File

@@ -0,0 +1,424 @@
package main
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"gopkg.in/yaml.v3"
)
type TestCase struct {
name string
robotsFile string
expectedFile string
options TestOptions
}
type TestOptions struct {
format string
action string
policyName string
deniedAction string
crawlDelayWeight int
}
func TestDataFileConversion(t *testing.T) {
testCases := []TestCase{
{
name: "simple_default",
robotsFile: "simple.robots.txt",
expectedFile: "simple.yaml",
options: TestOptions{format: "yaml"},
},
{
name: "simple_json",
robotsFile: "simple.robots.txt",
expectedFile: "simple.json",
options: TestOptions{format: "json"},
},
{
name: "simple_deny_action",
robotsFile: "simple.robots.txt",
expectedFile: "deny-action.yaml",
options: TestOptions{format: "yaml", action: "DENY"},
},
{
name: "simple_custom_name",
robotsFile: "simple.robots.txt",
expectedFile: "custom-name.yaml",
options: TestOptions{format: "yaml", policyName: "my-custom-policy"},
},
{
name: "blacklist_with_crawl_delay",
robotsFile: "blacklist.robots.txt",
expectedFile: "blacklist.yaml",
options: TestOptions{format: "yaml", crawlDelayWeight: 3},
},
{
name: "wildcards",
robotsFile: "wildcards.robots.txt",
expectedFile: "wildcards.yaml",
options: TestOptions{format: "yaml"},
},
{
name: "empty_file",
robotsFile: "empty.robots.txt",
expectedFile: "empty.yaml",
options: TestOptions{format: "yaml"},
},
{
name: "complex_scenario",
robotsFile: "complex.robots.txt",
expectedFile: "complex.yaml",
options: TestOptions{format: "yaml", crawlDelayWeight: 5},
},
{
name: "consecutive_user_agents",
robotsFile: "consecutive.robots.txt",
expectedFile: "consecutive.yaml",
options: TestOptions{format: "yaml", crawlDelayWeight: 3},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
robotsPath := filepath.Join("testdata", tc.robotsFile)
expectedPath := filepath.Join("testdata", tc.expectedFile)
// Read robots.txt input
robotsFile, err := os.Open(robotsPath)
if err != nil {
t.Fatalf("Failed to open robots file %s: %v", robotsPath, err)
}
defer robotsFile.Close()
// Parse robots.txt
rules, err := parseRobotsTxt(robotsFile)
if err != nil {
t.Fatalf("Failed to parse robots.txt: %v", err)
}
// Set test options
oldFormat := *outputFormat
oldAction := *baseAction
oldCrawlDelay := *crawlDelay
oldPolicyName := *policyName
oldDeniedAction := *userAgentDeny
if tc.options.format != "" {
*outputFormat = tc.options.format
}
if tc.options.action != "" {
*baseAction = tc.options.action
}
if tc.options.crawlDelayWeight > 0 {
*crawlDelay = tc.options.crawlDelayWeight
}
if tc.options.policyName != "" {
*policyName = tc.options.policyName
}
if tc.options.deniedAction != "" {
*userAgentDeny = tc.options.deniedAction
}
// Restore options after test
defer func() {
*outputFormat = oldFormat
*baseAction = oldAction
*crawlDelay = oldCrawlDelay
*policyName = oldPolicyName
*userAgentDeny = oldDeniedAction
}()
// Convert to Anubis rules
anubisRules := convertToAnubisRules(rules)
// Generate output
var actualOutput []byte
switch strings.ToLower(*outputFormat) {
case "yaml":
actualOutput, err = yaml.Marshal(anubisRules)
case "json":
actualOutput, err = json.MarshalIndent(anubisRules, "", " ")
}
if err != nil {
t.Fatalf("Failed to marshal output: %v", err)
}
// Read expected output
expectedOutput, err := os.ReadFile(expectedPath)
if err != nil {
t.Fatalf("Failed to read expected file %s: %v", expectedPath, err)
}
if strings.ToLower(*outputFormat) == "yaml" {
var actualData []interface{}
var expectedData []interface{}
err = yaml.Unmarshal(actualOutput, &actualData)
if err != nil {
t.Fatalf("Failed to unmarshal actual output: %v", err)
}
err = yaml.Unmarshal(expectedOutput, &expectedData)
if err != nil {
t.Fatalf("Failed to unmarshal expected output: %v", err)
}
// Compare data structures
if !compareData(actualData, expectedData) {
actualStr := strings.TrimSpace(string(actualOutput))
expectedStr := strings.TrimSpace(string(expectedOutput))
t.Errorf("Output mismatch for %s\nExpected:\n%s\n\nActual:\n%s", tc.name, expectedStr, actualStr)
}
} else {
var actualData []interface{}
var expectedData []interface{}
err = json.Unmarshal(actualOutput, &actualData)
if err != nil {
t.Fatalf("Failed to unmarshal actual JSON output: %v", err)
}
err = json.Unmarshal(expectedOutput, &expectedData)
if err != nil {
t.Fatalf("Failed to unmarshal expected JSON output: %v", err)
}
// Compare data structures
if !compareData(actualData, expectedData) {
actualStr := strings.TrimSpace(string(actualOutput))
expectedStr := strings.TrimSpace(string(expectedOutput))
t.Errorf("Output mismatch for %s\nExpected:\n%s\n\nActual:\n%s", tc.name, expectedStr, actualStr)
}
}
})
}
}
func TestCaseInsensitiveParsing(t *testing.T) {
robotsTxt := `User-Agent: *
Disallow: /admin
Crawl-Delay: 10
User-agent: TestBot
disallow: /test
crawl-delay: 5
USER-AGENT: UpperBot
DISALLOW: /upper
CRAWL-DELAY: 20`
reader := strings.NewReader(robotsTxt)
rules, err := parseRobotsTxt(reader)
if err != nil {
t.Fatalf("Failed to parse case-insensitive robots.txt: %v", err)
}
expectedRules := 3
if len(rules) != expectedRules {
t.Errorf("Expected %d rules, got %d", expectedRules, len(rules))
}
// Check that all crawl delays were parsed
for i, rule := range rules {
expectedDelays := []int{10, 5, 20}
if rule.CrawlDelay != expectedDelays[i] {
t.Errorf("Rule %d: expected crawl delay %d, got %d", i, expectedDelays[i], rule.CrawlDelay)
}
}
}
func TestVariousOutputFormats(t *testing.T) {
robotsTxt := `User-agent: *
Disallow: /admin`
reader := strings.NewReader(robotsTxt)
rules, err := parseRobotsTxt(reader)
if err != nil {
t.Fatalf("Failed to parse robots.txt: %v", err)
}
oldPolicyName := *policyName
*policyName = "test-policy"
defer func() { *policyName = oldPolicyName }()
anubisRules := convertToAnubisRules(rules)
// Test YAML output
yamlOutput, err := yaml.Marshal(anubisRules)
if err != nil {
t.Fatalf("Failed to marshal YAML: %v", err)
}
if !strings.Contains(string(yamlOutput), "name: test-policy-disallow-1") {
t.Errorf("YAML output doesn't contain expected rule name")
}
// Test JSON output
jsonOutput, err := json.MarshalIndent(anubisRules, "", " ")
if err != nil {
t.Fatalf("Failed to marshal JSON: %v", err)
}
if !strings.Contains(string(jsonOutput), `"name": "test-policy-disallow-1"`) {
t.Errorf("JSON output doesn't contain expected rule name")
}
}
func TestDifferentActions(t *testing.T) {
robotsTxt := `User-agent: *
Disallow: /admin`
testActions := []string{"ALLOW", "DENY", "CHALLENGE", "WEIGH"}
for _, action := range testActions {
t.Run("action_"+action, func(t *testing.T) {
reader := strings.NewReader(robotsTxt)
rules, err := parseRobotsTxt(reader)
if err != nil {
t.Fatalf("Failed to parse robots.txt: %v", err)
}
oldAction := *baseAction
*baseAction = action
defer func() { *baseAction = oldAction }()
anubisRules := convertToAnubisRules(rules)
if len(anubisRules) != 1 {
t.Fatalf("Expected 1 rule, got %d", len(anubisRules))
}
if anubisRules[0].Action != action {
t.Errorf("Expected action %s, got %s", action, anubisRules[0].Action)
}
})
}
}
func TestPolicyNaming(t *testing.T) {
robotsTxt := `User-agent: *
Disallow: /admin
Disallow: /private
User-agent: BadBot
Disallow: /`
testNames := []string{"custom-policy", "my-rules", "site-protection"}
for _, name := range testNames {
t.Run("name_"+name, func(t *testing.T) {
reader := strings.NewReader(robotsTxt)
rules, err := parseRobotsTxt(reader)
if err != nil {
t.Fatalf("Failed to parse robots.txt: %v", err)
}
oldName := *policyName
*policyName = name
defer func() { *policyName = oldName }()
anubisRules := convertToAnubisRules(rules)
// Check that all rule names use the custom prefix
for _, rule := range anubisRules {
if !strings.HasPrefix(rule.Name, name+"-") {
t.Errorf("Rule name %s doesn't start with expected prefix %s-", rule.Name, name)
}
}
})
}
}
func TestCrawlDelayWeights(t *testing.T) {
robotsTxt := `User-agent: *
Disallow: /admin
Crawl-delay: 10
User-agent: SlowBot
Disallow: /slow
Crawl-delay: 60`
testWeights := []int{1, 5, 10, 25}
for _, weight := range testWeights {
t.Run(fmt.Sprintf("weight_%d", weight), func(t *testing.T) {
reader := strings.NewReader(robotsTxt)
rules, err := parseRobotsTxt(reader)
if err != nil {
t.Fatalf("Failed to parse robots.txt: %v", err)
}
oldWeight := *crawlDelay
*crawlDelay = weight
defer func() { *crawlDelay = oldWeight }()
anubisRules := convertToAnubisRules(rules)
// Count weight rules and verify they have correct weight
weightRules := 0
for _, rule := range anubisRules {
if rule.Action == "WEIGH" && rule.Weight != nil {
weightRules++
if rule.Weight.Adjust != weight {
t.Errorf("Expected weight %d, got %d", weight, rule.Weight.Adjust)
}
}
}
expectedWeightRules := 2 // One for *, one for SlowBot
if weightRules != expectedWeightRules {
t.Errorf("Expected %d weight rules, got %d", expectedWeightRules, weightRules)
}
})
}
}
func TestBlacklistActions(t *testing.T) {
robotsTxt := `User-agent: BadBot
Disallow: /
User-agent: SpamBot
Disallow: /`
testActions := []string{"DENY", "CHALLENGE"}
for _, action := range testActions {
t.Run("blacklist_"+action, func(t *testing.T) {
reader := strings.NewReader(robotsTxt)
rules, err := parseRobotsTxt(reader)
if err != nil {
t.Fatalf("Failed to parse robots.txt: %v", err)
}
oldAction := *userAgentDeny
*userAgentDeny = action
defer func() { *userAgentDeny = oldAction }()
anubisRules := convertToAnubisRules(rules)
// All rules should be blacklist rules with the specified action
for _, rule := range anubisRules {
if !strings.Contains(rule.Name, "blacklist") {
t.Errorf("Expected blacklist rule, got %s", rule.Name)
}
if rule.Action != action {
t.Errorf("Expected action %s, got %s", action, rule.Action)
}
}
})
}
}
// compareData performs a deep comparison of two data structures,
// ignoring differences that are semantically equivalent in YAML/JSON
func compareData(actual, expected interface{}) bool {
return reflect.DeepEqual(actual, expected)
}

View File

@@ -0,0 +1,15 @@
# Test with blacklisted user agents
User-agent: *
Disallow: /admin
Crawl-delay: 10
User-agent: BadBot
Disallow: /
User-agent: SpamBot
Disallow: /
Crawl-delay: 60
User-agent: Googlebot
Disallow: /search
Crawl-delay: 5

View File

@@ -0,0 +1,30 @@
- action: WEIGH
expression: "true"
name: robots-txt-policy-crawl-delay-1
weight:
adjust: 3
- action: CHALLENGE
expression: path.startsWith("/admin")
name: robots-txt-policy-disallow-2
- action: DENY
expression: userAgent.contains("BadBot")
name: robots-txt-policy-blacklist-3
- action: WEIGH
expression: userAgent.contains("SpamBot")
name: robots-txt-policy-crawl-delay-4
weight:
adjust: 3
- action: DENY
expression: userAgent.contains("SpamBot")
name: robots-txt-policy-blacklist-5
- action: WEIGH
expression: userAgent.contains("Googlebot")
name: robots-txt-policy-crawl-delay-6
weight:
adjust: 3
- action: CHALLENGE
expression:
all:
- userAgent.contains("Googlebot")
- path.startsWith("/search")
name: robots-txt-policy-disallow-7

View File

@@ -0,0 +1,30 @@
# Complex real-world example
User-agent: *
Disallow: /admin/
Disallow: /private/
Disallow: /api/internal/
Allow: /api/public/
Crawl-delay: 5
User-agent: Googlebot
Disallow: /search/
Allow: /api/
Crawl-delay: 2
User-agent: Bingbot
Disallow: /search/
Disallow: /admin/
Crawl-delay: 10
User-agent: BadBot
Disallow: /
User-agent: SeoBot
Disallow: /
Crawl-delay: 300
# Test with various patterns
User-agent: TestBot
Disallow: /*/admin
Disallow: /temp*.html
Disallow: /file?.log

71
cmd/robots2policy/testdata/complex.yaml vendored Normal file
View File

@@ -0,0 +1,71 @@
- action: WEIGH
expression: "true"
name: robots-txt-policy-crawl-delay-1
weight:
adjust: 5
- action: CHALLENGE
expression: path.startsWith("/admin/")
name: robots-txt-policy-disallow-2
- action: CHALLENGE
expression: path.startsWith("/private/")
name: robots-txt-policy-disallow-3
- action: CHALLENGE
expression: path.startsWith("/api/internal/")
name: robots-txt-policy-disallow-4
- action: WEIGH
expression: userAgent.contains("Googlebot")
name: robots-txt-policy-crawl-delay-5
weight:
adjust: 5
- action: CHALLENGE
expression:
all:
- userAgent.contains("Googlebot")
- path.startsWith("/search/")
name: robots-txt-policy-disallow-6
- action: WEIGH
expression: userAgent.contains("Bingbot")
name: robots-txt-policy-crawl-delay-7
weight:
adjust: 5
- action: CHALLENGE
expression:
all:
- userAgent.contains("Bingbot")
- path.startsWith("/search/")
name: robots-txt-policy-disallow-8
- action: CHALLENGE
expression:
all:
- userAgent.contains("Bingbot")
- path.startsWith("/admin/")
name: robots-txt-policy-disallow-9
- action: DENY
expression: userAgent.contains("BadBot")
name: robots-txt-policy-blacklist-10
- action: WEIGH
expression: userAgent.contains("SeoBot")
name: robots-txt-policy-crawl-delay-11
weight:
adjust: 5
- action: DENY
expression: userAgent.contains("SeoBot")
name: robots-txt-policy-blacklist-12
- action: CHALLENGE
expression:
all:
- userAgent.contains("TestBot")
- path.matches("^/.*/admin")
name: robots-txt-policy-disallow-13
- action: CHALLENGE
expression:
all:
- userAgent.contains("TestBot")
- path.matches("^/temp.*\\.html")
name: robots-txt-policy-disallow-14
- action: CHALLENGE
expression:
all:
- userAgent.contains("TestBot")
- path.matches("^/file.\\.log")
name: robots-txt-policy-disallow-15

View File

@@ -0,0 +1,25 @@
# Test consecutive user agents that should be grouped into any: blocks
User-agent: *
Disallow: /admin
Crawl-delay: 10
# Multiple consecutive user agents - should be grouped
User-agent: BadBot
User-agent: SpamBot
User-agent: EvilBot
Disallow: /
# Single user agent - should be separate
User-agent: GoodBot
Disallow: /private
# Multiple consecutive user agents with crawl delay
User-agent: SlowBot1
User-agent: SlowBot2
Crawl-delay: 5
# Multiple consecutive user agents with specific path
User-agent: SearchBot1
User-agent: SearchBot2
User-agent: SearchBot3
Disallow: /search

View File

@@ -0,0 +1,47 @@
- action: WEIGH
expression: "true"
name: robots-txt-policy-crawl-delay-1
weight:
adjust: 3
- action: CHALLENGE
expression: path.startsWith("/admin")
name: robots-txt-policy-disallow-2
- action: DENY
expression:
any:
- userAgent.contains("BadBot")
- userAgent.contains("SpamBot")
- userAgent.contains("EvilBot")
name: robots-txt-policy-blacklist-3
- action: CHALLENGE
expression:
all:
- userAgent.contains("GoodBot")
- path.startsWith("/private")
name: robots-txt-policy-disallow-4
- action: WEIGH
expression:
any:
- userAgent.contains("SlowBot1")
- userAgent.contains("SlowBot2")
name: robots-txt-policy-crawl-delay-5
weight:
adjust: 3
- action: CHALLENGE
expression:
all:
- userAgent.contains("SearchBot1")
- path.startsWith("/search")
name: robots-txt-policy-disallow-7
- action: CHALLENGE
expression:
all:
- userAgent.contains("SearchBot2")
- path.startsWith("/search")
name: robots-txt-policy-disallow-8
- action: CHALLENGE
expression:
all:
- userAgent.contains("SearchBot3")
- path.startsWith("/search")
name: robots-txt-policy-disallow-9

View File

@@ -0,0 +1,6 @@
- action: CHALLENGE
expression: path.startsWith("/admin/")
name: my-custom-policy-disallow-1
- action: CHALLENGE
expression: path.startsWith("/private")
name: my-custom-policy-disallow-2

View File

@@ -0,0 +1,6 @@
- action: DENY
expression: path.startsWith("/admin/")
name: robots-txt-policy-disallow-1
- action: DENY
expression: path.startsWith("/private")
name: robots-txt-policy-disallow-2

View File

@@ -0,0 +1,2 @@
# Empty robots.txt (comments only)
# No actual rules

1
cmd/robots2policy/testdata/empty.yaml vendored Normal file
View File

@@ -0,0 +1 @@
[]

12
cmd/robots2policy/testdata/simple.json vendored Normal file
View File

@@ -0,0 +1,12 @@
[
{
"expression": "path.startsWith(\"/admin/\")",
"name": "robots-txt-policy-disallow-1",
"action": "CHALLENGE"
},
{
"expression": "path.startsWith(\"/private\")",
"name": "robots-txt-policy-disallow-2",
"action": "CHALLENGE"
}
]

View File

@@ -0,0 +1,5 @@
# Simple robots.txt test
User-agent: *
Disallow: /admin/
Disallow: /private
Allow: /public

View File

@@ -0,0 +1,6 @@
- action: CHALLENGE
expression: path.startsWith("/admin/")
name: robots-txt-policy-disallow-1
- action: CHALLENGE
expression: path.startsWith("/private")
name: robots-txt-policy-disallow-2

View File

@@ -0,0 +1,6 @@
# Test wildcard patterns
User-agent: *
Disallow: /search*
Disallow: /*/private
Disallow: /file?.txt
Disallow: /admin/*?action=delete

View File

@@ -0,0 +1,12 @@
- action: CHALLENGE
expression: path.matches("^/search.*")
name: robots-txt-policy-disallow-1
- action: CHALLENGE
expression: path.matches("^/.*/private")
name: robots-txt-policy-disallow-2
- action: CHALLENGE
expression: path.matches("^/file.\\.txt")
name: robots-txt-policy-disallow-3
- action: CHALLENGE
expression: path.matches("^/admin/.*.action=delete")
name: robots-txt-policy-disallow-4

View File

@@ -0,0 +1,6 @@
- name: allow-api-routes
action: ALLOW
expression:
all:
- '!(method == "HEAD" || method == "GET")'
- path.startsWith("/api/")

View File

@@ -0,0 +1,20 @@
# Make SASL login work on bookstack with Anubis
# https://www.bookstackapp.com/docs/admin/saml2-auth/
- name: allow-bookstack-sasl-login-routes
action: ALLOW
expression:
all:
- 'method == "POST"'
- path.startsWith("/saml2/acs")
- name: allow-bookstack-sasl-metadata-routes
action: ALLOW
expression:
all:
- 'method == "GET"'
- path.startsWith("/saml2/metadata")
- name: allow-bookstack-sasl-logout-routes
action: ALLOW
expression:
all:
- 'method == "GET"'
- path.startsWith("/saml2/sls")

View File

@@ -0,0 +1,7 @@
# This policy allows Qualys SSL Labs to fully work. (https://www.ssllabs.com/ssltest)
# IP ranges are taken from: https://qualys.my.site.com/discussions/s/article/000005823
- name: qualys-ssl-labs
action: ALLOW
remote_addresses:
- 64.41.200.0/24
- 2600:C02:1020:4202::/64

View File

@@ -0,0 +1,9 @@
# This policy allows SearXNG's instance tracker to work. (https://searx.space)
# IPs are taken from `check.searx.space` DNS records.
# https://toolbox.googleapps.com/apps/dig/#A/check.searx.space
# https://toolbox.googleapps.com/apps/dig/#AAAA/check.searx.space
- name: searx-checker
action: ALLOW
remote_addresses:
- 167.235.158.251/32
- 2a01:4f8:1c1c:8fc2::1/128

View File

@@ -1,49 +0,0 @@
{
"bots": [
{
"import": "(data)/bots/ai-robots-txt.yaml"
},
{
"import": "(data)/bots/cloudflare-workers.yaml"
},
{
"import": "(data)/bots/headless-browsers.yaml"
},
{
"import": "(data)/bots/us-ai-scraper.yaml"
},
{
"import": "(data)/crawlers/googlebot.yaml"
},
{
"import": "(data)/crawlers/bingbot.yaml"
},
{
"import": "(data)/crawlers/duckduckbot.yaml"
},
{
"import": "(data)/crawlers/qwantbot.yaml"
},
{
"import": "(data)/crawlers/internet-archive.yaml"
},
{
"import": "(data)/crawlers/kagibot.yaml"
},
{
"import": "(data)/crawlers/marginalia.yaml"
},
{
"import": "(data)/crawlers/mojeekbot.yaml"
},
{
"import": "(data)/common/keep-internet-working.yaml"
},
{
"name": "generic-browser",
"user_agent_regex": "Mozilla|Opera",
"action": "CHALLENGE"
}
],
"dnsbl": false
}

View File

@@ -11,22 +11,35 @@
## /usr/share/docs/anubis/data or in the tarball you extracted Anubis from.
bots:
# Pathological bots to deny
- # This correlates to data/bots/ai-robots-txt.yaml in the source tree
import: (data)/bots/ai-robots-txt.yaml
- import: (data)/bots/cloudflare-workers.yaml
- import: (data)/bots/headless-browsers.yaml
- import: (data)/bots/us-ai-scraper.yaml
# You can import the entire default config with this macro:
# - import: (data)/meta/default-config.yaml
# Search engines to allow
- import: (data)/crawlers/googlebot.yaml
- import: (data)/crawlers/bingbot.yaml
- import: (data)/crawlers/duckduckbot.yaml
- import: (data)/crawlers/qwantbot.yaml
- import: (data)/crawlers/internet-archive.yaml
- import: (data)/crawlers/kagibot.yaml
- import: (data)/crawlers/marginalia.yaml
- import: (data)/crawlers/mojeekbot.yaml
# Pathological bots to deny
- # This correlates to data/bots/_deny-pathological.yaml in the source tree
# https://github.com/TecharoHQ/anubis/blob/main/data/bots/_deny-pathological.yaml
import: (data)/bots/_deny-pathological.yaml
- import: (data)/bots/aggressive-brazilian-scrapers.yaml
# Aggressively block AI/LLM related bots/agents by default
- import: (data)/meta/ai-block-aggressive.yaml
# Consider replacing the aggressive AI policy with more selective policies:
# - import: (data)/meta/ai-block-moderate.yaml
# - import: (data)/meta/ai-block-permissive.yaml
# Search engine crawlers to allow, defaults to:
# - Google (so they don't try to bypass Anubis)
# - Apple
# - Bing
# - DuckDuckGo
# - Qwant
# - The Internet Archive
# - Kagi
# - Marginalia
# - Mojeek
- import: (data)/crawlers/_allow-good.yaml
# Challenge Firefox AI previews
- import: (data)/clients/x-firefox-ai.yaml
# Allow common "keeping the internet working" routes (well-known, favicon, robots.txt)
- import: (data)/common/keep-internet-working.yaml
@@ -38,21 +51,186 @@ bots:
# action: CHALLENGE
# challenge:
# difficulty: 16 # impossible
# report_as: 4 # lie to the operator
# algorithm: slow # intentionally waste CPU cycles and time
# Requires a subscription to Thoth to use, see
# https://anubis.techaro.lol/docs/admin/thoth#geoip-based-filtering
- name: countries-with-aggressive-scrapers
action: WEIGH
geoip:
countries:
- BR
- CN
weight:
adjust: 10
# Requires a subscription to Thoth to use, see
# https://anubis.techaro.lol/docs/admin/thoth#asn-based-filtering
- name: aggressive-asns-without-functional-abuse-contact
action: WEIGH
asns:
match:
- 13335 # Cloudflare
- 136907 # Huawei Cloud
- 45102 # Alibaba Cloud
weight:
adjust: 10
# ## System load based checks.
# # If the system is under high load, 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 your backend service is running on the same operating system as Anubis,
## you can uncomment this rule to make the challenge easier when the system is
## under low load.
##
## If it is not, 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: -10
# Generic catchall rule
- name: generic-browser
user_agent_regex: >-
Mozilla|Opera
action: CHALLENGE
action: WEIGH
weight:
adjust: 10
dnsbl: false
# #
# impressum:
# # Displayed at the bottom of every page rendered by Anubis.
# footer: >-
# This website is hosted by Zombocom. If you have any complaints or notes
# about the service, please contact
# <a href="mailto:contact@domainhere.example">contact@domainhere.example</a>
# and we will assist you as soon as possible.
# # The imprint page that will be linked to at the footer of every Anubis page.
# page:
# # The HTML <title> of the page
# title: Imprint and Privacy Policy
# # The HTML contents of the page. The exact contents of this page can
# # and will vary by locale. Please consult with a lawyer if you are not
# # sure what to put here
# body: >-
# <p>Last updated: June 2025</p>
# <h2>Information that is gathered from visitors</h2>
# <p>In common with other websites, log files are stored on the web server saving details such as the visitor's IP address, browser type, referring page and time of visit.</p>
# <p>Cookies may be used to remember visitor preferences when interacting with the website.</p>
# <p>Where registration is required, the visitor's email and a username will be stored on the server.</p>
# <!-- ... -->
# Open Graph passthrough configuration, see here for more information:
# https://anubis.techaro.lol/docs/admin/configuration/open-graph/
openGraph:
# Enables Open Graph passthrough
enabled: false
# Enables the use of the HTTP host in the cache key, this enables
# caching metadata for multiple http hosts at once.
considerHost: false
# How long cached OpenGraph metadata should last in memory
ttl: 24h
# # If set, return these opengraph values instead of looking them up with
# # the target service.
# #
# # Correlates to properties in https://ogp.me/
# override:
# # og:title is required, it is the title of the website
# "og:title": "Techaro Anubis"
# "og:description": >-
# Anubis is a Web AI Firewall Utility that helps you fight the bots
# away so that you can maintain uptime at work!
# "description": >-
# Anubis is a Web AI Firewall Utility that helps you fight the bots
# away so that you can maintain uptime at work!
# By default, send HTTP 200 back to clients that either get issued a challenge
# or a denial. This seems weird, but this is load-bearing due to the fact that
# the most aggressive scraper bots seem to really really want an HTTP 200 and
# the most aggressive scraper bots seem to really, really, want an HTTP 200 and
# will stop sending requests once they get it.
status_codes:
CHALLENGE: 200
DENY: 200
# Anubis can store temporary data in one of a few backends. See the storage
# backends section of the docs for more information:
#
# https://anubis.techaro.lol/docs/admin/policies#storage-backends
store:
backend: memory
parameters: {}
# The weight thresholds for when to trigger individual challenges. Any
# CHALLENGE will take precedence over this.
#
# A threshold has four configuration options:
#
# - name: the name that is reported down the stack and used for metrics
# - expression: A CEL expression with the request weight in the variable
# weight
# - action: the Anubis action to apply, similar to in a bot policy
# - challenge: which challenge to send to the user, similar to in a bot policy
#
# See https://anubis.techaro.lol/docs/admin/configuration/thresholds for more
# information.
thresholds:
# By default Anubis ships with the following thresholds:
- name: minimal-suspicion # This client is likely fine, its soul is lighter than a feather
expression: weight <= 0 # a feather weighs zero units
action: ALLOW # Allow the traffic through
# For clients that had some weight reduced through custom rules, give them a
# lightweight challenge.
- name: mild-suspicion
expression:
all:
- weight > 0
- weight < 10
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh
algorithm: metarefresh
difficulty: 1
# For clients that are browser-like but have either gained points from custom rules or
# report as a standard browser.
- name: moderate-suspicion
expression:
all:
- weight >= 10
- weight < 20
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 2 # two leading zeros, very fast for most clients
- name: mild-proof-of-work
expression:
all:
- weight >= 20
- weight < 30
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 4
# For clients that are browser like and have gained many points from custom rules
- name: extreme-suspicion
expression: weight >= 30
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 6

View File

@@ -0,0 +1,6 @@
- import: (data)/bots/cloudflare-workers.yaml
- import: (data)/bots/headless-browsers.yaml
- import: (data)/bots/us-ai-scraper.yaml
- import: (data)/bots/custom-async-http-client.yaml
- import: (data)/crawlers/alibaba-cloud.yaml
- import: (data)/crawlers/huawei-cloud.yaml

View File

@@ -0,0 +1,26 @@
- name: deny-aggressive-brazilian-scrapers
action: WEIGH
weight:
adjust: 20
expression:
any:
# Internet Explorer should be out of support
- userAgent.contains("MSIE")
# Trident is the Internet Explorer browser engine
- userAgent.contains("Trident")
# Opera is a fork of chrome now
- userAgent.contains("Presto")
# Windows CE is discontinued
- userAgent.contains("Windows CE")
# Windows 95 is discontinued
- userAgent.contains("Windows 95")
# Windows 98 is discontinued
- userAgent.contains("Windows 98")
# Windows 9.x is discontinued
- userAgent.contains("Win 9x")
# Amazon does not have an Alexa Toolbar.
- userAgent.contains("Alexa Toolbar")
# This is not released, even Windows 11 calls itself Windows 10
- userAgent.contains("Windows NT 11.0")
# iPods are not in common use
- userAgent.contains("iPod")

View File

@@ -0,0 +1,11 @@
# Extensive list of AI-affiliated agents based on https://github.com/ai-robots-txt/ai.robots.txt
# Add new/undocumented agents here. Where documentation exists, consider moving to dedicated policy files.
# Notes on various agents:
# - Amazonbot: Well documented, but they refuse to state which agent collects training data.
# - anthropic-ai/Claude-Web: Undocumented by Anthropic. Possibly deprecated or hallucinations?
# - Perplexity*: Well documented, but they refuse to state which agent collects training data.
# Warning: May contain user agents that _must_ be blocked in robots.txt, or the opt-out will have no effect.
- name: "ai-catchall"
user_agent_regex: >-
AI2Bot|Ai2Bot-Dolma|aiHitBot|Amazonbot|anthropic-ai|Brightbot 1.0|Bytespider|Claude-Web|cohere-ai|cohere-training-data-crawler|Cotoyogi|Crawlspace|Diffbot|DuckAssistBot|FacebookBot|Factset_spyderbot|FirecrawlAgent|FriendlyCrawler|Google-CloudVertexBot|GoogleOther|GoogleOther-Image|GoogleOther-Video|iaskspider/2.0|ICC-Crawler|ImagesiftBot|img2dataset|imgproxy|ISSCyberRiskCrawler|Kangaroo Bot|meta-externalagent|Meta-ExternalAgent|meta-externalfetcher|Meta-ExternalFetcher|NovaAct|omgili|omgilibot|Operator|PanguBot|Perplexity-User|PerplexityBot|PetalBot|QualifiedBot|Scrapy|SemrushBot-OCOB|SemrushBot-SWA|Sidetrade indexer bot|TikTokSpider|Timpibot|VelenPublicWebCrawler|Webzio-Extended|wpbot|YouBot
action: DENY

View File

@@ -1,4 +1,8 @@
# Warning: Contains user agents that _must_ be blocked in robots.txt, or the opt-out will have no effect.
# Note: Blocks human-directed/non-training user agents
#
# CCBot is allowed because if Common Crawl is allowed, then scrapers don't need to scrape to get the data.
- name: "ai-robots-txt"
user_agent_regex: >-
AI2Bot|Ai2Bot-Dolma|aiHitBot|Amazonbot|anthropic-ai|Applebot|Applebot-Extended|Brightbot 1.0|Bytespider|CCBot|ChatGPT-User|Claude-Web|ClaudeBot|cohere-ai|cohere-training-data-crawler|Cotoyogi|Crawlspace|Diffbot|DuckAssistBot|FacebookBot|Factset_spyderbot|FirecrawlAgent|FriendlyCrawler|Google-Extended|GoogleOther|GoogleOther-Image|GoogleOther-Video|GPTBot|iaskspider/2.0|ICC-Crawler|ImagesiftBot|img2dataset|imgproxy|ISSCyberRiskCrawler|Kangaroo Bot|meta-externalagent|Meta-ExternalAgent|meta-externalfetcher|Meta-ExternalFetcher|NovaAct|OAI-SearchBot|omgili|omgilibot|Operator|PanguBot|Perplexity-User|PerplexityBot|PetalBot|Scrapy|SemrushBot-OCOB|SemrushBot-SWA|Sidetrade indexer bot|TikTokSpider|Timpibot|VelenPublicWebCrawler|Webzio-Extended|YouBot
AddSearchBot|AI2Bot|Ai2Bot-Dolma|aiHitBot|Amazonbot|Andibot|anthropic-ai|Applebot|Applebot-Extended|Awario|bedrockbot|bigsur.ai|Brightbot 1.0|Bytespider|CCBot|ChatGPT Agent|ChatGPT-User|Claude-SearchBot|Claude-User|Claude-Web|ClaudeBot|CloudVertexBot|cohere-ai|cohere-training-data-crawler|Cotoyogi|Crawlspace|Datenbank Crawler|Devin|Diffbot|DuckAssistBot|Echobot Bot|EchoboxBot|FacebookBot|facebookexternalhit|Factset_spyderbot|FirecrawlAgent|FriendlyCrawler|Gemini-Deep-Research|Google-CloudVertexBot|Google-Extended|GoogleAgent-Mariner|GoogleOther|GoogleOther-Image|GoogleOther-Video|GPTBot|iaskspider/2.0|ICC-Crawler|ImagesiftBot|img2dataset|ISSCyberRiskCrawler|Kangaroo Bot|LinerBot|meta-externalagent|Meta-ExternalAgent|meta-externalfetcher|Meta-ExternalFetcher|MistralAI-User|MistralAI-User/1.0|MyCentralAIScraperBot|netEstate Imprint Crawler|NovaAct|OAI-SearchBot|omgili|omgilibot|OpenAI|Operator|PanguBot|Panscient|panscient.com|Perplexity-User|PerplexityBot|PetalBot|PhindBot|Poseidon Research Crawler|QualifiedBot|QuillBot|quillbot.com|SBIntuitionsBot|Scrapy|SemrushBot-OCOB|SemrushBot-SWA|Sidetrade indexer bot|Thinkbot|TikTokSpider|Timpibot|VelenPublicWebCrawler|WARDBot|Webzio-Extended|wpbot|YaK|YandexAdditional|YandexAdditionalBot|YouBot
action: DENY

View File

@@ -1,4 +1,6 @@
- name: cloudflare-workers
headers_regex:
CF-Worker: .*
action: DENY
action: WEIGH
weight:
adjust: 15

View File

@@ -0,0 +1,5 @@
- name: "custom-async-http-client"
user_agent_regex: "Custom-AsyncHttpClient"
action: WEIGH
weight:
adjust: 10

View File

@@ -0,0 +1,9 @@
# phrik in the Arch Linux IRC channels
- name: archlinux-phrik
action: ALLOW
expression:
all:
- remoteAddress == "159.69.213.214" || remoteAddress == "2a01:4f8:c2c:7bf4::1"
- userAgent == "Mozilla/5.0 (compatible; utils.web Limnoria module)"
- '"X-Http-Version" in headers'
- headers["X-Http-Version"] == "HTTP/1.1"

View File

@@ -0,0 +1,9 @@
# chat in the gentoo IRC channels
- name: gentoo-chat
action: ALLOW
expression:
all:
- remoteAddress == "45.76.166.57"
- userAgent == "Mozilla/5.0 (Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0"
- '"X-Http-Version" in headers'
- headers["X-Http-Version"] == "HTTP/1.1"

8
data/clients/ai.yaml Normal file
View File

@@ -0,0 +1,8 @@
# User agents that act on behalf of humans in AI tools, e.g. searching the web.
# Each entry should have a positive/ALLOW entry created as well, with further documentation.
# Exceptions:
# - Claude-User: No published IP allowlist
- name: "ai-clients"
user_agent_regex: >-
ChatGPT-User|Claude-User|MistralAI-User
action: DENY

View File

@@ -0,0 +1,60 @@
- name: allow-docker-client
action: ALLOW
expression:
all:
- path.startsWith("/v2/")
- userAgent.contains("docker/")
- userAgent.contains("git-commit/")
- '"Accept" in headers'
- headers["Accept"].contains("vnd.docker.distribution")
- '"Baggage" in headers'
- headers["Baggage"].contains("trigger")
- name: allow-crane-client
action: ALLOW
expression:
all:
- userAgent.contains("crane/")
- userAgent.contains("go-containerregistry/")
- name: allow-docker-distribution-api-client
action: ALLOW
expression:
all:
- '"Docker-Distribution-Api-Version" in headers'
- '!(userAgent.contains("Mozilla"))'
- name: allow-go-containerregistry-client
action: ALLOW
expression:
all:
- path.startsWith("/v2/")
- userAgent.contains("go-containerregistry/")
- name: allow-buildah
action: ALLOW
expression:
all:
- path.startsWith("/v2/")
- userAgent.contains("Buildah/")
- name: allow-podman
action: ALLOW
expression:
all:
- path.startsWith("/v2/")
- userAgent.contains("containers/")
- name: allow-containerd
action: ALLOW
expression:
all:
- path.startsWith("/v2/")
- userAgent.contains("containerd/")
- name: allow-renovate
action: ALLOW
expression:
all:
- path.startsWith("/v2/")
- userAgent.contains("Renovate/")

20
data/clients/git.yaml Normal file
View File

@@ -0,0 +1,20 @@
- name: allow-git-clients
action: ALLOW
expression:
all:
- >
(
userAgent.startsWith("git/") ||
userAgent.contains("libgit") ||
userAgent.startsWith("go-git") ||
userAgent.startsWith("JGit/") ||
userAgent.startsWith("JGit-")
)
- '"Accept" in headers'
- headers["Accept"] == "*/*"
- '"Cache-Control" in headers'
- headers["Cache-Control"] == "no-cache"
- '"Pragma" in headers'
- headers["Pragma"] == "no-cache"
- '"Accept-Encoding" in headers'
- headers["Accept-Encoding"].contains("gzip")

7
data/clients/go-get.yaml Normal file
View File

@@ -0,0 +1,7 @@
- name: go-get
action: ALLOW
expression:
all:
- userAgent.startsWith("Go-http-client/")
- '"go-get" in query'
- query["go-get"] == "1"

View File

@@ -0,0 +1,10 @@
# Acts on behalf of user requests
# https://docs.mistral.ai/robots/
- name: mistral-mistralai-user
user_agent_regex: MistralAI-User/.+; \+https\://docs\.mistral\.ai/robots
action: ALLOW
# https://mistral.ai/mistralai-user-ips.json
remote_addresses: [
"20.240.160.161/32",
"20.240.160.1/32",
]

View File

@@ -0,0 +1,93 @@
# Acts on behalf of user requests
# https://platform.openai.com/docs/bots/overview-of-openai-crawlers
- name: openai-chatgpt-user
user_agent_regex: ChatGPT-User/.+; \+https\://openai\.com/bot
action: ALLOW
# https://openai.com/chatgpt-user.json
# curl 'https://openai.com/chatgpt-user.json' | jq '.prefixes.[].ipv4Prefix' | sed 's/$/,/'
remote_addresses: [
"13.65.138.112/28",
"23.98.179.16/28",
"13.65.138.96/28",
"172.183.222.128/28",
"20.102.212.144/28",
"40.116.73.208/28",
"172.183.143.224/28",
"52.190.190.16/28",
"13.83.237.176/28",
"51.8.155.64/28",
"74.249.86.176/28",
"51.8.155.48/28",
"20.55.229.144/28",
"135.237.131.208/28",
"135.237.133.48/28",
"51.8.155.112/28",
"135.237.133.112/28",
"52.159.249.96/28",
"52.190.137.16/28",
"52.255.111.112/28",
"40.84.181.32/28",
"172.178.141.112/28",
"52.190.142.64/28",
"172.178.140.144/28",
"52.190.137.144/28",
"172.178.141.128/28",
"57.154.187.32/28",
"4.196.118.112/28",
"20.193.50.32/28",
"20.215.188.192/28",
"20.215.214.16/28",
"4.197.22.112/28",
"4.197.115.112/28",
"172.213.21.16/28",
"172.213.11.144/28",
"172.213.12.112/28",
"172.213.21.144/28",
"20.90.7.144/28",
"57.154.175.0/28",
"57.154.174.112/28",
"52.236.94.144/28",
"137.135.191.176/28",
"23.98.186.192/28",
"23.98.186.96/28",
"23.98.186.176/28",
"23.98.186.64/28",
"68.221.67.192/28",
"68.221.67.160/28",
"13.83.167.128/28",
"20.228.106.176/28",
"52.159.227.32/28",
"68.220.57.64/28",
"172.213.21.112/28",
"68.221.67.224/28",
"68.221.75.16/28",
"20.97.189.96/28",
"52.252.113.240/28",
"52.230.163.32/28",
"172.212.159.64/28",
"52.255.111.80/28",
"52.255.111.0/28",
"4.151.241.240/28",
"52.255.111.32/28",
"52.255.111.48/28",
"52.255.111.16/28",
"52.230.164.176/28",
"52.176.139.176/28",
"52.173.234.16/28",
"4.151.71.176/28",
"4.151.119.48/28",
"52.255.109.112/28",
"52.255.109.80/28",
"20.161.75.208/28",
"68.154.28.96/28",
"52.255.109.128/28",
"52.225.75.208/28",
"52.190.139.48/28",
"68.221.67.240/28",
"52.156.77.144/28",
"52.148.129.32/28",
"40.84.221.208/28",
"104.210.139.224/28",
"40.84.221.224/28",
"104.210.139.192/28",
]

View File

@@ -0,0 +1,2 @@
- import: (data)/clients/small-internet-browsers/netsurf.yaml
- import: (data)/clients/small-internet-browsers/palemoon.yaml

View File

@@ -0,0 +1,5 @@
- name: "reduce-weight-netsurf"
user_agent_regex: "NetSurf"
action: WEIGH
weight:
adjust: -5

View File

@@ -0,0 +1,5 @@
- name: "reduce-weight-palemoon"
user_agent_regex: "PaleMoon"
action: WEIGH
weight:
adjust: -5

View File

@@ -0,0 +1,6 @@
- name: telegrambot
action: ALLOW
expression:
all:
- userAgent.matches("TelegramBot")
- verifyFCrDNS(remoteAddress, "ptr\\.telegram\\.org$")

View File

@@ -0,0 +1,6 @@
- name: vkbot
action: ALLOW
expression:
all:
- userAgent.matches("vkShare[^+]+\\+http\\://vk\\.com/dev/Share")
- verifyFCrDNS(remoteAddress, "^snipster\\d+\\.go\\.mail\\.ru$")

View File

@@ -0,0 +1,6 @@
# https://connect.mozilla.org/t5/firefox-labs/try-out-link-previews-in-firefox-labs-138-and-share-your/td-p/92012
- name: x-firefox-ai
action: WEIGH
expression: '"X-Firefox-Ai" in headers'
weight:
adjust: 5

View File

@@ -0,0 +1,6 @@
- name: allow-api-routes
action: ALLOW
expression:
all:
- '!(method == "HEAD" || method == "GET")'
- path.startsWith("/api/")

View File

@@ -0,0 +1,7 @@
- name: allow-api-requests
action: ALLOW
expression:
all:
- '"Accept" in headers'
- 'headers["Accept"] == "application/json"'
- 'path.startsWith("/api/")'

View File

@@ -1,10 +1,13 @@
# Common "keeping the internet working" routes
- name: well-known
path_regex: ^/.well-known/.*$
path_regex: ^/\.well-known/.*$
action: ALLOW
- name: favicon
path_regex: ^/favicon.ico$
path_regex: ^/favicon\.(?:ico|png|gif|jpg|jpeg|svg)$
action: ALLOW
- name: robots-txt
path_regex: ^/robots.txt$
path_regex: ^/robots\.txt$
action: ALLOW
- name: sitemap
path_regex: ^/sitemap\.xml$
action: ALLOW

View File

@@ -0,0 +1,3 @@
- name: no-user-agent-string
action: DENY
expression: userAgent == ""

View File

@@ -0,0 +1,11 @@
- import: (data)/crawlers/googlebot.yaml
- import: (data)/crawlers/applebot.yaml
- import: (data)/crawlers/bingbot.yaml
- import: (data)/crawlers/duckduckbot.yaml
- import: (data)/crawlers/qwantbot.yaml
- import: (data)/crawlers/internet-archive.yaml
- import: (data)/crawlers/kagibot.yaml
- import: (data)/crawlers/marginalia.yaml
- import: (data)/crawlers/mojeekbot.yaml
- import: (data)/crawlers/commoncrawl.yaml
- import: (data)/crawlers/yandexbot.yaml

View File

@@ -0,0 +1,8 @@
# User agents that index exclusively for search in for AI systems.
# Each entry should have a positive/ALLOW entry created as well, with further documentation.
# Exceptions:
# - Claude-SearchBot: No published IP allowlist
- name: "ai-crawlers-search"
user_agent_regex: >-
OAI-SearchBot|Claude-SearchBot
action: DENY

View File

@@ -0,0 +1,8 @@
# User agents that crawl for training AI/LLM systems
# Each entry should have a positive/ALLOW entry created as well, with further documentation.
# Exceptions:
# - ClaudeBot: No published IP allowlist
- name: "ai-crawlers-training"
user_agent_regex: >-
GPTBot|ClaudeBot
action: DENY

View File

@@ -0,0 +1,881 @@
- name: alibaba-cloud
action: DENY
# Updated 2025-08-20 from IP addresses for AS45102
remote_addresses:
- 103.81.186.0/23
- 110.76.21.0/24
- 110.76.23.0/24
- 116.251.64.0/18
- 139.95.0.0/23
- 139.95.10.0/23
- 139.95.12.0/23
- 139.95.14.0/23
- 139.95.16.0/23
- 139.95.18.0/23
- 139.95.2.0/23
- 139.95.4.0/23
- 139.95.6.0/23
- 139.95.64.0/24
- 139.95.8.0/23
- 14.1.112.0/22
- 14.1.115.0/24
- 140.205.1.0/24
- 140.205.122.0/24
- 147.139.0.0/17
- 147.139.0.0/18
- 147.139.128.0/17
- 147.139.128.0/18
- 147.139.155.0/24
- 147.139.192.0/18
- 147.139.64.0/18
- 149.129.0.0/20
- 149.129.0.0/21
- 149.129.16.0/23
- 149.129.192.0/18
- 149.129.192.0/19
- 149.129.224.0/19
- 149.129.32.0/19
- 149.129.64.0/18
- 149.129.64.0/19
- 149.129.8.0/21
- 149.129.96.0/19
- 156.227.20.0/24
- 156.236.12.0/24
- 156.236.17.0/24
- 156.240.76.0/23
- 156.245.1.0/24
- 161.117.0.0/16
- 161.117.0.0/17
- 161.117.126.0/24
- 161.117.127.0/24
- 161.117.128.0/17
- 161.117.128.0/24
- 161.117.129.0/24
- 161.117.138.0/24
- 161.117.143.0/24
- 170.33.104.0/24
- 170.33.105.0/24
- 170.33.106.0/24
- 170.33.107.0/24
- 170.33.136.0/24
- 170.33.137.0/24
- 170.33.138.0/24
- 170.33.20.0/24
- 170.33.21.0/24
- 170.33.22.0/24
- 170.33.23.0/24
- 170.33.24.0/24
- 170.33.29.0/24
- 170.33.30.0/24
- 170.33.31.0/24
- 170.33.32.0/24
- 170.33.33.0/24
- 170.33.34.0/24
- 170.33.35.0/24
- 170.33.64.0/24
- 170.33.65.0/24
- 170.33.66.0/24
- 170.33.68.0/24
- 170.33.69.0/24
- 170.33.72.0/24
- 170.33.73.0/24
- 170.33.76.0/24
- 170.33.77.0/24
- 170.33.78.0/24
- 170.33.79.0/24
- 170.33.80.0/24
- 170.33.81.0/24
- 170.33.82.0/24
- 170.33.83.0/24
- 170.33.84.0/24
- 170.33.85.0/24
- 170.33.86.0/24
- 170.33.88.0/24
- 170.33.90.0/24
- 170.33.92.0/24
- 170.33.93.0/24
- 185.78.106.0/23
- 198.11.128.0/18
- 198.11.137.0/24
- 198.11.184.0/21
- 202.144.199.0/24
- 203.107.64.0/24
- 203.107.65.0/24
- 203.107.66.0/24
- 203.107.67.0/24
- 203.107.68.0/24
- 205.204.102.0/23
- 205.204.111.0/24
- 205.204.117.0/24
- 205.204.125.0/24
- 205.204.96.0/19
- 223.5.5.0/24
- 223.6.6.0/24
- 2400:3200::/48
- 2400:3200:baba::/48
- 2400:b200:4100::/48
- 2400:b200:4101::/48
- 2400:b200:4102::/48
- 2400:b200:4103::/48
- 2401:8680:4100::/48
- 2401:b180:4100::/48
- 2404:2280:1000::/36
- 2404:2280:1000::/37
- 2404:2280:1800::/37
- 2404:2280:2000::/36
- 2404:2280:2000::/37
- 2404:2280:2800::/37
- 2404:2280:3000::/36
- 2404:2280:3000::/37
- 2404:2280:3800::/37
- 2404:2280:4000::/36
- 2404:2280:4000::/37
- 2404:2280:4800::/37
- 2408:4000:1000::/48
- 2408:4009:500::/48
- 240b:4000::/32
- 240b:4000::/33
- 240b:4000:8000::/33
- 240b:4000:fffe::/48
- 240b:4001::/32
- 240b:4001::/33
- 240b:4001:8000::/33
- 240b:4002::/32
- 240b:4002::/33
- 240b:4002:8000::/33
- 240b:4004::/32
- 240b:4004::/33
- 240b:4004:8000::/33
- 240b:4005::/32
- 240b:4005::/33
- 240b:4005:8000::/33
- 240b:4006::/48
- 240b:4006:1000::/44
- 240b:4006:1000::/45
- 240b:4006:1000::/47
- 240b:4006:1002::/47
- 240b:4006:1008::/45
- 240b:4006:1010::/44
- 240b:4006:1010::/45
- 240b:4006:1018::/45
- 240b:4006:1020::/44
- 240b:4006:1020::/45
- 240b:4006:1028::/45
- 240b:4007::/32
- 240b:4007::/33
- 240b:4007:8000::/33
- 240b:4009::/32
- 240b:4009::/33
- 240b:4009:8000::/33
- 240b:400b::/32
- 240b:400b::/33
- 240b:400b:8000::/33
- 240b:400c::/32
- 240b:400c::/33
- 240b:400c::/40
- 240b:400c::/41
- 240b:400c:100::/40
- 240b:400c:100::/41
- 240b:400c:180::/41
- 240b:400c:80::/41
- 240b:400c:8000::/33
- 240b:400c:f00::/48
- 240b:400c:f01::/48
- 240b:400c:ffff::/48
- 240b:400d::/32
- 240b:400d::/33
- 240b:400d:8000::/33
- 240b:400e::/32
- 240b:400e::/33
- 240b:400e:8000::/33
- 240b:400f::/32
- 240b:400f::/33
- 240b:400f:8000::/33
- 240b:4011::/32
- 240b:4011::/33
- 240b:4011:8000::/33
- 240b:4012::/48
- 240b:4013::/32
- 240b:4013::/33
- 240b:4013:8000::/33
- 240b:4014::/32
- 240b:4014::/33
- 240b:4014:8000::/33
- 43.100.0.0/15
- 43.100.0.0/16
- 43.101.0.0/16
- 43.102.0.0/20
- 43.102.112.0/20
- 43.102.16.0/20
- 43.102.32.0/20
- 43.102.48.0/20
- 43.102.64.0/20
- 43.102.80.0/20
- 43.102.96.0/20
- 43.103.0.0/17
- 43.103.0.0/18
- 43.103.64.0/18
- 43.104.0.0/15
- 43.104.0.0/16
- 43.105.0.0/16
- 43.108.0.0/17
- 43.108.0.0/18
- 43.108.64.0/18
- 43.91.0.0/16
- 43.91.0.0/17
- 43.91.128.0/17
- 43.96.10.0/24
- 43.96.100.0/24
- 43.96.101.0/24
- 43.96.102.0/24
- 43.96.104.0/24
- 43.96.11.0/24
- 43.96.20.0/24
- 43.96.21.0/24
- 43.96.23.0/24
- 43.96.24.0/24
- 43.96.25.0/24
- 43.96.3.0/24
- 43.96.32.0/24
- 43.96.33.0/24
- 43.96.34.0/24
- 43.96.35.0/24
- 43.96.4.0/24
- 43.96.40.0/24
- 43.96.5.0/24
- 43.96.52.0/24
- 43.96.6.0/24
- 43.96.66.0/24
- 43.96.67.0/24
- 43.96.68.0/24
- 43.96.69.0/24
- 43.96.7.0/24
- 43.96.70.0/24
- 43.96.71.0/24
- 43.96.72.0/24
- 43.96.73.0/24
- 43.96.74.0/24
- 43.96.75.0/24
- 43.96.8.0/24
- 43.96.80.0/24
- 43.96.81.0/24
- 43.96.84.0/24
- 43.96.85.0/24
- 43.96.86.0/24
- 43.96.88.0/24
- 43.96.9.0/24
- 43.96.96.0/24
- 43.98.0.0/16
- 43.98.0.0/17
- 43.98.128.0/17
- 43.99.0.0/16
- 43.99.0.0/17
- 43.99.128.0/17
- 45.199.179.0/24
- 47.235.0.0/22
- 47.235.0.0/23
- 47.235.1.0/24
- 47.235.10.0/23
- 47.235.10.0/24
- 47.235.11.0/24
- 47.235.12.0/23
- 47.235.12.0/24
- 47.235.13.0/24
- 47.235.16.0/23
- 47.235.16.0/24
- 47.235.18.0/23
- 47.235.18.0/24
- 47.235.19.0/24
- 47.235.2.0/23
- 47.235.20.0/24
- 47.235.21.0/24
- 47.235.22.0/24
- 47.235.23.0/24
- 47.235.24.0/22
- 47.235.24.0/23
- 47.235.26.0/23
- 47.235.28.0/23
- 47.235.28.0/24
- 47.235.29.0/24
- 47.235.30.0/24
- 47.235.31.0/24
- 47.235.4.0/24
- 47.235.5.0/24
- 47.235.6.0/23
- 47.235.6.0/24
- 47.235.7.0/24
- 47.235.8.0/24
- 47.235.9.0/24
- 47.236.0.0/15
- 47.236.0.0/16
- 47.237.0.0/16
- 47.237.32.0/20
- 47.237.34.0/24
- 47.238.0.0/15
- 47.238.0.0/16
- 47.239.0.0/16
- 47.240.0.0/16
- 47.240.0.0/17
- 47.240.128.0/17
- 47.241.0.0/16
- 47.241.0.0/17
- 47.241.128.0/17
- 47.242.0.0/15
- 47.242.0.0/16
- 47.243.0.0/16
- 47.244.0.0/16
- 47.244.0.0/17
- 47.244.128.0/17
- 47.244.73.0/24
- 47.245.0.0/18
- 47.245.0.0/19
- 47.245.128.0/17
- 47.245.128.0/18
- 47.245.192.0/18
- 47.245.32.0/19
- 47.245.64.0/18
- 47.245.64.0/19
- 47.245.96.0/19
- 47.246.100.0/22
- 47.246.104.0/21
- 47.246.104.0/22
- 47.246.108.0/22
- 47.246.120.0/24
- 47.246.122.0/24
- 47.246.123.0/24
- 47.246.124.0/24
- 47.246.125.0/24
- 47.246.128.0/22
- 47.246.128.0/23
- 47.246.130.0/23
- 47.246.132.0/22
- 47.246.132.0/23
- 47.246.134.0/23
- 47.246.136.0/21
- 47.246.136.0/22
- 47.246.140.0/22
- 47.246.144.0/23
- 47.246.144.0/24
- 47.246.145.0/24
- 47.246.146.0/23
- 47.246.146.0/24
- 47.246.147.0/24
- 47.246.150.0/23
- 47.246.150.0/24
- 47.246.151.0/24
- 47.246.152.0/23
- 47.246.152.0/24
- 47.246.153.0/24
- 47.246.154.0/24
- 47.246.155.0/24
- 47.246.156.0/22
- 47.246.156.0/23
- 47.246.158.0/23
- 47.246.160.0/20
- 47.246.160.0/21
- 47.246.168.0/21
- 47.246.176.0/20
- 47.246.176.0/21
- 47.246.184.0/21
- 47.246.192.0/22
- 47.246.192.0/23
- 47.246.194.0/23
- 47.246.196.0/22
- 47.246.196.0/23
- 47.246.198.0/23
- 47.246.32.0/22
- 47.246.66.0/24
- 47.246.67.0/24
- 47.246.68.0/23
- 47.246.68.0/24
- 47.246.69.0/24
- 47.246.72.0/21
- 47.246.72.0/22
- 47.246.76.0/22
- 47.246.80.0/24
- 47.246.82.0/23
- 47.246.82.0/24
- 47.246.83.0/24
- 47.246.84.0/22
- 47.246.84.0/23
- 47.246.86.0/23
- 47.246.88.0/22
- 47.246.88.0/23
- 47.246.90.0/23
- 47.246.92.0/23
- 47.246.92.0/24
- 47.246.93.0/24
- 47.246.96.0/21
- 47.246.96.0/22
- 47.250.0.0/17
- 47.250.0.0/18
- 47.250.128.0/17
- 47.250.128.0/18
- 47.250.192.0/18
- 47.250.64.0/18
- 47.250.99.0/24
- 47.251.0.0/16
- 47.251.0.0/17
- 47.251.128.0/17
- 47.251.224.0/22
- 47.252.0.0/17
- 47.252.0.0/18
- 47.252.128.0/17
- 47.252.128.0/18
- 47.252.192.0/18
- 47.252.64.0/18
- 47.252.67.0/24
- 47.253.0.0/16
- 47.253.0.0/17
- 47.253.128.0/17
- 47.254.0.0/17
- 47.254.0.0/18
- 47.254.113.0/24
- 47.254.128.0/18
- 47.254.128.0/19
- 47.254.160.0/19
- 47.254.192.0/18
- 47.254.192.0/19
- 47.254.224.0/19
- 47.254.64.0/18
- 47.52.0.0/16
- 47.52.0.0/17
- 47.52.128.0/17
- 47.56.0.0/15
- 47.56.0.0/16
- 47.57.0.0/16
- 47.74.0.0/18
- 47.74.0.0/19
- 47.74.0.0/21
- 47.74.128.0/17
- 47.74.128.0/18
- 47.74.192.0/18
- 47.74.32.0/19
- 47.74.64.0/18
- 47.74.64.0/19
- 47.74.96.0/19
- 47.75.0.0/16
- 47.75.0.0/17
- 47.75.128.0/17
- 47.76.0.0/16
- 47.76.0.0/17
- 47.76.128.0/17
- 47.77.0.0/22
- 47.77.0.0/23
- 47.77.104.0/21
- 47.77.12.0/22
- 47.77.128.0/17
- 47.77.128.0/18
- 47.77.128.0/21
- 47.77.136.0/21
- 47.77.144.0/21
- 47.77.152.0/21
- 47.77.16.0/21
- 47.77.16.0/22
- 47.77.192.0/18
- 47.77.2.0/23
- 47.77.20.0/22
- 47.77.24.0/22
- 47.77.24.0/23
- 47.77.26.0/23
- 47.77.32.0/19
- 47.77.32.0/20
- 47.77.4.0/22
- 47.77.4.0/23
- 47.77.48.0/20
- 47.77.6.0/23
- 47.77.64.0/19
- 47.77.64.0/20
- 47.77.8.0/21
- 47.77.8.0/22
- 47.77.80.0/20
- 47.77.96.0/20
- 47.77.96.0/21
- 47.78.0.0/17
- 47.78.128.0/17
- 47.79.0.0/20
- 47.79.0.0/21
- 47.79.104.0/21
- 47.79.112.0/20
- 47.79.128.0/19
- 47.79.128.0/20
- 47.79.144.0/20
- 47.79.16.0/20
- 47.79.16.0/21
- 47.79.192.0/18
- 47.79.192.0/19
- 47.79.224.0/19
- 47.79.24.0/21
- 47.79.32.0/20
- 47.79.32.0/21
- 47.79.40.0/21
- 47.79.48.0/20
- 47.79.48.0/21
- 47.79.52.0/23
- 47.79.54.0/23
- 47.79.56.0/21
- 47.79.56.0/23
- 47.79.58.0/23
- 47.79.60.0/23
- 47.79.62.0/23
- 47.79.64.0/20
- 47.79.64.0/21
- 47.79.72.0/21
- 47.79.8.0/21
- 47.79.80.0/20
- 47.79.80.0/21
- 47.79.83.0/24
- 47.79.88.0/21
- 47.79.96.0/19
- 47.79.96.0/20
- 47.80.0.0/18
- 47.80.0.0/19
- 47.80.128.0/17
- 47.80.128.0/18
- 47.80.192.0/18
- 47.80.32.0/19
- 47.80.64.0/18
- 47.80.64.0/19
- 47.80.96.0/19
- 47.81.0.0/18
- 47.81.0.0/19
- 47.81.128.0/17
- 47.81.128.0/18
- 47.81.192.0/18
- 47.81.32.0/19
- 47.81.64.0/18
- 47.81.64.0/19
- 47.81.96.0/19
- 47.82.0.0/18
- 47.82.0.0/19
- 47.82.10.0/23
- 47.82.12.0/23
- 47.82.128.0/17
- 47.82.128.0/18
- 47.82.14.0/23
- 47.82.192.0/18
- 47.82.32.0/19
- 47.82.32.0/21
- 47.82.40.0/21
- 47.82.48.0/21
- 47.82.56.0/21
- 47.82.64.0/18
- 47.82.64.0/19
- 47.82.8.0/23
- 47.82.96.0/19
- 47.83.0.0/16
- 47.83.0.0/17
- 47.83.128.0/17
- 47.83.32.0/21
- 47.83.40.0/21
- 47.83.48.0/21
- 47.83.56.0/21
- 47.84.0.0/16
- 47.84.0.0/17
- 47.84.128.0/17
- 47.84.144.0/21
- 47.84.152.0/21
- 47.84.160.0/21
- 47.84.168.0/21
- 47.85.0.0/16
- 47.85.0.0/17
- 47.85.112.0/22
- 47.85.112.0/23
- 47.85.114.0/23
- 47.85.128.0/17
- 47.86.0.0/16
- 47.86.0.0/17
- 47.86.128.0/17
- 47.87.0.0/18
- 47.87.0.0/19
- 47.87.128.0/18
- 47.87.128.0/19
- 47.87.160.0/19
- 47.87.192.0/22
- 47.87.192.0/23
- 47.87.194.0/23
- 47.87.196.0/22
- 47.87.196.0/23
- 47.87.198.0/23
- 47.87.200.0/22
- 47.87.200.0/23
- 47.87.202.0/23
- 47.87.204.0/22
- 47.87.204.0/23
- 47.87.206.0/23
- 47.87.208.0/22
- 47.87.208.0/23
- 47.87.210.0/23
- 47.87.212.0/22
- 47.87.212.0/23
- 47.87.214.0/23
- 47.87.216.0/22
- 47.87.216.0/23
- 47.87.218.0/23
- 47.87.220.0/22
- 47.87.220.0/23
- 47.87.222.0/23
- 47.87.224.0/22
- 47.87.224.0/23
- 47.87.226.0/23
- 47.87.228.0/22
- 47.87.228.0/23
- 47.87.230.0/23
- 47.87.232.0/22
- 47.87.232.0/23
- 47.87.234.0/23
- 47.87.236.0/22
- 47.87.236.0/23
- 47.87.238.0/23
- 47.87.240.0/22
- 47.87.240.0/23
- 47.87.242.0/23
- 47.87.32.0/19
- 47.87.64.0/18
- 47.87.64.0/19
- 47.87.96.0/19
- 47.88.0.0/17
- 47.88.0.0/18
- 47.88.109.0/24
- 47.88.128.0/17
- 47.88.128.0/18
- 47.88.135.0/24
- 47.88.192.0/18
- 47.88.41.0/24
- 47.88.42.0/24
- 47.88.43.0/24
- 47.88.64.0/18
- 47.89.0.0/18
- 47.89.0.0/19
- 47.89.100.0/24
- 47.89.101.0/24
- 47.89.102.0/24
- 47.89.103.0/24
- 47.89.104.0/21
- 47.89.104.0/22
- 47.89.108.0/22
- 47.89.122.0/24
- 47.89.123.0/24
- 47.89.124.0/23
- 47.89.124.0/24
- 47.89.125.0/24
- 47.89.128.0/18
- 47.89.128.0/19
- 47.89.160.0/19
- 47.89.192.0/18
- 47.89.192.0/19
- 47.89.221.0/24
- 47.89.224.0/19
- 47.89.32.0/19
- 47.89.72.0/22
- 47.89.72.0/23
- 47.89.74.0/23
- 47.89.76.0/22
- 47.89.76.0/23
- 47.89.78.0/23
- 47.89.80.0/23
- 47.89.82.0/23
- 47.89.84.0/24
- 47.89.88.0/22
- 47.89.88.0/23
- 47.89.90.0/23
- 47.89.92.0/22
- 47.89.92.0/23
- 47.89.94.0/23
- 47.89.96.0/24
- 47.89.97.0/24
- 47.89.98.0/23
- 47.89.99.0/24
- 47.90.0.0/17
- 47.90.0.0/18
- 47.90.128.0/17
- 47.90.128.0/18
- 47.90.172.0/24
- 47.90.173.0/24
- 47.90.174.0/24
- 47.90.175.0/24
- 47.90.192.0/18
- 47.90.64.0/18
- 47.91.0.0/19
- 47.91.0.0/20
- 47.91.112.0/20
- 47.91.128.0/17
- 47.91.128.0/18
- 47.91.16.0/20
- 47.91.192.0/18
- 47.91.32.0/19
- 47.91.32.0/20
- 47.91.48.0/20
- 47.91.64.0/19
- 47.91.64.0/20
- 47.91.80.0/20
- 47.91.96.0/19
- 47.91.96.0/20
- 5.181.224.0/23
- 59.82.136.0/23
- 8.208.0.0/16
- 8.208.0.0/17
- 8.208.0.0/18
- 8.208.0.0/19
- 8.208.128.0/17
- 8.208.141.0/24
- 8.208.32.0/19
- 8.209.0.0/19
- 8.209.0.0/20
- 8.209.128.0/18
- 8.209.128.0/19
- 8.209.16.0/20
- 8.209.160.0/19
- 8.209.192.0/18
- 8.209.192.0/19
- 8.209.224.0/19
- 8.209.36.0/23
- 8.209.36.0/24
- 8.209.37.0/24
- 8.209.38.0/23
- 8.209.38.0/24
- 8.209.39.0/24
- 8.209.40.0/22
- 8.209.40.0/23
- 8.209.42.0/23
- 8.209.44.0/22
- 8.209.44.0/23
- 8.209.46.0/23
- 8.209.48.0/20
- 8.209.48.0/21
- 8.209.56.0/21
- 8.209.64.0/18
- 8.209.64.0/19
- 8.209.96.0/19
- 8.210.0.0/16
- 8.210.0.0/17
- 8.210.128.0/17
- 8.210.240.0/24
- 8.211.0.0/17
- 8.211.0.0/18
- 8.211.104.0/21
- 8.211.128.0/18
- 8.211.128.0/19
- 8.211.160.0/19
- 8.211.192.0/18
- 8.211.192.0/19
- 8.211.224.0/19
- 8.211.226.0/24
- 8.211.64.0/18
- 8.211.80.0/21
- 8.211.88.0/21
- 8.211.96.0/21
- 8.212.0.0/17
- 8.212.0.0/18
- 8.212.128.0/18
- 8.212.128.0/19
- 8.212.160.0/19
- 8.212.192.0/18
- 8.212.192.0/19
- 8.212.224.0/19
- 8.212.64.0/18
- 8.213.0.0/17
- 8.213.0.0/18
- 8.213.128.0/19
- 8.213.128.0/20
- 8.213.144.0/20
- 8.213.160.0/21
- 8.213.160.0/22
- 8.213.164.0/22
- 8.213.176.0/20
- 8.213.176.0/21
- 8.213.184.0/21
- 8.213.192.0/18
- 8.213.192.0/19
- 8.213.224.0/19
- 8.213.251.0/24
- 8.213.252.0/24
- 8.213.253.0/24
- 8.213.64.0/18
- 8.214.0.0/16
- 8.214.0.0/17
- 8.214.128.0/17
- 8.215.0.0/16
- 8.215.0.0/17
- 8.215.128.0/17
- 8.215.160.0/24
- 8.215.162.0/23
- 8.215.168.0/24
- 8.215.169.0/24
- 8.216.0.0/17
- 8.216.0.0/18
- 8.216.128.0/17
- 8.216.128.0/18
- 8.216.148.0/24
- 8.216.192.0/18
- 8.216.64.0/18
- 8.216.69.0/24
- 8.216.74.0/24
- 8.217.0.0/16
- 8.217.0.0/17
- 8.217.128.0/17
- 8.218.0.0/16
- 8.218.0.0/17
- 8.218.128.0/17
- 8.219.0.0/16
- 8.219.0.0/17
- 8.219.128.0/17
- 8.219.40.0/21
- 8.220.116.0/24
- 8.220.128.0/18
- 8.220.128.0/19
- 8.220.147.0/24
- 8.220.160.0/19
- 8.220.192.0/18
- 8.220.192.0/19
- 8.220.224.0/19
- 8.220.229.0/24
- 8.220.64.0/18
- 8.220.64.0/19
- 8.220.96.0/19
- 8.221.0.0/17
- 8.221.0.0/18
- 8.221.0.0/21
- 8.221.128.0/17
- 8.221.128.0/18
- 8.221.184.0/22
- 8.221.188.0/22
- 8.221.192.0/18
- 8.221.192.0/21
- 8.221.200.0/21
- 8.221.208.0/21
- 8.221.216.0/21
- 8.221.48.0/21
- 8.221.56.0/21
- 8.221.64.0/18
- 8.221.8.0/21
- 8.222.0.0/20
- 8.222.0.0/21
- 8.222.112.0/20
- 8.222.128.0/17
- 8.222.128.0/18
- 8.222.16.0/20
- 8.222.16.0/21
- 8.222.192.0/18
- 8.222.24.0/21
- 8.222.32.0/20
- 8.222.32.0/21
- 8.222.40.0/21
- 8.222.48.0/20
- 8.222.48.0/21
- 8.222.56.0/21
- 8.222.64.0/20
- 8.222.64.0/21
- 8.222.72.0/21
- 8.222.8.0/21
- 8.222.80.0/20
- 8.222.80.0/21
- 8.222.88.0/21
- 8.222.96.0/19
- 8.222.96.0/20
- 8.223.0.0/17
- 8.223.0.0/18
- 8.223.128.0/17
- 8.223.128.0/18
- 8.223.192.0/18
- 8.223.64.0/18

View File

@@ -0,0 +1,20 @@
# Indexing for search and Siri
# https://support.apple.com/en-us/119829
- name: applebot
user_agent_regex: Applebot
action: ALLOW
# https://search.developer.apple.com/applebot.json
remote_addresses: [
"17.241.208.160/27",
"17.241.193.160/27",
"17.241.200.160/27",
"17.22.237.0/24",
"17.22.245.0/24",
"17.22.253.0/24",
"17.241.75.0/24",
"17.241.219.0/24",
"17.241.227.0/24",
"17.246.15.0/24",
"17.246.19.0/24",
"17.246.23.0/24",
]

Some files were not shown because too many files have changed in this diff Show More