Skip to content

fix(ztls,auto): fix nil dereference guards and retry counter logic#975

Merged
Mzack9999 merged 1 commit into
projectdiscovery:devfrom
cherry-bisht:fix-nil-guard-and-retry-counter
May 22, 2026
Merged

fix(ztls,auto): fix nil dereference guards and retry counter logic#975
Mzack9999 merged 1 commit into
projectdiscovery:devfrom
cherry-bisht:fix-nil-guard-and-retry-counter

Conversation

@cherry-bisht
Copy link
Copy Markdown

@cherry-bisht cherry-bisht commented May 10, 2026

Changes

ztls: nil dereference guards

All hl field accesses were moved inside the hl != nil check to prevent
potential nil pointer dereference when the handshake log is unavailable.
TLSChain processing is also moved inside the ServerCertificates nil
check to prevent dereference when no certificates are present.

auto: retry counter fix

The shared retryCounter was incremented by all three clients in a single
loop pass, meaning at default settings (Retries=1, forced to 3) each
client got exactly one attempt and the loop exited — making retries
effectively impossible. Fixed to use a standard for i := 0; i < maxRetries
loop where each full pass tries all available clients independently.

Testing

  • go build ./cmd/tlsx/
  • go test ./pkg/tlsx/clients/...
  • Pre-existing test failure in TestClientCertRequired is unrelated to
    these changes (fails on main too)

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Enhanced TLS handshake processing with improved null-safety checks to prevent errors when processing certificate data.
  • Refactoring

    • Adjusted TLS connection retry logic for improved performance, reducing default retry attempts when not explicitly configured.
    • Improved handshake field extraction with better organization and robustness.

Review Change Stack

@neo-by-projectdiscovery-dev
Copy link
Copy Markdown

neo-by-projectdiscovery-dev Bot commented May 10, 2026

Neo - PR Security Review

No security issues found

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6ae64889-3868-4278-82db-c79c2bd137fb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR improves connection handling resilience in tlsx by refactoring retry logic and strengthening nil-pointer safety. The retry mechanism now uses an indexed for loop with configurable max retries defaulting to 1, and handshake log processing is reorganized with explicit nil guards at multiple levels to prevent unsafe iteration.

Changes

Connection Handling Resilience

Layer / File(s) Summary
Retry Loop Refactoring
pkg/tlsx/auto/auto.go
Retry setup changes from retryCounter-based control to indexed for i := 0; i < maxRetries loop. Default maxRetries becomes 1 when c.options.Retries <= 0, and per-engine failure increments are removed.
Handshake Log Safety
pkg/tlsx/ztls/ztls.go
All handshake log field extraction moves under hl != nil guard. Certificate response building and TLS chain population are nested under hl.ServerCertificates != nil to prevent nil iteration.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A rabbit hops through retry loops so clean,
With defaults now gentle, not forced in between,
And handshake logs guarded with care from the start,
Nil-checks nested neatly—a safety-first art! 🎯

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: fixing nil dereference guards in ztls and retry counter logic in auto, which matches the core bug fixes detailed in the PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@cherry-bisht
Copy link
Copy Markdown
Author

also flagging this ,
in the old code, it forced maxRetries to a minimum of 3 regardless of user config (Retries=1 would still result in 3 retries). This new code removes the implicit floor and defaults to 1 only when Retries <= 0. Retries now work as user configured. Flagging this because the function was doing something which it shouldnt be

@cherry-bisht
Copy link
Copy Markdown
Author

cherry-bisht commented May 10, 2026

Also flagging this: in the old code, ClientHello and ServerHello were gated behind the TLSChain option, so if TLSChain was not enabled, these fields would never be populated even if the user asked for them. Moved them out to the top-level hl != nil check so they work correctly regardless of TLSChain. Flagging this because these fields had nothing to do with TLSChain in the first place.

@Mzack9999 Mzack9999 force-pushed the fix-nil-guard-and-retry-counter branch from ac2bbdf to a0da435 Compare May 22, 2026 08:25
@Mzack9999 Mzack9999 changed the base branch from main to dev May 22, 2026 08:25
@Mzack9999
Copy link
Copy Markdown
Member

Thanks @cherry-bisht, the ztls nil-guard fix is a real catch and we kept that part as-is. Force-pushed a cleanup that drops the auto.go retry change and retargeted the PR to dev.

On the retry counter: the original loop reads "Retries = total connection attempts shared across ctls/ztls/openssl", and at the defaults that downstream tools actually use (tlsx -retry 3, nuclei propagating user's -retries, aurora hardcoding 3) it does exactly 3 attempts per host. Switching to "Retries per engine" means those same callers would jump to 9 attempts per host (3 engines x 3 retries), which is a meaningful jump in scan traffic without an opt-in. The counter is named confusingly but it isn't broken in practice, so we'd rather leave it alone for now.

Happy to revisit the retry semantics in a follow-up if there's appetite, with the per-engine vs total-budget trade-off called out explicitly in the release notes.

@Mzack9999 Mzack9999 merged commit d1e4fe4 into projectdiscovery:dev May 22, 2026
19 of 22 checks passed
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.

2 participants