Skip to content

feat(http): add RFC 9111 cache w/ per-request disable#6746

Open
dwisiswant0 wants to merge 10 commits intodevfrom
dwisiswant0/feat/http/httpcache
Open

feat(http): add RFC 9111 cache w/ per-request disable#6746
dwisiswant0 wants to merge 10 commits intodevfrom
dwisiswant0/feat/http/httpcache

Conversation

@dwisiswant0
Copy link
Copy Markdown
Member

@dwisiswant0 dwisiswant0 commented Jan 3, 2026

Proposed changes

feat(http): add RFC-9111 cache w/ per-request disable

  • wrap HTTP transports with sandrolain/httpcache
    and expose global --no-http-cache flag.
  • allow templates to set disable-http-cache.
  • bump Go to 1.25.7.

Closes #6725.


by default, caching is on. but if either:

  • the user disables it globally via CLI, or
  • disables it via template-specific request option
    (disable-http-cache), the cache is turned off.

neither can force it "on" if the other wants it "off".

everything follows the spec outlined in #6725,
with LevelDB configured using default settings.
see:

nit changes:

  • bd805e6 ci: pin go version by go.mod
    Previously pinned to the "stable" version
    because GOEXPERIMENT=greenteagc
    requires >= go1.25. now that constraint is no
    longer needed, it follows go.mod again.
  • ef30f8b build: set GODEBUG=tlssha1=1
    SHA-1 sig algos are now disallowed in TLS 1.2
    handshakes by default (RFC 9155) in >= go1.25.
    although we explicitly set tls.VersionTLS10
    (in httpclientpool), we also set globally,
    just in case.
  • 7077986 fix(bindgen): update deprecated parser.ParseDir calls
    as commit message.
  • 43e6f80 build(make): add more GO* envs for go-build
    as commit message.

🚨 behavior/breaking changes & action items

few things to consider after bumping to >= go1.25,
beyond what's already addressed in this patch (as
outlined above):

  • crypto/x509.ParseCertificate now rejects
    certs with negative pathLenConstraint and is
    stricter about ASN.1 T61String/BMPString
    encoding.

    Impact: Nuclei might report errors parsing
    malformed certs that were previously accepted.
    So be aware that "failed to parse certificate"
    errors might increase for targets with
    non-compliant certs.

  • nil pointer compiler bug fixed in 1.25 means
    code that incorrectly delayed nil checks
    (e.g., using a file handle before checking the
    err from os.Open) will now correctly panic.

    Impact: Low risk but worth noting if user see
    new panics in error handling paths.

  • Container-aware GOMAXPROCS1, means the runtime
    now respects cgroup CPU limits and updates
    GOMAXPROCS dynamically.

    Impact: Nuclei running in Docker/Kubernetes
    might see different default concurrency levels.
    This is basically an improvement but changes
    perf characteristics. Can be disabled via
    GODEBUG=containermaxprocs=0.

  • Change to unhandled panic output2, means the
    output format for recovered and re-panicked
    panics has changed (it no longer repeats the
    panic value).

    Impact: If Nuclei has any internal log parsing
    tests that match exact panic output strings,
    they might fail.

  • Platform support. go1.25 now requires macOS 12
    (Monterey) or later and windows/arm (32-bit)
    port is broken and deprecated (support wil be
    removed in >= go1.26).

    Impact: No action needed. We already ignore that
    deprecated GOOS & GOARCH in the GoReleaser
    config.

Proof

Template:

# test-http-cache.yaml
id: test-http-cache

info:
  name: Test HTTP Cache
  author: dwisiswant0
  severity: info
  tags: test

http:
  - method: GET
    path:
      - "{{BaseURL}}/cache/300" # Cacheable for 300 seconds (Cache-Control: max-age=300)
      # - "{{BaseURL}}/cache/0" # not cacheable
      # - "{{BaseURL}}/get" # no cache headers (won't be cached)
      # - "{{BaseURL}}/response-headers?Cache-Control=max-age=60" # custom cache headers

    matchers:
      - type: status
        status:
          - 200
$ make build
$ DISABLE_STDOUT=1 hyperfine --warmup 1 --prepare "curl https://httpbin.org/cache/300" \
>       "./bin/nuclei -silent -t test-http-cache.yaml -u https://httpbin.org" \
>       "./bin/nuclei -silent -t test-http-cache.yaml -u https://httpbin.org -no-http-cache"
Benchmark 1: ./bin/nuclei -silent -t test-http-cache.yaml -u https://httpbin.org
  Time (mean ± σ):     396.6 ms ±  13.3 ms    [User: 377.1 ms, System: 92.1 ms]
  Range (min … max):   375.3 ms … 419.8 ms    10 runs
 
Benchmark 2: ./bin/nuclei -silent -t test-http-cache.yaml -u https://httpbin.org -no-http-cache
  Time (mean ± σ):      1.674 s ±  0.157 s    [User: 0.369 s, System: 0.097 s]
  Range (min … max):    1.421 s …  1.857 s    10 runs
 
Summary
  ./bin/nuclei -silent -t test-http-cache.yaml -u https://httpbin.org ran
    4.22 ± 0.42 times faster than ./bin/nuclei -silent -t test-http-cache.yaml -u https://httpbin.org -no-http-cache

As demonstrated above, enabling the HTTP cache
results in a ~4x speedup for repeated requests
to cacheable endpoints. This significantly reduces
network traffic and scan times when testing
against targets with proper cache control headers,
making re-scans and complex workflows much more
efficient.

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Summary by CodeRabbit

  • New Features

    • Adds RFC‑compliant HTTP response caching, a global CLI toggle for HTTP caching, and a per-request option to disable caching.
  • Documentation

    • Documents the disable-http-cache request option and updates HTTP field reference and template docs.
  • Chores

    • Updates Go toolchain and numerous dependencies; tweaks build environment settings.
  • Tests

    • Adds integration tests for caching behavior and adjusts leak-detection ignores for cache background tasks.

@dwisiswant0 dwisiswant0 requested a review from Mzack9999 January 3, 2026 01:43
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds RFC 9111–compliant HTTP response caching with LevelDB (fallback in-memory), global enable flag and per-request disable, integrates caching into HTTP transport/client pool, updates CLI/docs/templates/tests, refactors bindgen to use packages.Load, updates dependencies and Makefile build flags.

Changes

Cohort / File(s) Summary
HTTP Caching Core
pkg/protocols/http/httpcache/httpcache.go
New package providing RFC 9111 transport wrapper, singleton LevelDB (with in-memory fallback), transport config (Vary, CacheKeyHeaders, async revalidate) and caching predicate (2xx only).
HTTP Client Pool
pkg/protocols/http/httpclientpool/clientpool.go
Adds DisableHTTPCache to Configuration, includes it in Hash()/HasStandardOptions(), and conditionally applies the httpcache transport wrapper when caching is enabled.
HTTP Request Model
pkg/protocols/http/http.go
Adds DisableHTTPCache bool to Request with YAML/JSON/jsonschema tags and propagates it into client configuration during Compile.
Global Options & CLI
pkg/types/types.go, cmd/nuclei/main.go
Adds EnableHTTPCache to global Options (preserved in Copy()); adds CLI flag --http-cache (-hc) bound to this option.
Templates & Docs
pkg/templates/templates_doc.go, SYNTAX-REFERENCE.md
Introduces disable-http-cache template field, updates/reorders HTTP request fields and documentation entries.
Integration Tests & Test Adjustments
cmd/integration-test/http.go, lib/tests/sdk_test.go
Adds httpCache and httpDisableCache integration tests and registers testcases; extends goleak ignores for LevelDB and BufferPool goroutines.
AST Generator Refactor
pkg/js/devtools/bindgen/generator.go
Replaces go/parser/types.Config flow with golang.org/x/tools/go/packages (packages.Load), uses pkg.Syntax/pkg.Types, and adjusts error handling.
Dependencies
go.mod
Bumps Go toolchain to 1.25.3 and updates many module versions (httpcache/leveldb, AWS SDK v2, testcontainers, mongo-driver, otel, protobuf, docker, etc.).
Build Configuration
Makefile
go-build recipe now prefixes build with GOEXPERIMENT=greenteagc and GODEBUG=tlssha1=1 while keeping CGO_ENABLED=0.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as Nuclei Request
  participant Pool as HTTP Client Pool
  participant Transport as httpcache.Transport
  participant Cache as LevelDB / In‑memory Cache
  participant Server as Origin Server

  Client->>Pool: Issue HTTP request
  Pool->>Transport: Forward request (wrapped RoundTripper)
  activate Transport
  Transport->>Cache: Lookup cache key (URL + Vary + CacheKeyHeaders)
  alt cache hit (fresh)
    Cache-->>Transport: Cached response
    Transport-->>Pool: Return cached response
  else cache miss or stale
    Transport->>Server: Send request (may add conditional headers)
    Server-->>Transport: Response (200 / 304 / other)
    alt 304 Not Modified
      Transport->>Cache: Update metadata
      Transport-->>Pool: Serve cached body + headers
    else 2xx
      Transport->>Cache: Store/refresh entry
      Transport-->>Pool: Return response
    else non-2xx
      Transport-->>Pool: Return response (not cached)
    end
  end
  deactivate Transport
  Pool-->>Client: Deliver final response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇
I hid a stash beneath the log,
LevelDB snug, no noisy slog.
Two-twenty replies I gently keep,
Revalidate while you hop and sleep.
Fewer hops — a faster jog! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Changes are well-scoped to HTTP caching implementation. However, the Go version bump (1.24→1.25.3), GODEBUG/GOEXPERIMENT environment variables, and parser refactoring exceed the direct caching feature scope, though maintainers noted these are necessary infrastructure updates. Clarify whether Go 1.25 bump, GODEBUG=tlssha1=1, GOEXPERIMENT=greenteagc, and parser refactoring to golang.org/x/tools are essential dependencies for the caching feature or separate infrastructure changes that could be split into a separate PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(http): add RFC 9111 cache w/ per-request disable' clearly and specifically describes the main change: adding RFC 9111-compliant HTTP caching with per-request disable capability.
Linked Issues check ✅ Passed The PR successfully implements all major coding requirements from issue #6725: RFC 9111 compliant caching using sandrolain/httpcache, LevelDB persistent storage with in-memory fallback, 2XX-only caching policy, proper transport configuration, global disable flag, and per-request disable option.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dwisiswant0/feat/http/httpcache

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

Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 3

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbeebda and 43e6f80.

⛔ Files ignored due to path filters (6)
  • .github/workflows/compat-checks.yaml is excluded by !**/*.yaml
  • .github/workflows/release.yaml is excluded by !**/*.yaml
  • .github/workflows/tests.yaml is excluded by !**/*.yaml
  • .goreleaser.yml is excluded by !**/*.yml
  • go.sum is excluded by !**/*.sum
  • nuclei-jsonschema.json is excluded by !**/*.json
📒 Files selected for processing (10)
  • Makefile
  • SYNTAX-REFERENCE.md
  • cmd/nuclei/main.go
  • go.mod
  • pkg/js/devtools/bindgen/generator.go
  • pkg/protocols/http/http.go
  • pkg/protocols/http/httpcache/httpcache.go
  • pkg/protocols/http/httpclientpool/clientpool.go
  • pkg/templates/templates_doc.go
  • pkg/types/types.go
🧰 Additional context used
📓 Path-based instructions (6)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.go: Format Go code using go fmt ./...
Run static analysis using go vet ./... on Go code

Files:

  • pkg/protocols/http/http.go
  • cmd/nuclei/main.go
  • pkg/types/types.go
  • pkg/js/devtools/bindgen/generator.go
  • pkg/protocols/http/httpcache/httpcache.go
  • pkg/templates/templates_doc.go
  • pkg/protocols/http/httpclientpool/clientpool.go
pkg/protocols/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/protocols/**/*.go: Each protocol implementation should implement the Request interface with Compile(), ExecuteWithResults(), Match(), and Extract() methods
Protocol implementations should embed Operators for matching/extraction functionality

Files:

  • pkg/protocols/http/http.go
  • pkg/protocols/http/httpcache/httpcache.go
  • pkg/protocols/http/httpclientpool/clientpool.go
cmd/nuclei/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Main CLI entry point with flag parsing and configuration should be located in cmd/nuclei

Files:

  • cmd/nuclei/main.go
pkg/js/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Use custom JavaScript runtime for code protocol templates with auto-generated bindings from pkg/js/generated/

Files:

  • pkg/js/devtools/bindgen/generator.go
pkg/js/devtools/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Development tools for JavaScript binding generation should be located in pkg/js/devtools/

Files:

  • pkg/js/devtools/bindgen/generator.go
pkg/templates/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Template parsing, compilation, and management should be implemented in pkg/templates

Files:

  • pkg/templates/templates_doc.go
🧬 Code graph analysis (2)
pkg/protocols/http/httpcache/httpcache.go (2)
pkg/protocols/http/request_annotations.go (1)
  • Once (48-48)
pkg/catalog/config/nucleiconfig.go (1)
  • DefaultConfig (23-23)
pkg/protocols/http/httpclientpool/clientpool.go (1)
pkg/protocols/http/httpcache/httpcache.go (1)
  • NewTransportWrapper (46-71)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint
🔇 Additional comments (15)
SYNTAX-REFERENCE.md (1)

1460-1469: LGTM!

Documentation for the new disable-http-cache field is clear and follows the established format. The description correctly indicates that this is a per-request override of global cache settings.

go.mod (3)

3-3: Go 1.25.3 toolchain upgrade looks good.

The Go version bump is well-documented in the PR description, including notes about breaking changes (stricter x509 parsing, nil-check fixes, container-aware GOMAXPROCS, etc.). Ensure the CI/CD pipelines and development environments are updated to use Go 1.25.3.


63-67: Dependency updates look reasonable.

The dependency updates include:

  • Coordinated AWS SDK v2 updates (all modules aligned)
  • testcontainers bump for testing (v0.38.0 → v0.39.0)
  • mongo-driver patch update (v1.17.4 → v1.17.6)
  • OpenTelemetry and protobuf patch updates

These are primarily patch and minor version updates that should maintain backward compatibility. The coordinated AWS SDK update is particularly good practice.

Also applies to: 122-128, 157-170, 380-381, 416-416


116-116: HTTP caching dependency is well-maintained and secure.

The github.com/sandrolain/httpcache v1.4.0 dependency is actively maintained (last updated December 2025) with no known security vulnerabilities. The library correctly implements RFC 9111 caching semantics including Age calculation, Cache-Control handling, and Vary header support. This is a solid choice for the HTTP caching feature.

pkg/protocols/http/http.go (2)

175-178: LGTM!

The DisableHTTPCache field is well-implemented:

  • Follows struct field naming conventions
  • Properly tagged for YAML/JSON serialization with omitempty
  • Clear documentation indicating it overrides global settings
  • Appropriate jsonschema metadata for API documentation

312-316: Proper integration with HTTP client pool configuration.

The DisableHTTPCache field is correctly propagated to the httpclientpool.Configuration during request compilation. This placement alongside other connection configuration settings (like DisableCookie) is appropriate and will allow the HTTP client pool to respect per-request cache control settings.

pkg/js/devtools/bindgen/generator.go (1)

105-130: Bindgen functionality verified after package loading refactor.

The migration from go/parser to golang.org/x/tools/go/packages is a sound modernization that has been successfully tested. The bindgen tool correctly processes all library modules (bytes, fs, goconsole, ikev2, kerberos, ldap, mssql, mysql, net, oracle, and others) with proper package discovery and error handling. The jsupdate-bindgen Make target uses the refactored code and operates without issues.

pkg/protocols/http/httpclientpool/clientpool.go (3)

23-23: LGTM! Clean integration of httpcache package.

The import and usage of the httpcache package is properly integrated into the client pool configuration.


87-88: LGTM! Configuration field added correctly.

The DisableHTTPCache field is properly added to the Configuration struct with clear documentation.


226-228: LGTM! Correct conditional caching logic.

The caching is only enabled when both the global option (options.DisableHTTPCache) and the per-configuration option (configuration.DisableHTTPCache) are false (not disabled). This provides the correct two-level control as described in the PR objectives.

pkg/templates/templates_doc.go (1)

602-606: LGTM! Documentation correctly describes the new field.

The disable-http-cache field documentation is clear and accurately describes that it disables HTTP caching for individual requests and overrides global cache settings.

pkg/protocols/http/httpcache/httpcache.go (4)

27-40: LGTM! Robust cache initialization with fallback.

The singleton pattern is correctly implemented with sync.Once, and the fallback to in-memory cache when LevelDB initialization fails is a good defensive approach. The verbose logging on success is appropriate.


46-71: LGTM! Well-configured transport wrapper.

The transport configuration is comprehensive and follows RFC 9111 best practices:

  • SkipServerErrorsFromCache: true prevents serving stale errors
  • EnableVarySeparation: true respects Vary headers
  • CacheKeyHeaders includes appropriate headers for cache segmentation (Authorization, Cookie, etc.)
  • AsyncRevalidateTimeout provides reasonable async revalidation window

75-78: LGTM! Correct cache policy.

Caching only 2xx responses is the correct approach per RFC 9111 and prevents caching error responses that might be transient.


29-29: No initialization order issue exists.

The code is safe as-is. Go's init() functions execute automatically during package import (before main() starts), so config.DefaultConfig is guaranteed to be initialized before any code calls GetCacheDir(). The sync.Once pattern at line 28-37 provides thread-safe lazy initialization for the cache. By the time GetCache() is invoked during HTTP client pool operations, config.DefaultConfig is already available.

Comment thread cmd/nuclei/main.go Outdated
Comment thread Makefile
Comment thread pkg/types/types.go Outdated
Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 0

🧹 Nitpick comments (1)
lib/tests/sdk_test.go (1)

22-28: Remove redundant function-level ignores.

The package-level ignore on line 23 (IgnoreAnyContainingPkg("github.com/syndtr/goleveldb")) already suppresses all goroutines from the LevelDB package, making the specific function ignores on lines 24-28 redundant.

Recommendation: Choose one approach:

  • Option 1 (recommended): Keep only the package-level ignore if all LevelDB background goroutines are expected and legitimate.
  • Option 2: Remove the package-level ignore and keep only the specific function ignores if you want tighter control and the ability to detect unexpected goroutines from LevelDB.

Option 1 is simpler and likely sufficient since LevelDB's background goroutines are part of its normal operation.

🔎 Proposed fix to remove redundancy
 	// LevelDB goroutines (used by httpcache)
 	goleak.IgnoreAnyContainingPkg("github.com/syndtr/goleveldb"),
-	goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).compactionError"),
-	goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).mCompaction"),
-	goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).mpoolDrain"),
-	goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).tCompaction"),
-	goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).drain"),
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43e6f80 and 717ffe7.

📒 Files selected for processing (1)
  • lib/tests/sdk_test.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.go: Format Go code using go fmt ./...
Run static analysis using go vet ./... on Go code

Files:

  • lib/tests/sdk_test.go
lib/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

SDK for embedding nuclei as a library should be implemented in lib/

Files:

  • lib/tests/sdk_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Tests (windows-latest)
  • GitHub Check: Tests (ubuntu-latest)
  • GitHub Check: Tests (macOS-latest)

@dwisiswant0
Copy link
Copy Markdown
Member Author

Note that if this ships, it will affect some templates (particularly cache poisoning/deception & cache-related vulnerabilities).

Scenario:

  1. The template sends a request with a "poison" header (ex., X-Forwarded-Host: evil.com).
  2. The server reflects evil.com and returns cacheable headers.
  3. Nuclei's new client-side cache stores this response.
  4. The template sends a second "clean" request.
  5. Nuclei serves the locally cached poisoned response instead of sending the request to the server.

Here is what I've found (so far - tho still needs double-checking & deeper pass - I mainly found these via grep -Pnr "id: .*?cache.*?" - so the list is non-exhaustive):

# Cache poisoning
http/vulnerabilities/generic/cache-poisoning.yaml
http/vulnerabilities/generic/cache-poisoning-xss.yaml
http/vulnerabilities/nextjs/next-js-cache-poisoning.yaml
http/misconfiguration/akamai/akamai-s3-cache-poisoning.yaml
http/misconfiguration/aws/cdn-cache-poisoning.yaml
http/fuzzing/cache-poisoning-fuzz.yaml

# Cache deception/leakage
http/vulnerabilities/magento/magento-cacheleak.yaml
http/vulnerabilities/wordpress/wpdm-cache-session.yaml
http/vulnerabilities/wordpress/clearfy-cache-xss.yaml
http/vulnerabilities/wordpress/wp-super-cache-fpd.yaml
http/vulnerabilities/wordpress/wp-fastest-cache-fpd.yaml
http/vulnerabilities/wordpress/wp-sg-cachepress-fpd.yaml
http/misconfiguration/aem/aem-cached-pages.yaml

# Cache purge
http/misconfiguration/unauthenticated-varnish-cache-purge.yaml

They will need to be adjusted by adding disable-http-cache: true to explicitly disable the client-side cache.

cc: @projectdiscovery/template

Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 2

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 800a4f5 and ea668ec.

⛔ Files ignored due to path filters (2)
  • integration_tests/protocols/http/disable-http-cache.yaml is excluded by !**/*.yaml
  • integration_tests/protocols/http/http-cache.yaml is excluded by !**/*.yaml
📒 Files selected for processing (1)
  • cmd/integration-test/http.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.go: Format Go code using go fmt ./...
Run static analysis using go vet ./... on Go code

Files:

  • cmd/integration-test/http.go
🧬 Code graph analysis (1)
cmd/integration-test/http.go (1)
pkg/testutils/integration.go (1)
  • RunNucleiTemplateAndGetResults (30-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint
🔇 Additional comments (2)
cmd/integration-test/http.go (2)

14-14: LGTM!

The sync/atomic import is necessary for the atomic counter operations used in the new cache tests.


92-92: LGTM!

The test case registration follows the existing pattern and correctly associates the template path with the test implementation.

Comment thread cmd/integration-test/http.go
Comment thread cmd/integration-test/http.go
@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/feat/http/httpcache branch from ea668ec to 5cc562e Compare January 3, 2026 04:40
@dwisiswant0 dwisiswant0 changed the title feat(http): add RFC-9111 cache w/ per-request disable feat(http): add RFC 9111 cache w/ per-request disable Jan 3, 2026
Copy link
Copy Markdown
Member

@Mzack9999 Mzack9999 left a comment

Choose a reason for hiding this comment

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

  • Merge Conflict
  • Since this represent a potential breaking change, what do you think to make it optional with a CLI flag instead of enabled by default?

@dwisiswant0
Copy link
Copy Markdown
Member Author

dwisiswant0 commented Jan 5, 2026

  • Since this represent a potential breaking change, what do you think to make it optional with a CLI flag instead of enabled by default?

The breaking changes are coming from the Go bump, not by the introduction of this feature. So making it opt-in would not really help either (the break would still be there), because the dependency requires that Go version. And it is not a hard break anyway, just a behavior change.

@dwisiswant0
Copy link
Copy Markdown
Member Author

dwisiswant0 commented Jan 5, 2026

I am noting & calling this out based on past experience, when we bumped the Go version before, we did not revisit or check the release notes and it resulted in breaking. Like:

  • ef30f8b build: set GODEBUG=tlssha1=1
    SHA-1 sig algos are now disallowed in TLS 1.2
    handshakes by default (RFC 9155) in >= go1.25.
    although we explicitly set tls.VersionTLS10
    (in httpclientpool), we also set globally,
    just in case.

"just in case" means I do not remember which PR it was anymore, but I still remember it happening, iirc.

so I think it is worth being extra explicit this time, just want to make sure we do not repeat the same mistake.

@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/feat/http/httpcache branch from 5cc562e to cc402af Compare January 5, 2026 23:36
Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 0

🧹 Nitpick comments (3)
pkg/templates/templates_doc.go (1)

463-686: Clarify per‑request cache disable wording to avoid implying it can re‑enable cache

The disable-http-cache field description says it “overrides global cache settings.” Given the implementation only ever disables caching (and cannot re‑enable it if --no-http-cache is set), consider rephrasing to something like:

“Disables HTTP caching for this request, even when HTTP caching is globally enabled.”

and regenerate this file via docgen so SYNTAX-REFERENCE and generated docs stay in sync.

pkg/js/devtools/bindgen/generator.go (1)

15-16: go/packages-based loader looks good; optional diagnostics improvement

The switch to golang.org/x/tools/go/packages with NeedSyntax/NeedTypes and wiring pkgMain.Types into TemplateData is a solid fit for this devtool and keeps the rest of the pipeline unchanged.

If you want richer diagnostics when a package fails to load, you could aggregate pkgMain.Errors into a single error message (instead of only the first) and include directory/pattern info, but that’s purely a tooling UX improvement.

Also applies to: 105-122, 126-130

SYNTAX-REFERENCE.md (1)

1459-1467: Tighten wording for disable-http-cache to reflect one‑way disable

To match the actual behavior (per-request flag can only disable caching, not re-enable it if --no-http-cache is set), consider rephrasing this entry to something like:

“Disables HTTP caching for this request, even when HTTP caching is globally enabled.”

That keeps intent clear and avoids suggesting it can override a global disable.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc562e and cc402af.

⛔ Files ignored due to path filters (8)
  • .github/workflows/compat-checks.yaml is excluded by !**/*.yaml
  • .github/workflows/release.yaml is excluded by !**/*.yaml
  • .github/workflows/tests.yaml is excluded by !**/*.yaml
  • .goreleaser.yml is excluded by !**/*.yml
  • go.sum is excluded by !**/*.sum
  • integration_tests/protocols/http/disable-http-cache.yaml is excluded by !**/*.yaml
  • integration_tests/protocols/http/http-cache.yaml is excluded by !**/*.yaml
  • nuclei-jsonschema.json is excluded by !**/*.json
📒 Files selected for processing (12)
  • Makefile
  • SYNTAX-REFERENCE.md
  • cmd/integration-test/http.go
  • cmd/nuclei/main.go
  • go.mod
  • lib/tests/sdk_test.go
  • pkg/js/devtools/bindgen/generator.go
  • pkg/protocols/http/http.go
  • pkg/protocols/http/httpcache/httpcache.go
  • pkg/protocols/http/httpclientpool/clientpool.go
  • pkg/templates/templates_doc.go
  • pkg/types/types.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • lib/tests/sdk_test.go
  • cmd/nuclei/main.go
  • pkg/protocols/http/httpcache/httpcache.go
  • pkg/protocols/http/http.go
🧰 Additional context used
📓 Path-based instructions (5)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.go: Format Go code using go fmt ./...
Run static analysis using go vet ./... on Go code

Files:

  • pkg/types/types.go
  • pkg/templates/templates_doc.go
  • pkg/protocols/http/httpclientpool/clientpool.go
  • cmd/integration-test/http.go
  • pkg/js/devtools/bindgen/generator.go
pkg/templates/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Template parsing, compilation, and management should be implemented in pkg/templates

Files:

  • pkg/templates/templates_doc.go
pkg/protocols/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/protocols/**/*.go: Each protocol implementation should implement the Request interface with Compile(), ExecuteWithResults(), Match(), and Extract() methods
Protocol implementations should embed Operators for matching/extraction functionality

Files:

  • pkg/protocols/http/httpclientpool/clientpool.go
pkg/js/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Use custom JavaScript runtime for code protocol templates with auto-generated bindings from pkg/js/generated/

Files:

  • pkg/js/devtools/bindgen/generator.go
pkg/js/devtools/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Development tools for JavaScript binding generation should be located in pkg/js/devtools/

Files:

  • pkg/js/devtools/bindgen/generator.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint
🔇 Additional comments (10)
go.mod (1)

3-416: Validate module state and compatibility under Go 1.25.3

The Go toolchain bump to go 1.25.3 and dependency upgrades (AWS SDK v2 family, sandrolain/httpcache, testcontainers, MongoDB driver, Docker, otel, protobuf, gopsutil, and others) are consistent with the new HTTP caching feature and modern runtime requirements.

Ensure this branch passes module validation and build checks under Go 1.25.3:

go mod tidy
go build ./...
go vet ./...
pkg/types/types.go (2)

204-205: LGTM! DisableHTTPCache field correctly added.

The field is properly declared with a clear comment, and the default false value aligns with the PR objective to enable caching by default.


559-559: LGTM! Copy() now correctly propagates DisableHTTPCache.

The field is properly copied, ensuring the setting persists across option clones.

cmd/integration-test/http.go (3)

94-95: LGTM! Test case registrations added correctly.

The new test cases follow the established pattern and reference the appropriate template files.


1739-1769: LGTM! httpCache test correctly validates caching behavior.

The test properly verifies that:

  1. Both template requests produce matching results (2 results)
  2. Only 1 actual HTTP request reaches the server due to caching

The use of Cache-Control: max-age=2 ensures the response is cacheable per RFC 9111.


1771-1801: LGTM! httpDisableCache test correctly validates cache-disable behavior.

The test properly verifies that when disable-http-cache: true is set in the template:

  1. Both template requests produce matching results (2 results)
  2. Both requests actually hit the server (2 requests, confirming cache is bypassed)
pkg/protocols/http/httpclientpool/clientpool.go (4)

87-88: LGTM! DisableHTTPCache field added to Configuration.

The field is properly placed with a clear comment explaining its purpose.


128-129: LGTM! Hash correctly includes DisableHTTPCache.

Including the cache setting in the hash ensures proper client pooling - cached and non-cached clients will have different hashes and won't be mixed.


144-144: LGTM! HasStandardOptions correctly handles DisableHTTPCache.

When DisableHTTPCache is true, HasStandardOptions() returns false, ensuring a custom client is created with caching disabled rather than using the default pooled client.


226-228: LGTM! Cache wrapper applied correctly with proper precedence.

The logic !options.DisableHTTPCache && !configuration.DisableHTTPCache correctly implements the PR objective: caching is enabled only when neither the global flag (--no-http-cache) nor the template-level option (disable-http-cache) disables it. Either mechanism can independently disable caching.

@dwisiswant0 dwisiswant0 requested a review from Mzack9999 January 5, 2026 23:41
@dwisiswant0
Copy link
Copy Markdown
Member Author

"just in case" means I do not remember which PR it was anymore, but I still remember it happening, iirc.

so I think it is worth being extra explicit this time, just want to make sure we do not repeat the same mistake.

Here I just came across this accidentally: projectdiscovery/fastdialer#434.

Another normative references:

@Mzack9999
Copy link
Copy Markdown
Member

The reason I proposed to make it optional as a start and gradually turn into default, was about not introducing breaking changes on the actual templates. We can quantify on public templates, but many might be private. Hence I think either we introduce some heuristic for cache templates types and we disable this automatically or we can introduce it as optional and activate gradually for what over time we tag as safe template categories (for example single-request templates, which should exclude cache poisoning as they generally require multiple request to poison and check). What do you think?

Copy link
Copy Markdown
Member

@Mzack9999 Mzack9999 left a comment

Choose a reason for hiding this comment

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

marking as "request changes" as there is open discussion about go version bump and default behavior

@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/feat/http/httpcache branch from cc402af to 1c7d02b Compare January 21, 2026 08:36
Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@cmd/nuclei/main.go`:
- Line 438: The short flag "-hc" for the http-cache flag (defined via
flagSet.BoolVarP and bound to options.EnableHTTPCache) collides with the
existing "--health-check" short alias; remove the short alias for http-cache or
assign a different unused short letter—e.g., drop the short alias by switching
from BoolVarP to BoolVar (so only --http-cache remains) or change the short rune
to a non-conflicting one in the http-cache flag registration; update the
corresponding second occurrence at the other location similarly to avoid the
duplicate "-hc" binding.

In `@pkg/protocols/http/httpclientpool/clientpool.go`:
- Around line 226-228: The cache enablement condition in clientpool.go currently
uses OR and makes caching on by default; update the condition that sets
retryableHttpOptions.WrapTransport so it only enables caching when both the
global opt-in and the per-request allow it — i.e., replace the expression using
options.EnableHTTPCache || !configuration.DisableHTTPCache with a conjunction
that checks the global flag (configuration.DisableHTTPCache or its inverse) and
that the request did not disable caching (options.EnableHTTPCache), ensuring
WrapTransport is set only when both criteria are true.
🧹 Nitpick comments (3)
pkg/js/devtools/bindgen/generator.go (2)

103-103: Consider removing or converting debug output.

fmt.Println(directory) appears to be debug output. Consider removing it or converting it to a proper log statement using log.Printf for consistency with Line 124.

Suggested fix
 func CreateTemplateData(directory string, packagePrefix string) (*TemplateData, error) {
-	fmt.Println(directory)
+	log.Printf("[create] Processing directory: %s\n", directory)

119-122: Consider reporting all package errors for better diagnostics.

Currently only the first error is reported. For a dev tool, aggregating all errors could help with debugging when multiple issues exist.

Optional: Report all errors
 	pkgMain := pkgs[0]
 	if len(pkgMain.Errors) > 0 {
-		return nil, errors.Wrap(pkgMain.Errors[0], "could not check package")
+		var errMsgs []string
+		for _, e := range pkgMain.Errors {
+			errMsgs = append(errMsgs, e.Error())
+		}
+		return nil, fmt.Errorf("could not check package: %s", strings.Join(errMsgs, "; "))
 	}
pkg/protocols/http/httpcache/httpcache.go (1)

29-36: Log when LevelDB init fails to avoid silent in‑memory fallback.

Right now the fallback is silent, which makes it hard to diagnose why persistence isn’t used. Consider a warning log on the error path.

♻️ Suggested tweak
-		cache, err = leveldbcache.New(cacheDir)
-		if err != nil {
-			cache = httpcache.NewMemoryCache()
-		} else {
-			gologger.Verbose().Msgf("HTTP cache initialized at %q", cacheDir)
-		}
+		cache, err = leveldbcache.New(cacheDir)
+		if err != nil {
+			gologger.Warning().Msgf("HTTP cache fallback to memory (leveldb init failed): %v", err)
+			cache = httpcache.NewMemoryCache()
+		} else {
+			gologger.Verbose().Msgf("HTTP cache initialized at %q", cacheDir)
+		}

Comment thread cmd/nuclei/main.go Outdated
Comment thread pkg/protocols/http/httpclientpool/clientpool.go Outdated
@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/feat/http/httpcache branch 2 times, most recently from 8b9d7e7 to fd513ff Compare January 21, 2026 11:57
Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@pkg/protocols/http/httpclientpool/clientpool.go`:
- Around line 226-228: DefaultHTTPClient is left nil and the cache wrapper is
only applied in wrappedGet(), so Get() can return a nil client and miss caching;
in initDialers() ensure Dialers.DefaultHTTPClient is constructed (not nil) and
that when options.EnableHTTPCache && !configuration.DisableHTTPCache you apply
the httpcache.NewTransportWrapper() to the DefaultHTTPClient's transport (or set
retryableHttpOptions.WrapTransport accordingly) so the cache is present on the
default client; update initDialers() to create the http.Client (or retryable
client used elsewhere), attach the wrapper, and ensure Get()/wrappedGet() return
that initialized client.

Comment on lines +226 to +228
if options.EnableHTTPCache && !configuration.DisableHTTPCache {
retryableHttpOptions.WrapTransport = httpcache.NewTransportWrapper()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find where DefaultHTTPClient is created and how transport wrapping is configured
rg -nP 'DefaultHTTPClient|NewWithHTTPClient|WrapTransport|httpcache\.NewTransportWrapper' --type=go pkg

Repository: projectdiscovery/nuclei

Length of output: 708


🏁 Script executed:

#!/bin/bash
# Get context around line 182 (DefaultHTTPClient return) and the full Get method
sed -n '170,200p' pkg/protocols/http/httpclientpool/clientpool.go

# Get context around line 227 (WrapTransport)
sed -n '210,240p' pkg/protocols/http/httpclientpool/clientpool.go

# Get context around line 364 (NewWithHTTPClient)
sed -n '350,370p' pkg/protocols/http/httpclientpool/clientpool.go

Repository: projectdiscovery/nuclei

Length of output: 2993


🏁 Script executed:

#!/bin/bash
# Find HasStandardOptions definition
rg -nP 'func.*HasStandardOptions' --type=go pkg

# Find where DefaultHTTPClient is created/initialized
rg -nP 'DefaultHTTPClient\s*=' --type=go pkg

# Find the initialization of DefaultHTTPClient
rg -nB5 -A5 'DefaultHTTPClient\s*=' --type=go pkg/protocols/common/protocolstate/

Repository: projectdiscovery/nuclei

Length of output: 170


🏁 Script executed:

#!/bin/bash
# Get HasStandardOptions implementation
sed -n '143,160p' pkg/protocols/http/httpclientpool/clientpool.go

# Search for DefaultHTTPClient initialization in dialers
cat -n pkg/protocols/common/protocolstate/dialers.go | head -100

# Also search for where DefaultHTTPClient might be initialized
rg -nP 'DefaultHTTPClient\s*=' --type=go

Repository: projectdiscovery/nuclei

Length of output: 1617


🏁 Script executed:

#!/bin/bash
# Find where DefaultHTTPClient is assigned/created
rg -nB10 -A10 'DefaultHTTPClient\s*=' --type=go pkg/protocols/

# Also check in cmd or main files for initialization
git ls-files | grep -E '(main|init|setup)' | head -20

Repository: projectdiscovery/nuclei

Length of output: 530


🏁 Script executed:

#!/bin/bash
# Check the protocol initialization file
cat -n pkg/protocols/common/protocolinit/init.go | head -150

# Search more thoroughly for where DefaultHTTPClient might be created
rg -nB5 -A15 'DefaultHTTPClient' --type=go pkg/ | grep -E '(DefaultHTTPClient|NewWithHTTPClient|WrapTransport)'

Repository: projectdiscovery/nuclei

Length of output: 1940


🏁 Script executed:

#!/bin/bash
# Find protocolstate Init function
rg -nA30 'func Init' pkg/protocols/common/protocolstate/ --type=go

# Find httpclientpool Init function
rg -nA50 'func Init' pkg/protocols/http/httpclientpool/ --type=go

Repository: projectdiscovery/nuclei

Length of output: 8975


🏁 Script executed:

#!/bin/bash
# Get the complete initDialers function
sed -n '66,200p' pkg/protocols/common/protocolstate/state.go

Repository: projectdiscovery/nuclei

Length of output: 4192


🏁 Script executed:

#!/bin/bash
# Continue reading initDialers
sed -n '156,250p' pkg/protocols/common/protocolstate/state.go

Repository: projectdiscovery/nuclei

Length of output: 3007


🏁 Script executed:

#!/bin/bash
# Search for actual assignments to DefaultHTTPClient
rg -nP '\.DefaultHTTPClient\s*=' --type=go pkg/

# Also search for where it might be assigned using Set or other methods
rg -nP 'DefaultHTTPClient' --type=go pkg/ -B2 -A2 | head -100

Repository: projectdiscovery/nuclei

Length of output: 1316


🏁 Script executed:

#!/bin/bash
# Absolutely verify no assignment to DefaultHTTPClient anywhere
rg 'DefaultHTTPClient\s*=' --type=go

# Also search in all files, not just Go
git grep 'DefaultHTTPClient' | grep -E '(\s=\s|:=)' || echo "No assignments found"

# Check if there's any lazy initialization logic
rg -B5 -A5 'dialers\.DefaultHTTPClient' --type=go pkg/

Repository: projectdiscovery/nuclei

Length of output: 1687


DefaultHTTPClient is uninitialized and cache wrapper is not applied.

The concern is valid. DefaultHTTPClient is never created or initialized in the codebase—it remains a nil field in the Dialers struct. Even if it were initialized, the cache wrapper is only applied in wrappedGet() at line 227, not during DefaultHTTPClient creation. When Get() returns dialers.DefaultHTTPClient for standard configurations (line 182), it returns nil, and requests using standard configs will not have caching enabled.

The httpcache.NewTransportWrapper() must be applied to DefaultHTTPClient during its initialization in protocolstate.initDialers() when EnableHTTPCache is true.

🤖 Prompt for AI Agents
In `@pkg/protocols/http/httpclientpool/clientpool.go` around lines 226 - 228,
DefaultHTTPClient is left nil and the cache wrapper is only applied in
wrappedGet(), so Get() can return a nil client and miss caching; in
initDialers() ensure Dialers.DefaultHTTPClient is constructed (not nil) and that
when options.EnableHTTPCache && !configuration.DisableHTTPCache you apply the
httpcache.NewTransportWrapper() to the DefaultHTTPClient's transport (or set
retryableHttpOptions.WrapTransport accordingly) so the cache is present on the
default client; update initDialers() to create the http.Client (or retryable
client used elsewhere), attach the wrapper, and ensure Get()/wrappedGet() return
that initialized client.

@dwisiswant0 dwisiswant0 requested a review from Mzack9999 January 21, 2026 12:04
@tarunKoyalwar tarunKoyalwar removed their request for review February 5, 2026 10:36
@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/feat/http/httpcache branch from fd513ff to 3cc45c8 Compare March 5, 2026 05:54
@neo-by-projectdiscovery-dev
Copy link
Copy Markdown

neo-by-projectdiscovery-dev Bot commented Mar 5, 2026

Neo - PR Security Review

Medium: 4

Current PR state: 4 medium active findings.

Highlights

  • Medium: undefined in Makefile:31
  • Medium: undefined in cmd/integration-test/http.go:1793
  • Medium: undefined in cmd/integration-test/http.go:1825
Medium (4)
  • undefinedMakefile:31
    undefined
  • undefinedcmd/integration-test/http.go:1793
    undefined
  • undefinedcmd/integration-test/http.go:1825
    undefined
  • undefinedpkg/protocols/http/httpclientpool/clientpool.go:228
    undefined

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

Copy link
Copy Markdown
Contributor

@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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
pkg/js/devtools/bindgen/generator.go (1)

105-110: Optional: Document or pin build environment for bindgen determinism

Line 110 loads packages with default environment settings. While no build-constrained files currently exist in the target packages, consider documenting or explicitly pinning the environment (e.g., BuildFlags in packages.Config) if future changes introduce platform-specific code. This ensures generated bindings remain consistent across machines.

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

In `@pkg/js/devtools/bindgen/generator.go` around lines 105 - 110, The
packages.Load call uses a packages.Config (cfg) with default environment
settings; to make bindgen deterministic, update cfg to explicitly pin the build
environment (for example by setting cfg.BuildFlags and/or cfg.Env to a stable
GOOS/GOARCH and any necessary tags) and document this choice near the creation
of cfg, so future platform-specific files won’t change generated output;
reference the packages.Config instance named cfg and the packages.Load call to
apply this change and add a brief comment explaining the pinned values.
pkg/protocols/http/httpcache/httpcache.go (1)

31-35: Log LevelDB init failures before in-memory fallback.

Fallback is good, but the current path is silent on failure and makes cache persistence issues hard to diagnose in production.

🔎 Suggested improvement
 		cache, err = leveldbcache.New(cacheDir)
 		if err != nil {
+			gologger.Warning().Msgf("HTTP cache LevelDB init failed at %q: %v; using in-memory cache", cacheDir, err)
 			cache = httpcache.NewMemoryCache()
 		} else {
 			gologger.Verbose().Msgf("HTTP cache initialized at %q", cacheDir)
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/protocols/http/httpcache/httpcache.go` around lines 31 - 35, When
leveldbcache.New(cacheDir) fails the code silently falls back to
httpcache.NewMemoryCache(); change this to log the failure before falling back
by capturing the returned err and calling gologger.Error().Msgf (or Warn) with a
descriptive message that includes cacheDir and err; keep the existing
gologger.Verbose().Msgf("HTTP cache initialized at %q", cacheDir) for the
success path and only perform the in-memory fallback after logging the error
from leveldbcache.New.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/templates/templates_doc.go`:
- Around line 605-606: The description and line comment for
HTTPRequestDoc.Fields[22] currently say "DisableHTTPCache disables HTTP caching
for this request, overriding global cache settings." — update both the
Description and the encoder.LineComment for HTTPRequestDoc.Fields[22] to clarify
that DisableHTTPCache is a one-way opt-out: it disables caching for this request
but cannot re-enable caching if caching is globally disabled (i.e., it prevents
caching locally but does not override a global disable). Ensure the revised text
explicitly states the precedence: local opt-out allowed, local opt-in not
permitted when global cache is disabled.

---

Nitpick comments:
In `@pkg/js/devtools/bindgen/generator.go`:
- Around line 105-110: The packages.Load call uses a packages.Config (cfg) with
default environment settings; to make bindgen deterministic, update cfg to
explicitly pin the build environment (for example by setting cfg.BuildFlags
and/or cfg.Env to a stable GOOS/GOARCH and any necessary tags) and document this
choice near the creation of cfg, so future platform-specific files won’t change
generated output; reference the packages.Config instance named cfg and the
packages.Load call to apply this change and add a brief comment explaining the
pinned values.

In `@pkg/protocols/http/httpcache/httpcache.go`:
- Around line 31-35: When leveldbcache.New(cacheDir) fails the code silently
falls back to httpcache.NewMemoryCache(); change this to log the failure before
falling back by capturing the returned err and calling gologger.Error().Msgf (or
Warn) with a descriptive message that includes cacheDir and err; keep the
existing gologger.Verbose().Msgf("HTTP cache initialized at %q", cacheDir) for
the success path and only perform the in-memory fallback after logging the error
from leveldbcache.New.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 839d3329-7632-44bc-ac65-5251e1589582

📥 Commits

Reviewing files that changed from the base of the PR and between fd513ff and 3cc45c8.

⛔ Files ignored due to path filters (8)
  • .github/workflows/compat-checks.yaml is excluded by !**/*.yaml
  • .github/workflows/release.yaml is excluded by !**/*.yaml
  • .github/workflows/tests.yaml is excluded by !**/*.yaml
  • .goreleaser.yml is excluded by !**/*.yml
  • go.sum is excluded by !**/*.sum
  • integration_tests/protocols/http/disable-http-cache.yaml is excluded by !**/*.yaml
  • integration_tests/protocols/http/http-cache.yaml is excluded by !**/*.yaml
  • nuclei-jsonschema.json is excluded by !**/*.json
📒 Files selected for processing (12)
  • Makefile
  • SYNTAX-REFERENCE.md
  • cmd/integration-test/http.go
  • cmd/nuclei/main.go
  • go.mod
  • lib/tests/sdk_test.go
  • pkg/js/devtools/bindgen/generator.go
  • pkg/protocols/http/http.go
  • pkg/protocols/http/httpcache/httpcache.go
  • pkg/protocols/http/httpclientpool/clientpool.go
  • pkg/templates/templates_doc.go
  • pkg/types/types.go
✅ Files skipped from review due to trivial changes (1)
  • SYNTAX-REFERENCE.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • pkg/types/types.go
  • pkg/protocols/http/httpclientpool/clientpool.go
  • pkg/protocols/http/http.go
  • Makefile
  • cmd/integration-test/http.go
  • cmd/nuclei/main.go

Comment thread pkg/protocols/http/httpcache/httpcache.go
Comment on lines +605 to +606
HTTPRequestDoc.Fields[22].Description = "DisableHTTPCache disables HTTP caching for this request, overriding global cache settings."
HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "DisableHTTPCache disables HTTP caching for this request, overriding global cache settings."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clarify disable-http-cache precedence semantics.

The current text implies full override behavior. disable-http-cache should be documented as a one-way opt-out (cannot re-enable cache when globally disabled).

✏️ Suggested wording update
- HTTPRequestDoc.Fields[22].Description = "DisableHTTPCache disables HTTP caching for this request, overriding global cache settings."
- HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "DisableHTTPCache disables HTTP caching for this request, overriding global cache settings."
+ HTTPRequestDoc.Fields[22].Description = "DisableHTTPCache disables HTTP caching for this request. If global HTTP cache is disabled, this field cannot enable it."
+ HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "DisableHTTPCache disables HTTP caching for this request."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/templates/templates_doc.go` around lines 605 - 606, The description and
line comment for HTTPRequestDoc.Fields[22] currently say "DisableHTTPCache
disables HTTP caching for this request, overriding global cache settings." —
update both the Description and the encoder.LineComment for
HTTPRequestDoc.Fields[22] to clarify that DisableHTTPCache is a one-way opt-out:
it disables caching for this request but cannot re-enable caching if caching is
globally disabled (i.e., it prevents caching locally but does not override a
global disable). Ensure the revised text explicitly states the precedence: local
opt-out allowed, local opt-in not permitted when global cache is disabled.

@dwisiswant0
Copy link
Copy Markdown
Member Author

@coderabbitai create an issue for this (CI error):

[INF] nuclei-templates are not installed, installing...
panic: cause="GET https://api.github.com/repos/projectdiscovery/nuclei-templates/releases/latest: 403 API rate limit exceeded for 52.176.19.195. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.) [rate reset in 55m25s]" chain="hit github ratelimit while downloading latest release; failed to install templates at /home/runner/nuclei-templates"

goroutine 1 [running]:
main.main()
	/home/runner/work/nuclei/nuclei/examples/simple/simple.go:15 +0x253
exit status 2

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 5, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh issue create \
  --repo projectdiscovery/nuclei \
  --title "CI: panic on GitHub API rate limit when installing nuclei-templates" \
  --assignee dwisiswant0 \
  --body "## Description

During CI, the process panics instead of handling the GitHub API rate limit error gracefully when attempting to install \`nuclei-templates\`.

## Error

\`\`\`
[INF] nuclei-templates are not installed, installing...
panic: cause=\"GET https://api.github.com/repos/projectdiscovery/nuclei-templates/releases/latest: 403 API rate limit exceeded for 52.176.19.195. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.) [rate reset in 55m25s]\" chain=\"hit github ratelimit while downloading latest release; failed to install templates at /home/runner/nuclei-templates\"

goroutine 1 [running]:
main.main()
	/home/runner/work/nuclei/nuclei/examples/simple/simple.go:15 +0x253
exit status 2
\`\`\`

## Root Cause

- The GitHub API returns a **403 rate limit** response when fetching the latest \`nuclei-templates\` release from an unauthenticated runner IP.
- The application **panics** instead of returning or logging a recoverable error.

## Expected Behavior

- The application should handle the rate limit error gracefully (e.g., return an error, log a warning, retry with backoff, or use an authenticated token).
- CI runners should use an authenticated GitHub token (\`GITHUB_TOKEN\`) when making API calls to avoid hitting the unauthenticated rate limit.

## References

- PR: https://github.com/projectdiscovery/nuclei/pull/6746 (comment where this was reported)

Reported by `@dwisiswant0`."

Length of output: 54


@dwisiswant0: Done! I've created the issue here: #7118

The issue covers two aspects of the problem:

  1. The GitHub API rate limit (403) being hit on unauthenticated CI runners when fetching the latest nuclei-templates release.
  2. The application panicking instead of handling the error gracefully — which is the more critical fix, as the rate limit itself can be mitigated by using GITHUB_TOKEN in CI.

Copy link
Copy Markdown
Member

@Mzack9999 Mzack9999 left a comment

Choose a reason for hiding this comment

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

  • Merge Conflicts
  • Failing Tests

dwisiswant0 and others added 10 commits April 1, 2026 15:07
* wrap HTTP transports with sandrolain/httpcache
  and expose global `--no-http-cache` flag.
* allow templates to set `disable-http-cache`.
* bump Go to 1.25.7.

Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
Signed-off-by: Dwi Siswanto <git@dw1.io>
@dwisiswant0 dwisiswant0 force-pushed the dwisiswant0/feat/http/httpcache branch from 3cc45c8 to 834fae0 Compare April 1, 2026 08:10
Sign up for free to 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.

[FEATURE] RFC 9111 Compliant HTTP Response Caching

2 participants