diff --git a/backend/secuscan/config.py b/backend/secuscan/config.py index 2853354f..5685895a 100644 --- a/backend/secuscan/config.py +++ b/backend/secuscan/config.py @@ -63,7 +63,7 @@ class Settings(BaseSettings): admin_api_key: Optional[str] = None # Network Policy Configuration - network_allowlist: List[str] = [] # IPs/networks to allow (CIDR) + network_allowlist: List[str] = [] # IPs/networks to allow (CIDR); empty = deny all egress network_denylist: List[str] = [ # IPs/networks to deny (CIDR) "169.254.169.254/32", # AWS metadata "169.254.0.0/16", # Reserved/metadata diff --git a/backend/secuscan/network_policy.py b/backend/secuscan/network_policy.py index 21bf490f..db4af27f 100644 --- a/backend/secuscan/network_policy.py +++ b/backend/secuscan/network_policy.py @@ -398,11 +398,9 @@ def _init_default_policies(engine: NetworkPolicyEngine) -> None: except ValueError: logger.warning(f"Skipping invalid allowlist CIDR: {cidr}") - # Add system defaults (if allowlist is empty, add public internet) + # Warn if allowlist is empty — network policy defaults to deny-all egress if not settings.network_allowlist: logger.warning( - "SECUSCAN_NETWORK_ALLOWLIST is empty. Allowing all public IPs. " - "Configure this environment variable to restrict egress." + "SECUSCAN_NETWORK_ALLOWLIST is empty. All external network egress is blocked. " + "Configure this environment variable with CIDR ranges to allow outbound traffic." ) - engine.add_allow_rule("0.0.0.0/0", reason="Default allow all (configure SECUSCAN_NETWORK_ALLOWLIST)") - engine.add_allow_rule("::/0", reason="Default allow all IPv6") diff --git a/backend/secuscan/workflows.py b/backend/secuscan/workflows.py index eb98c598..c7ba88dc 100644 --- a/backend/secuscan/workflows.py +++ b/backend/secuscan/workflows.py @@ -72,6 +72,7 @@ def _should_run(self, now: datetime, last_run_at: str | None, schedule_seconds: return elapsed >= schedule_seconds async def _run_workflow(self, workflow_id: str, steps: List[Dict[str, Any]]): logger.info("Running workflow %s with %d step(s)", workflow_id, len(steps)) + db = await get_db() for step in steps: plugin_id = step.get("plugin_id") inputs = step.get("inputs") or {} diff --git a/frontend/testing/unit/pages/ToolConfigDynamic.test.tsx b/frontend/testing/unit/pages/ToolConfigDynamic.test.tsx index 6cd5a1da..03bfb13c 100644 --- a/frontend/testing/unit/pages/ToolConfigDynamic.test.tsx +++ b/frontend/testing/unit/pages/ToolConfigDynamic.test.tsx @@ -108,6 +108,11 @@ describe('ToolConfig dynamic schema flow', () => { }), true, 'quick', + expect.objectContaining({ + scan_profile: 'standard', + validation_mode: 'proof', + evidence_level: 'standard', + }), ) }) }) diff --git a/frontend/testing/unit/pages/ToolConfigTimeout.test.tsx b/frontend/testing/unit/pages/ToolConfigTimeout.test.tsx index 4c0b2213..513ca033 100644 --- a/frontend/testing/unit/pages/ToolConfigTimeout.test.tsx +++ b/frontend/testing/unit/pages/ToolConfigTimeout.test.tsx @@ -75,6 +75,6 @@ describe('ToolConfig timeout control', () => { // min from field.validation expect(input).toHaveAttribute('min', '30') // max is min(field.validation.max, server default_timeout) - expect(input).toHaveAttribute('max', '600') + expect(input).toHaveAttribute('max', '7200') }) }) diff --git a/frontend/testing/unit/pages/Workflows.test.tsx b/frontend/testing/unit/pages/Workflows.test.tsx index 7c304da8..54628a33 100644 --- a/frontend/testing/unit/pages/Workflows.test.tsx +++ b/frontend/testing/unit/pages/Workflows.test.tsx @@ -130,7 +130,15 @@ describe('Workflows — create action', () => { name: 'Nightly Scan', schedule_seconds: 7200, enabled: true, - steps: [{ plugin_id: '', inputs: {} }], + steps: [{ + plugin_id: '', + inputs: {}, + execution_context: { + scan_profile: 'standard', + validation_mode: 'proof', + evidence_level: 'standard', + }, + }], }) }) })