fix: per-endpoint rate limits, request timeout and input hardening

bal-server:
- Wire independent actix-governor buckets per endpoint class (pushtxs,
  searchtx, info/stats, default) so polling a cheap endpoint can no longer
  exhaust the push-txs budget; previously every limit was dead config
- Enforce BAL_SERVER_ACTIX_TIMEOUT_SECS via a request-timeout middleware that
  returns 408 Request Timeout, covering slow request bodies
- De-duplicate txids within a single /pushtxs request body
- Replace the byte-slice xpub detection (panic on non-ASCII) with a safe
  prefix check

bal-pusher:
- Handle malformed/empty ZMQ frames without indexing panics or UTF-8 expect
- Return an error from sign_message and skip the stats report instead of
  panicking when the private key cannot be parsed

validation / db:
- Reject IPv4-mapped IPv6 targets (::ffff:a.b.c.d) in is_valid_welist_url
  to close an SSRF bypass, with unit tests
- Use Path::starts_with for the SQLite forbidden-directory check so paths
  like /etcfoo are not misclassified

misc:
- Add explicit secret patterns to .gitignore and sync the docs
This commit is contained in:
2026-10-14 18:30:23 -04:00
parent 457c143954
commit b8d87ecabd
8 changed files with 224 additions and 55 deletions

View File

@@ -22,7 +22,7 @@ serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.116" }
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "postgres", "chrono"] }
regex = { version = "1.10.4" }
tokio = { version = "1", features = ["rt", "net","macros","rt-multi-thread"] }
tokio = { version = "1", features = ["rt", "net","macros","rt-multi-thread","time"] }
url = { version = "2" }
# server-only