Skip to content

Replace exec() in responsetime condition with safe operator mapping#1335

Open
Prajwal5755 wants to merge 6 commits intoOWASP:masterfrom
Prajwal5755:remove-exec-responsetime
Open

Replace exec() in responsetime condition with safe operator mapping#1335
Prajwal5755 wants to merge 6 commits intoOWASP:masterfrom
Prajwal5755:remove-exec-responsetime

Conversation

@Prajwal5755
Copy link

Proposed change

This PR replaces the use of 'exec()' in the 'responsetime' condition exvaluation inside 'response_conditions_matched()' function with a safe operator mapping using Python's built-in 'operator' module

Previously, dynamic code execution was used to evaluate comparision operators, which:

  • Introduced unnecessary security risk
  • Reduced readability
  • Made debugger harder

This change:

  • Removes dynamic execution
  • Uses explicit operator mapping like('operator.eq')
  • Validates input format before evaluation

More importantly no functional behavior has been changed.

Type of change

  • New core framework functionality
  • Bugfix (non-breaking change which fixes an issue)
  • [ x ] Code refactoring without any functionality changes
  • New or existing module/payload change
  • Documentation/localization improvement
  • Test coverage improvement
  • Dependency upgrade
  • Other improvement (best practice, cleanup, optimization, etc)

Checklist

  • [ x ] I've followed the contributing guidelines
  • I've run make pre-commit, it didn't generate any changes
  • I've run make test, all tests passed locally

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 1, 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

Replaces exec-based responsetime evaluation with a safe operator-driven approach: adds an OPERATORS mapping, parses a two-token operator+value string, validates numeric value, applies the operator to response["responsetime"], and sets condition_results["responsetime"] to the matched value or [] on invalid/non-matching input.

Changes

Cohort / File(s) Summary
HTTP responsetime evaluation
nettacker/core/lib/http.py
Adds import operator and a public OPERATORS mapping; replaces exec-based evaluation with parsing of "operator value" (e.g., "> 0.5"), float validation, and using the mapped operator function to compare response["responsetime"]; sets condition_results["responsetime"] to actual time on match or [] otherwise.
New slow-endpoint scan profile
nettacker/modules/scan/slow_endpoint.yaml
Introduces a new YAML scan profile slow_endpoint_scan defining HTTP payload settings, a fuzzer input for slow endpoints, and response conditions (responsetime > 3, URL regex .*, status codes `200

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 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
Title check ✅ Passed The title accurately describes the main change: replacing exec() with safe operator mapping for responsetime condition evaluation.
Description check ✅ Passed The description is related to the main code change in http.py but does not mention the new slow_endpoint.yaml module that was also added, creating an inconsistency with the commit message.

✏️ 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
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

🧹 Nitpick comments (1)
nettacker/core/lib/http.py (1)

3-8: Import ordering: operator should be placed alphabetically among stdlib imports.

The operator module import should come after copy and before random to maintain alphabetical ordering enforced by isort.

Suggested fix
 import asyncio
 import copy
+import operator
 import random
 import re
 import time
-import operator
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nettacker/core/lib/http.py` around lines 3 - 8, The stdlib imports in
nettacker/core/lib/http.py are out of alphabetical order—move the import of
operator so it appears after copy and before random to satisfy isort; update the
import block (imports: asyncio, copy, operator, random, re, time) leaving
everything else unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nettacker/core/lib/http.py`:
- Around line 85-104: Replace the per-call local operators dict with a
module-level constant OPERATORS (UPPER_SNAKE_CASE) defined after imports and use
it instead of recreating operators inside the block; remove the redundant inner
check "if len(operator_value)==2 and operator_value[0] in operators" (since the
outer validation already ensures this), ensure proper PEP 8 spacing around
operators in the lines that assign operator_value and compare, and fix the typo
in the comment from "respnse" to "response"; keep using
response["responsetime"], value and set condition_results["responsetime"]
appropriately on success/failure.

---

Nitpick comments:
In `@nettacker/core/lib/http.py`:
- Around line 3-8: The stdlib imports in nettacker/core/lib/http.py are out of
alphabetical order—move the import of operator so it appears after copy and
before random to satisfy isort; update the import block (imports: asyncio, copy,
operator, random, re, time) leaving everything else unchanged.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b759d79 and c3a7527.

📒 Files selected for processing (1)
  • nettacker/core/lib/http.py

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nettacker/core/lib/http.py`:
- Around line 85-86: Guard the value before calling .split(): check that
conditions[condition] is a str (e.g., with isinstance(conditions[condition],
str)) before doing operator_value = conditions[condition].split(); if it isn't a
str, set operator_value = [] or continue so the subsequent check
(len(operator_value) == 2 and operator_value[0] in OPERATORS) won't raise
AttributeError. Update the code around operator_value, conditions and OPERATORS
to handle non-string condition values safely.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3a7527 and 351cecb.

📒 Files selected for processing (1)
  • nettacker/core/lib/http.py

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
nettacker/core/lib/http.py (1)

90-90: Use the already-guarded local value for parsing.

Line 90 can use value_str.split() (from Line 85) instead of re-reading conditions[condition]; it keeps the guard path tighter and avoids redundant lookup.

Proposed cleanup
-            operator_value = conditions[condition].split()
+            operator_value = value_str.split()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nettacker/core/lib/http.py` at line 90, The code redundantly re-reads
conditions[condition] when parsing operators; use the already-guarded local
variable value_str (assigned earlier) instead: replace the use of
conditions[condition].split() with value_str.split() so operator_value is
derived from the validated local value in the function that handles condition
parsing (look for operator_value, value_str, condition in the HTTP parsing
logic).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nettacker/core/lib/http.py`:
- Line 94: The if-statement line with
OPERATORS[operator_value[0]](response["responsetime"], value) is too long; to
fix, move the inline comment above the if or wrap the condition across multiple
lines so it stays under 99 chars—update the line in nettacker/core/lib/http.py
around the if that uses OPERATORS, operator_value, response, and value, placing
the comment on its own line or splitting the call into multiple lines (e.g.,
break after OPERATORS[...] and before the parentheses) to satisfy the project's
line-length rules.

---

Nitpick comments:
In `@nettacker/core/lib/http.py`:
- Line 90: The code redundantly re-reads conditions[condition] when parsing
operators; use the already-guarded local variable value_str (assigned earlier)
instead: replace the use of conditions[condition].split() with value_str.split()
so operator_value is derived from the validated local value in the function that
handles condition parsing (look for operator_value, value_str, condition in the
HTTP parsing logic).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 351cecb and 3a5fd58.

📒 Files selected for processing (1)
  • nettacker/core/lib/http.py

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 (1)
nettacker/core/lib/http.py (1)

85-90: Redundant dictionary access: use value_str instead of re-accessing conditions[condition].

Line 85 assigns value_str = conditions[condition], but line 90 accesses conditions[condition].split() again instead of using the already-validated value_str. This is both redundant and inconsistent with the type guard pattern above it.

♻️ Proposed fix
         if condition == "responsetime":
             value_str = conditions[condition]
             if not isinstance(value_str, str):
                 condition_results["responsetime"] = []
                 continue

-            operator_value = conditions[condition].split()
+            operator_value = value_str.split()
             if len(operator_value) == 2 and operator_value[0] in OPERATORS:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nettacker/core/lib/http.py` around lines 85 - 90, The code redundantly
re-reads conditions[condition] after validating it; change the operator_value
assignment to use the already-validated local variable value_str (i.e., set
operator_value = value_str.split()) in the function where value_str,
condition_results and operator_value are used (look for the block that assigns
value_str = conditions[condition] and then computes operator_value) so the type
guard is consistent and the extra dictionary access is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@nettacker/core/lib/http.py`:
- Around line 85-90: The code redundantly re-reads conditions[condition] after
validating it; change the operator_value assignment to use the already-validated
local variable value_str (i.e., set operator_value = value_str.split()) in the
function where value_str, condition_results and operator_value are used (look
for the block that assigns value_str = conditions[condition] and then computes
operator_value) so the type guard is consistent and the extra dictionary access
is removed.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a5fd58 and 0aab168.

📒 Files selected for processing (1)
  • nettacker/core/lib/http.py

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
nettacker/modules/scan/slow_endpoint.yaml (1)

44-54: Response conditions are correctly formatted.

The responsetime: "> 3" format correctly matches the new safe operator-based parsing introduced in nettacker/core/lib/http.py. The status_code and url conditions use the expected nested structure with regex and reverse keys.

Minor observation: The url condition with regex: .* will match any URL, making it effectively a pass-through. If this is intentional (to ensure the URL field exists), it's fine. Otherwise, you could remove it since condition_type: and with fewer conditions achieves the same result.

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

In `@nettacker/modules/scan/slow_endpoint.yaml` around lines 44 - 54, The response
conditions block uses the new operator-based parsing correctly (responsetime: ">
3") and nested regex structure for status_code and url; if the url: regex: .*
entry is only intended to assert presence it can stay, otherwise remove the url
condition from the response block to avoid a no-op rule—update the response
section (look for the response block and keys responsetime, status_code, url,
and condition_type) to either document the intent for url: regex: .* or delete
that url condition to simplify the AND condition set.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nettacker/modules/scan/slow_endpoint.yaml`:
- Around line 38-42: The schema/port mismatch in slow_endpoint.yaml (keys schema
and ports) causes false positives because schema is "http" while ports includes
443; update the YAML to either add "https" to the schema list and ensure HTTPS
requests set ssl: true or are handled conditionally for ports == 443, or remove
port 443 from the ports list if only plain HTTP scanning (schema: "http") is
intended—adjust the handling around the schema and ssl flag used by the scanner
accordingly.

---

Nitpick comments:
In `@nettacker/modules/scan/slow_endpoint.yaml`:
- Around line 44-54: The response conditions block uses the new operator-based
parsing correctly (responsetime: "> 3") and nested regex structure for
status_code and url; if the url: regex: .* entry is only intended to assert
presence it can stay, otherwise remove the url condition from the response block
to avoid a no-op rule—update the response section (look for the response block
and keys responsetime, status_code, url, and condition_type) to either document
the intent for url: regex: .* or delete that url condition to simplify the AND
condition set.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 785085af-5ada-47b9-975a-533ce2ce7302

📥 Commits

Reviewing files that changed from the base of the PR and between 0aab168 and 89977ac.

📒 Files selected for processing (1)
  • nettacker/modules/scan/slow_endpoint.yaml

Comment on lines +38 to +42
schema:
- "http"
ports:
- 80
- 443
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Protocol/port mismatch will cause false positives.

The schema is set to only "http" while ports includes 443. HTTP requests to port 443 will fail or timeout because port 443 expects HTTPS/TLS connections. This will likely trigger false positives since the connection failures or TLS handshake timeouts may exceed 3 seconds and be incorrectly flagged as "slow endpoints."

Consider either:

  • Adding "https" to the schema list and adjusting ssl: true for HTTPS requests, or
  • Removing port 443 from the ports list if only HTTP scanning is intended.
🔧 Proposed fix: Add HTTPS schema
             schema:
               - "http"
+              - "https"
             ports:
               - 80
               - 443

Note: If adding HTTPS, you may also want to set ssl: true or handle it conditionally for HTTPS requests.

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

In `@nettacker/modules/scan/slow_endpoint.yaml` around lines 38 - 42, The
schema/port mismatch in slow_endpoint.yaml (keys schema and ports) causes false
positives because schema is "http" while ports includes 443; update the YAML to
either add "https" to the schema list and ensure HTTPS requests set ssl: true or
are handled conditionally for ports == 443, or remove port 443 from the ports
list if only plain HTTP scanning (schema: "http") is intended—adjust the
handling around the schema and ssl flag used by the scanner accordingly.

@Gauravsharma2040
Copy link
Contributor

Hi @Prajwal5755, thanks for working on this this is an important fix 👍

I noticed this PR addresses the same root cause as the issue I recently opened (#1408), which also proposes replacing the exec()-based evaluation in response_conditions_matched() with a safe operator mapping.

To avoid duplicate work and review conflicts, it might be helpful to open an issue before submitting a PR for core engine changes, especially in shared components like http.py. That makes it easier to coordinate fixes and prevents multiple PRs targeting the same code path at the same time.

In this case both approaches are valid, and it may make sense to merge the ideas from both PRs into a single fix (for example, using the operator module while keeping the additional guards)
Thanks again for the contribution

@Prajwal5755
Copy link
Author

Hi @Prajwal5755, thanks for working on this this is an important fix 👍

I noticed this PR addresses the same root cause as the issue I recently opened (#1408), which also proposes replacing the exec()-based evaluation in response_conditions_matched() with a safe operator mapping.

To avoid duplicate work and review conflicts, it might be helpful to open an issue before submitting a PR for core engine changes, especially in shared components like http.py. That makes it easier to coordinate fixes and prevents multiple PRs targeting the same code path at the same time.

In this case both approaches are valid, and it may make sense to merge the ideas from both PRs into a single fix (for example, using the operator module while keeping the additional guards) Thanks again for the contribution

Hi, thanks for pointing this out and for opening issue #1408.

I wasn’t aware of the issue earlier, but I see both approaches are addressing the same root cause. In my PR I’ve also replaced exec() with a safer operator-based approach.

I agree it’s good to align solutions and avoid duplication. I’m open to making changes if needed based on maintainer feedback.

Thanks for the suggestion, I’ll make sure to check for existing issues before submitting similar changes going forward.

@Gauravsharma2040
Copy link
Contributor

Hi @Prajwal5755, thanks for working on this this is an important fix 👍
I noticed this PR addresses the same root cause as the issue I recently opened (#1408), which also proposes replacing the exec()-based evaluation in response_conditions_matched() with a safe operator mapping.
To avoid duplicate work and review conflicts, it might be helpful to open an issue before submitting a PR for core engine changes, especially in shared components like http.py. That makes it easier to coordinate fixes and prevents multiple PRs targeting the same code path at the same time.
In this case both approaches are valid, and it may make sense to merge the ideas from both PRs into a single fix (for example, using the operator module while keeping the additional guards) Thanks again for the contribution

Hi, thanks for pointing this out and for opening issue #1408.

I wasn’t aware of the issue earlier, but I see both approaches are addressing the same root cause. In my PR I’ve also replaced exec() with a safer operator-based approach.

I agree it’s good to align solutions and avoid duplication. I’m open to making changes if needed based on maintainer feedback.

Thanks for the suggestion, I’ll make sure to check for existing issues before submitting similar changes going forward.
Just a small note, since this PR is fixing the same issue discussed in #1408, it might help to link the issue in the PR description (for example with Fixes #1408 or Related to #1408).
That usually makes it easier for reviewers to see the context and keeps the discussion in one place, especially since there are multiple PRs touching the same part of http.py.

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