Skip to content

fix(dig-node): budget the proxy-fetch leg separately from cheap miss-lookups (#2189) - #190

Merged
MichaelTaylor3d merged 4 commits into
mainfrom
fix/2189-proxy-fetch-budget
Aug 6, 2026
Merged

fix(dig-node): budget the proxy-fetch leg separately from cheap miss-lookups (#2189)#190
MichaelTaylor3d merged 4 commits into
mainfrom
fix/2189-proxy-fetch-budget

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

Closes DIG-Network/dig_ecosystem#2189. DoS defense-in-depth (loop-security non-gating finding on PR #182).

The problem

The per-requestor miss budget (16 burst / 4-per-sec) is sized for a cheap DHT lookup, but a proxy:true miss triggers a full multi-source capsule fetch (large egress + crypto). A requestor could draw expensive proxy fetches from the budget calibrated for cheap lookups, converting cheap-lookup allowance into egress.

Fix

The proxy fetch-through leg gets its own, tighter, independent per-requestor allowance — a separate MissRateLimiter (proxy_rate_limiter, download.rs), not the shared lookup budget:

  • DEFAULT_PROXY_FETCH_BURST = 4.0 and DEFAULT_PROXY_FETCH_REFILL_PER_SEC = 1.0 (rate_limit.rs) — a quarter of the cheap-lookup burst/refill, calibrated against the per-fetch egress + CPU of a full multi-source capsule pull. A legitimate NAT-blocked reader proxying a handful of resources is absorbed; sustained proxy spam is throttled independently.
  • Fail-closed: once the proxy allowance is spent, further proxy:true misses degrade to the normal redirect outcome — never an unbounded fetch. The cheap-lookup budget is untouched by proxy spend.
  • A const{}-style calibration test pins DEFAULT_PROXY_FETCH_BURST < DEFAULT_MISS_LOOKUP_BURST, so a future loosening that erased the separation reds the build.

Test (the acceptance)

proxy_fetch_is_bounded_by_its_own_allowance_independent_of_lookups (lib.rs): a generous cheap-lookup budget (100) + a tiny proxy allowance (1, no refill), interleaved with lookup-only calls. It asserts the second proxy:true miss is redirected (proxy allowance exhausted) while the lookup budget is provably untouched — a regression that drew the proxy fetch from the shared lookup budget would serve the second proxy call (100 lookup tokens available) and red the assertion. Non-vacuous by construction.

Blast radius

crates/dig-node-core/src/rate_limit.rs (new proxy-default constants + with_proxy_defaults()), crates/dig-node-core/src/download.rs (the separate proxy_rate_limiter wired into miss_outcome, fail-closed degrade), crates/dig-node-core/src/lib.rs (the regression test + a test-only set_proxy_rate_limit). The cheap-lookup miss path (#2007) is unchanged.

Version

root [workspace.package].version 0.99.5 → 0.99.6 (patch, fix: — a rate-limit tightening, no wire/API change). Cargo.lock regenerated. Refs #2007.


Generated by Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
…lookups (#2189)
The per-requestor miss budget (16 burst / 4-per-sec) is sized for a cheap DHT
lookup, but a proxy:true miss triggers a full multi-source capsule fetch (large
egress + crypto). Add a separate, tighter per-requestor TokenBucket for the proxy
leg (4 burst / 1-per-sec) so proxy egress cannot be drained under the lookup
budget. Fail-closed: an exhausted proxy allowance degrades to the redirect, never
an unbounded fetch. The trusted operator (Local) is exempt.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…(#2189)
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d merged commit 83780c9 into mainAug 6, 2026
15 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the fix/2189-proxy-fetch-budget branch August 6, 2026 06:28
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@MichaelTaylor3d@claude