Warn when production shares one rate-limit bucket (closes #149) #153
Reference in New Issue
Block a user
Delete Branch "issue-149-trusted-proxies-warning"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #149.
Visibility only: the rate-limit keying, the limits and the
TRUSTED_PROXIESdefault are unchanged.What changed
internal/config/config.go: newwarnSharedRateLimitBucket, called fromNewright after the "Configuration loaded" line. Fires only whenIsProd()andlen(TrustedProxies) == 0.README.mdenv-var table +#### Trusted proxies: state the consequence and nameTRUSTED_PROXIESas the remedy.README.md### Rate Limiting: the shared-bucket paragraph now splits the receiver case (costs throughput, safe direction) from the login/password-change case (costs availability of the only admin path, not safe). The verified aggregate-ceiling text is preserved verbatim inside the receiver bullet.README.mdsecurity-features bullet: the "5 POST attempts per minute per IP" claim is now conditional onTRUSTED_PROXIES.internal/config/config_test.go+export_test.go:TestSharedRateLimitBucketWarning, asserting against a test-controlledsloghandler.TODO.mddeliberately untouched (owned by #151).Warning text
Level
WARN, attrsenvironment,trustedProxies:> TRUSTED_PROXIES is empty: rate limits key on the connecting peer, so behind the reverse proxy a production deployment runs behind, every client shares one bucket per limit. Any remote client can then keep the login limit full and deny the admin login, the only administrative path, until restart. Set TRUSTED_PROXIES to your reverse proxy's address.
Mutation evidence
--- FAIL: TestSharedRateLimitBucketWarning/prod_without_trusted_proxies_warns, four"" does not containassertions.--- FAIL: .../prod_with_trusted_proxies_is_quietand--- FAIL: .../dev_without_trusted_proxies_is_quiet.Gate evidence
make checkexit 0,0 issues.docker build --no-cache-filter=lint,builder --progress=plain .exit 0. In-container lint ran (#16 53.57 0 issues.) and tests ran uncached (#23 ok sneak.berlin/go/webhooker/internal/config 1.113s, not(cached)), including--- PASS: TestSharedRateLimitBucketWarningand its three subtests.PASS. Every clause of the warning and all three README rewrites verified against source; DoD for #149 met, scope held (keying, limits and the
TRUSTED_PROXIESdefault untouched), single commit onnext, mergeable, no attribution trailers.Nit, non-blocking:
README.md:326-327still carries the uncorrected form of the very claim this PR fixes elsewhere — "go-chi/httprate for per-IP login rate limiting" — with noTRUSTED_PROXIESqualifier and no nearby text that supplies one, unlikeREADME.md:864and:871which are qualified by the paragraph at:907. Same class of inaccuracy as the corrected:1148-1155, but outside the three passages the issue enumerated, so not held against this PR. Acceptable would be a trailing "(per bucket; per IP only withTRUSTED_PROXIESset)" or a link to Rate Limiting.Disclosure: the warning is gated on
IsProd(), andWEBHOOKER_ENVIRONMENTdefaults todev, so an internet-exposed deployment that never set it gets no warning. That matches the issue's DoD wording exactly ("in production mode") and is not treated as a defect here; flagging it as input to #150.Gate evidence on
0beeddd: CIcheck / check (push)success in 3m7s. Localmake checkexit 0, zero(cached)test markers,0 issues.docker build --no-cache-filter=lint,builderexit 0 in 3m0.8s; in-container lint executed (#16 49.42 0 issues., no parallel-linter message), tests uncached (ok sneak.berlin/go/webhooker/internal/config 1.112s) with all three warning subtests passing. Mutation reproduced independently in both directions in a throwaway copy: forcing the guard to always return failsprod_without_trusted_proxies_warnson all four assertions; forcing it never to return fails both quiet subtests.