1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-21 18:55:36 +02:00

security: fix two Codex review findings + add port option

Fix 1 — NixOS: store/ dir missing from ReadWritePaths
  archive_path points to .archivr/; captures write artifacts to the
  sibling store/ directory. Whitelisting only .archivr/ caused POST
  /captures to fail under ProtectSystem=strict.
  Fix: use builtins.dirOf a.path to whitelist the parent, which
  contains both .archivr/ and store/.

Fix 2 — Rust: X-Forwarded-For was unconditionally trusted
  An attacker could send a different IP on every login attempt,
  bypassing LOGIN_MAX_ATTEMPTS entirely.
  Fix: use ConnectInfo<SocketAddr> (via into_make_service_with_connect_info)
  as the primary rate-limit key; XFF is trusted only when the TCP peer
  is loopback (i.e. a local reverse proxy). Tests without a real socket
  fall back to XFF unchanged.

Port configuration:
  NixOS module: split 'bind' string into separate 'listenAddress'
  (default 127.0.0.1) and 'port' (default 8080) options. openFirewall
  now uses cfg.port directly instead of parsing it from the bind string.
  README NixOS example updated accordingly.
This commit is contained in:
TheGeneralist 2026-06-29 20:32:08 +02:00
parent 7ed7cb882f
commit 71e176cbd1
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
4 changed files with 70 additions and 27 deletions

View file

@ -154,7 +154,8 @@ enable the service:
{
services.archivr-server = {
enable = true;
bind = "127.0.0.1:8080"; # loopback only; put nginx/caddy in front for TLS
# listenAddress defaults to "127.0.0.1" (loopback only)
# port defaults to 8080
archives = [
{ id = "personal"; label = "Personal"; path = "/srv/archivr/personal/.archivr"; }
{ id = "work"; label = "Work"; path = "/srv/archivr/work/.archivr"; }
@ -180,7 +181,8 @@ Only needed when binding to a non-loopback address:
```nix
services.archivr-server = {
bind = "0.0.0.0:8080";
listenAddress = "0.0.0.0";
port = 8080; # explicit, though 8080 is the default
openFirewall = true;
};
```