Skip to content

fix: restore global rate limit fallback for passive sources#1761

Open
hriszc wants to merge 2 commits intoprojectdiscovery:devfrom
hriszc:codex/fix-rate-limit-fallback
Open

fix: restore global rate limit fallback for passive sources#1761
hriszc wants to merge 2 commits intoprojectdiscovery:devfrom
hriszc:codex/fix-rate-limit-fallback

Conversation

@hriszc
Copy link

@hriszc hriszc commented Mar 9, 2026

/claim #1434

Summary

Restore the global -rl fallback semantics for passive sources when no provider-specific entry is present in -rls.

  • uses the global rate limit for every source unless a source-specific override exists
  • keeps -rls overrides intact when a provider limit is explicitly set
  • preserves unlimited behavior only when neither -rl nor -rls provides a limit
  • adds regression coverage for global fallback, provider overrides, and zero-value fallback behavior

Validation

Ran:

go test ./pkg/passive -run 'TestResolveSourceRateLimit'

Result: passed.

Summary by CodeRabbit

  • Refactor

    • Centralized rate-limit resolution: unified handling of global limits and per-source overrides to simplify and standardize limiter creation and behavior.
  • Tests

    • Added unit tests covering global/default cases, per-source overrides, and zero/unlimited scenarios to validate the resolution logic.

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7ccfcdd7-d01e-43e1-956c-7cd2d8e76145

📥 Commits

Reviewing files that changed from the base of the PR and between 5ae8966 and 3978486.

📒 Files selected for processing (1)
  • pkg/passive/passive_test.go

Walkthrough

Extracted per-source rate-limit logic into a new helper resolveSourceRateLimit in the passive package and updated buildMultiRateLimiter to use it; added unit tests covering global defaults, per-source overrides, nil/missing custom maps, and zero (unlimited) cases.

Changes

Cohort / File(s) Summary
Rate Limit Resolution Refactor
pkg/passive/passive.go
Introduced resolveSourceRateLimit(globalRateLimit, rateLimit, sourceName) to centralize per-source rate-limit determination. Now handles nil rateLimit, applies per-source overrides via rateLimit.Custom.Get(lowercased sourceName), falls back to derived default from globalRateLimit, and buildMultiRateLimiter calls this helper for each source.
Unit Tests
pkg/passive/passive_test.go
Added TestResolveSourceRateLimit with subtests for: global-only rate limit, missing custom map, per-source override present, custom zero limit, and zero global rate limit (unlimited). Asserts expected uint results for each scenario.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I hopped through code to tidy the trail,
Pulled limits into one snug little vale,
Tests gave me carrots for each known case,
Now sources behave in orderly grace. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: restore global rate limit fallback for passive sources' directly and clearly describes the main change: restoring global rate limit fallback behavior for passive sources when provider-specific overrides are absent.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
pkg/passive/passive_test.go (2)

41-47: Consider adding a test case for case-insensitivity.

The resolveSourceRateLimit function applies strings.ToLower(sourceName) to ensure case-insensitive matching. Adding an explicit test case (e.g., sourceName: "SiteDossier" expecting to match the "sitedossier" key) would help protect this behavior against future regressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/passive/passive_test.go` around lines 41 - 47, Add a test case to
passive_test.go that verifies resolveSourceRateLimit is case-insensitive: in the
existing table-driven tests (the one using customRates and globalRateLimit), add
an entry with sourceName set to "SiteDossier" (mixed case) and expected equal to
the same value as the "sitedossier" customRates entry (e.g., 2); this ensures
resolveSourceRateLimit (which calls strings.ToLower(sourceName)) continues to
match keys regardless of case.

11-18: Use NewSyncLockMap constructor instead of direct struct literal initialization.

The test initializes SyncLockMap via struct literal (Map: map[string]uint{...}), which bypasses the constructor and its initialization logic. The codebase already demonstrates the correct pattern in pkg/passive/sources.go with NewSyncLockMap[string, string](mapsutil.WithMap(...)). This same pattern also appears in pkg/runner/runner.go and should be refactored in both places for consistency.

Use:

customRates := &subscraping.CustomRateLimit{
	Custom: *mapsutil.NewSyncLockMap[string, uint](
		mapsutil.WithMap(mapsutil.Map[string, uint]{
			"sitedossier": 2,
			"github":      0,
		}),
	),
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/passive/passive_test.go` around lines 11 - 18, The test constructs a
mapsutil.SyncLockMap via a struct literal which bypasses its constructor; update
the customRates initialization in passive_test.go to use mapsutil.NewSyncLockMap
with mapsutil.WithMap (e.g., create CustomRateLimit with Custom set to
*mapsutil.NewSyncLockMap[string, uint](mapsutil.WithMap(mapsutil.Map[string,
uint]{...}))) so the SyncLockMap is properly initialized; modify the customRates
variable (and any similar direct initializations) to use NewSyncLockMap instead
of the Map: struct literal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/passive/passive_test.go`:
- Around line 41-47: Add a test case to passive_test.go that verifies
resolveSourceRateLimit is case-insensitive: in the existing table-driven tests
(the one using customRates and globalRateLimit), add an entry with sourceName
set to "SiteDossier" (mixed case) and expected equal to the same value as the
"sitedossier" customRates entry (e.g., 2); this ensures resolveSourceRateLimit
(which calls strings.ToLower(sourceName)) continues to match keys regardless of
case.
- Around line 11-18: The test constructs a mapsutil.SyncLockMap via a struct
literal which bypasses its constructor; update the customRates initialization in
passive_test.go to use mapsutil.NewSyncLockMap with mapsutil.WithMap (e.g.,
create CustomRateLimit with Custom set to *mapsutil.NewSyncLockMap[string,
uint](mapsutil.WithMap(mapsutil.Map[string, uint]{...}))) so the SyncLockMap is
properly initialized; modify the customRates variable (and any similar direct
initializations) to use NewSyncLockMap instead of the Map: struct literal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 85708726-d29f-41c7-b080-be1dd5ea7f90

📥 Commits

Reviewing files that changed from the base of the PR and between 13e5db7 and 5ae8966.

📒 Files selected for processing (2)
  • pkg/passive/passive.go
  • pkg/passive/passive_test.go

@neo-by-projectdiscovery-dev
Copy link

neo-by-projectdiscovery-dev bot commented Mar 9, 2026

Neo - PR Security Review

No security issues found

Highlights

  • Incremental review: Only test code changes between commits 5ae8966 and 3978486
  • Added test case for case-insensitive source name matching in rate limit resolution
  • Test enhancements improve coverage without modifying production code behavior

Comment @pdneo help for available commands. · Open in Neo

@hriszc
Copy link
Author

hriszc commented Mar 9, 2026

Addressed the review nits:

  • switched the test map initialization to NewSyncLockMap(...WithMap(...))
  • added a mixed-case SiteDossier regression case to lock in case-insensitive matching
  • reran go test ./pkg/passive -run TestResolveSourceRateLimit

The PR head has been updated accordingly.

@hriszc
Copy link
Author

hriszc commented Mar 9, 2026

Follow-up: the CodeRabbit suggestions are already addressed, checks are green, and the regression coverage is in place. This should be ready for human review when convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant