Skip to content

fix: use safe type assertions in HTTP operators to prevent panics#7223

Closed
sandiyochristan wants to merge 1 commit intoprojectdiscovery:devfrom
sandiyochristan:fix/safe-type-assertions-in-http-operators
Closed

fix: use safe type assertions in HTTP operators to prevent panics#7223
sandiyochristan wants to merge 1 commit intoprojectdiscovery:devfrom
sandiyochristan:fix/safe-type-assertions-in-http-operators

Conversation

@sandiyochristan
Copy link
Contributor

@sandiyochristan sandiyochristan commented Mar 14, 2026

Proposed Changes

The HTTP protocol operators contain 4 unsafe type assertions that will panic and crash the entire nuclei process if the internal event data map contains unexpected types. This is a reliability and denial-of-service concern — a malformed HTTP response or corrupted internal state triggers an unrecoverable panic instead of graceful error handling.

Root Cause

Go type assertions of the form x.(Type) without a second ok return value cause a runtime panic if the value is not of the expected type. The HTTP operators use this unsafe pattern in several places where the data originates from HTTP responses (which are attacker-controlled in a scanning context).

Unsafe Assertions Fixed

Location Before (panics) After (safe)
Line 34 data["response"].(string) responseStr, _ := data["response"].(string)
Line 170 value.(bool) isGlobalMatchers, _ = value.(bool)
Line 174 value.(string) analyzerDetails, _ = value.(string)
Line 185 wrapped.InternalEvent["template-info"].(model.Info) info, _ := wrapped.InternalEvent["template-info"].(model.Info)

Crash Scenarios

Scenario 1: Malformed response processing

  • A target server sends a response that causes the response key in the data map to be stored as []byte instead of string
  • Line 34: data["response"].(string) panics → nuclei crashes
  • All other scan targets in the queue are lost

Scenario 2: Corrupted internal event during concurrent execution

  • Under high concurrency, a race condition or edge case causes template-info to be missing from the internal event map
  • Line 185: wrapped.InternalEvent["template-info"].(model.Info) panics on nil interface → nuclei crashes
  • This is the most dangerous assertion since it doesn't even check if the key exists first

Scenario 3: Plugin/extension type mismatch

  • A custom protocol extension or workflow step stores a non-bool value under the global-matchers key
  • Line 170: value.(bool) panics → nuclei crashes

The Fix

All 4 assertions now use Go's safe type assertion pattern value, ok := x.(Type) which returns the zero value instead of panicking when the type doesn't match. This is the idiomatic Go approach and is already used correctly elsewhere in the same file (e.g., line 52-60 in getStatusCode).

Files Changed

  • pkg/protocols/http/operators.go — 4 unsafe type assertions replaced with safe comma-ok pattern

Security Impact

  • CWE-248: Uncaught Exception (Go panic from type assertion)
  • Severity: Medium
  • Attack Vector: Malicious target server sends response that causes type mismatch in internal event data → nuclei crashes
  • Impact: Denial of Service — entire scan terminates, all queued targets are lost

Proof

The fix follows the exact same safe assertion pattern already used in the same file:

// Line 52-60 (existing safe pattern)
func getStatusCode(data map[string]interface{}) (int, bool) {
    statusCodeValue, ok := data["status_code"]
    if !ok {
        return 0, false
    }
    statusCode, ok := statusCodeValue.(int)  // Safe: checks ok
    if !ok {
        return 0, false
    }
    return statusCode, true
}

Checklist

  • PR created against dev branch
  • All checks passed (lint, unit/integration/regression tests)
  • Minimal change — only type assertion patterns modified, no logic changes
  • Follows existing safe patterns already used in the same file
  • Zero-value fallback behavior is safe for all 4 cases (empty string, false, zero-value struct)

Summary by CodeRabbit

  • Bug Fixes
    • Improved robustness of HTTP response handling by safely managing type assertions, preventing potential crashes when response data doesn't match expected types.

Unsafe type assertions without ok checks cause panics when the
data map contains unexpected types. This can crash the scanner
when processing malformed responses or corrupted internal state.
@auto-assign auto-assign bot requested a review from dogancanbakir March 14, 2026 23:02
@neo-by-projectdiscovery-dev
Copy link

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

Neo - PR Security Review

No security issues found

Highlights

  • Converts 4 unsafe type assertions to safe comma-ok pattern to prevent panics
  • Uses zero-value fallbacks (empty string, false, zero-value struct) when type assertions fail
  • No attacker-controlled execution paths or exploitable vulnerabilities introduced
Hardening Notes
  • The PR fixes CWE-248 (Uncaught Exception / panic from type assertion), which is a reliability issue rather than an exploitable security vulnerability
  • All type assertion failures now use safe zero values that are handled correctly by downstream functions
  • CreateStatusCodeSnippet at line 35 safely handles empty string by checking for 'HTTP/' prefix before string operations

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 14, 2026

Walkthrough

The changes modify type assertion handling in HTTP operator code, replacing direct assertions with safer comma-ok patterns to prevent panics when types don't match expected values during response handling and event creation.

Changes

Cohort / File(s) Summary
Type Assertion Safety
pkg/protocols/http/operators.go
Replaced direct type assertions with comma-ok patterns in StatusMatcher and MakeResultEventItem to gracefully handle type mismatches. Added defensive handling for response, boolean, string, and template-info fields.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰✨ With whiskers twitched and paws precise,
We caught those panics—oh how nice!
No more crashes when types don't align,
Safe assertions make code divine! 🛡️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: use safe type assertions in HTTP operators to prevent panics' directly and clearly describes the main change: replacing unsafe type assertions with safe ones to prevent runtime panics in HTTP operators.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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
📝 Coding Plan
  • Generate coding plan for human review comments

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

🧹 Nitpick comments (2)
pkg/protocols/http/operators.go (2)

34-35: Prefer types.ToString here to preserve snippets for non-string responses.

Line 34 is panic-safe now, but it turns non-string values into an empty snippet. Converting via types.ToString keeps behavior resilient without losing snippet content.

Proposed tweak
-		responseStr, _ := data["response"].(string)
+		responseStr := types.ToString(data["response"])
 		return matcher.Result(matcher.MatchStatusCode(statusCode)), []string{responsehighlighter.CreateStatusCodeSnippet(responseStr, statusCode)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/protocols/http/operators.go` around lines 34 - 35, The code is using a
direct string type assertion on data["response"] (responseStr :=
data["response"].(string)) which drops non-string snippet content; replace that
assertion by converting via types.ToString(data["response"]) and pass the
resulting string into responsehighlighter.CreateStatusCodeSnippet so non-string
responses retain their snippet content while keeping the panic-safe behavior in
the matcher.Result/matcher.MatchStatusCode flow.

183-187: Use a fallback for Info to avoid losing template metadata on type mismatch.

Line 183 avoids panic, but a failed assertion yields zero-value model.Info, which can degrade result quality. Consider defaulting to request.options.TemplateInfo.

Proposed tweak
-	info, _ := wrapped.InternalEvent["template-info"].(model.Info)
+	info, ok := wrapped.InternalEvent["template-info"].(model.Info)
+	if !ok {
+		info = request.options.TemplateInfo
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/protocols/http/operators.go` around lines 183 - 187, When building the
output.ResultEvent, don't rely solely on the type assertion info, because
wrapped.InternalEvent["template-info"].(model.Info) can yield a zero-value on
mismatch; instead check the assertion result and if it fails use the
request.options.TemplateInfo as a fallback for the Info field. Update the
construction of output.ResultEvent (the TemplateID/TemplatePath/Info block where
wrapped.InternalEvent is read) to perform a safe type assertion (ok pattern) and
assign request.options.TemplateInfo when ok is false or the value is empty so
template metadata isn't lost.
🤖 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/protocols/http/operators.go`:
- Around line 34-35: The code is using a direct string type assertion on
data["response"] (responseStr := data["response"].(string)) which drops
non-string snippet content; replace that assertion by converting via
types.ToString(data["response"]) and pass the resulting string into
responsehighlighter.CreateStatusCodeSnippet so non-string responses retain their
snippet content while keeping the panic-safe behavior in the
matcher.Result/matcher.MatchStatusCode flow.
- Around line 183-187: When building the output.ResultEvent, don't rely solely
on the type assertion info, because
wrapped.InternalEvent["template-info"].(model.Info) can yield a zero-value on
mismatch; instead check the assertion result and if it fails use the
request.options.TemplateInfo as a fallback for the Info field. Update the
construction of output.ResultEvent (the TemplateID/TemplatePath/Info block where
wrapped.InternalEvent is read) to perform a safe type assertion (ok pattern) and
assign request.options.TemplateInfo when ok is false or the value is empty so
template metadata isn't lost.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f78fd870-b707-4ba7-a9c5-8242ae125f2a

📥 Commits

Reviewing files that changed from the base of the PR and between 979c867 and aa002c2.

📒 Files selected for processing (1)
  • pkg/protocols/http/operators.go

Copy link
Member

@dwisiswant0 dwisiswant0 left a comment

Choose a reason for hiding this comment

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

Please file an issue before submitting fix patches.

Include reproduction steps as per the template and the exact nuclei command that crashes (or custom runner PoC for Nuclei SDK). The reproduction must be based on a realistic execution path that is fully concrete and reproducible.

Thanks!

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