From c5070ea3255ec8b70c1a6f7de6e984f7d090930f Mon Sep 17 00:00:00 2001 From: Rakshak05 <159248180+Rakshak05@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:04:44 +0530 Subject: [PATCH 1/2] Resolves issue-#1808 --- backend/secuscan/config.py | 11 +++++++++ backend/secuscan/models.py | 13 ++++++++++- testing/backend/unit/test_config_settings.py | 23 +++++++++++++++++++ .../backend/unit/test_sandbox_config_model.py | 19 +++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/backend/secuscan/config.py b/backend/secuscan/config.py index 757ca3ac9..249c4b761 100644 --- a/backend/secuscan/config.py +++ b/backend/secuscan/config.py @@ -8,8 +8,11 @@ from pydantic_settings import BaseSettings import base64 import hashlib +import logging import os +logger = logging.getLogger(__name__) + PROJECT_ROOT = Path(__file__).resolve().parent.parent @@ -199,6 +202,14 @@ class Config: env_prefix = "SECUSCAN_" case_sensitive = False + @field_validator("sandbox_timeout", "parser_sandbox_timeout_seconds") + @classmethod + def validate_sandbox_timeouts(cls, v: int) -> int: + if v is None or v <= 0: + logger.warning("Refusing falsy or non-positive sandbox timeout: %s. A non-zero timeout is required.", v) + raise ValueError("Timeout settings must be a positive non-zero integer") + return v + @field_validator( "cors_allowed_origins", "cors_allowed_methods", diff --git a/backend/secuscan/models.py b/backend/secuscan/models.py index 75661c3ab..3f80e0ab8 100644 --- a/backend/secuscan/models.py +++ b/backend/secuscan/models.py @@ -4,8 +4,11 @@ from typing import Optional, Dict, Any, List, Annotated from datetime import datetime -from pydantic import BaseModel, Field, RootModel +from pydantic import BaseModel, Field, RootModel, field_validator from enum import Enum +import logging + +logger = logging.getLogger(__name__) MAX_BULK_DELETE = 500 @@ -33,6 +36,14 @@ class SandboxConfig(BaseModel): max_output_bytes: int = Field(default=5_242_880, description="Max bytes captured from stdout/stderr") allow_network: bool = Field(default=True, description="Whether subprocess can make network calls") + @field_validator("timeout_seconds") + @classmethod + def validate_timeout_seconds(cls, v: int) -> int: + if v is None or v <= 0: + logger.warning("Refusing falsy or non-positive sandbox timeout_seconds: %s. A non-zero timeout is required.", v) + raise ValueError("timeout_seconds must be a positive non-zero integer") + return v + class SandboxViolation(Exception): """Raised when sandbox constraints are violated.""" diff --git a/testing/backend/unit/test_config_settings.py b/testing/backend/unit/test_config_settings.py index 45fdd5c99..8bd8ee50f 100644 --- a/testing/backend/unit/test_config_settings.py +++ b/testing/backend/unit/test_config_settings.py @@ -286,3 +286,26 @@ def test_sandbox_settings_env_override(): assert s.sandbox_timeout == 30 assert s.sandbox_memory_mb == 128 assert s.sandbox_allow_network is False + + +def test_sandbox_settings_validation_refuses_zero(): + """ValidationError is raised when sandbox_timeout or parser_sandbox_timeout_seconds is 0.""" + from pydantic import ValidationError + import pytest + with pytest.raises(ValidationError) as exc_info: + Settings(sandbox_timeout=0) + assert "Timeout settings must be a positive non-zero integer" in str(exc_info.value) + + with pytest.raises(ValidationError) as exc_info: + Settings(parser_sandbox_timeout_seconds=0) + assert "Timeout settings must be a positive non-zero integer" in str(exc_info.value) + + +def test_sandbox_settings_validation_refuses_negative(): + """ValidationError is raised when sandbox_timeout or parser_sandbox_timeout_seconds is negative.""" + from pydantic import ValidationError + import pytest + with pytest.raises(ValidationError) as exc_info: + Settings(sandbox_timeout=-10) + assert "Timeout settings must be a positive non-zero integer" in str(exc_info.value) + diff --git a/testing/backend/unit/test_sandbox_config_model.py b/testing/backend/unit/test_sandbox_config_model.py index dfc7a6232..56d053b20 100644 --- a/testing/backend/unit/test_sandbox_config_model.py +++ b/testing/backend/unit/test_sandbox_config_model.py @@ -81,3 +81,22 @@ def test_repr_includes_all_fields(self): repr_str = repr(config) assert "45" in repr_str assert "128" in repr_str + + +class TestSandboxConfigValidation: + def test_timeout_seconds_refuses_zero(self): + """ValidationError is raised when timeout_seconds is 0.""" + from pydantic import ValidationError + import pytest + with pytest.raises(ValidationError) as exc_info: + SandboxConfig(timeout_seconds=0) + assert "timeout_seconds must be a positive non-zero integer" in str(exc_info.value) + + def test_timeout_seconds_refuses_negative(self): + """ValidationError is raised when timeout_seconds is negative.""" + from pydantic import ValidationError + import pytest + with pytest.raises(ValidationError) as exc_info: + SandboxConfig(timeout_seconds=-10) + assert "timeout_seconds must be a positive non-zero integer" in str(exc_info.value) + From 85ffa76f8902e101253b2be21195805b02b7be2a Mon Sep 17 00:00:00 2001 From: Rakshak05 <159248180+Rakshak05@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:09:38 +0530 Subject: [PATCH 2/2] fixed formatting issue. --- testing/backend/unit/test_config_settings.py | 1 - testing/backend/unit/test_sandbox_config_model.py | 1 - 2 files changed, 2 deletions(-) diff --git a/testing/backend/unit/test_config_settings.py b/testing/backend/unit/test_config_settings.py index 8bd8ee50f..08c58af1e 100644 --- a/testing/backend/unit/test_config_settings.py +++ b/testing/backend/unit/test_config_settings.py @@ -308,4 +308,3 @@ def test_sandbox_settings_validation_refuses_negative(): with pytest.raises(ValidationError) as exc_info: Settings(sandbox_timeout=-10) assert "Timeout settings must be a positive non-zero integer" in str(exc_info.value) - diff --git a/testing/backend/unit/test_sandbox_config_model.py b/testing/backend/unit/test_sandbox_config_model.py index 56d053b20..bd24673d7 100644 --- a/testing/backend/unit/test_sandbox_config_model.py +++ b/testing/backend/unit/test_sandbox_config_model.py @@ -99,4 +99,3 @@ def test_timeout_seconds_refuses_negative(self): with pytest.raises(ValidationError) as exc_info: SandboxConfig(timeout_seconds=-10) assert "timeout_seconds must be a positive non-zero integer" in str(exc_info.value) -