Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/secuscan/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 3 additions & 5 deletions backend/secuscan/network_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
1 change: 1 addition & 0 deletions backend/secuscan/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
5 changes: 5 additions & 0 deletions frontend/testing/unit/pages/ToolConfigDynamic.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ describe('ToolConfig dynamic schema flow', () => {
}),
true,
'quick',
expect.objectContaining({
scan_profile: 'standard',
validation_mode: 'proof',
evidence_level: 'standard',
}),
)
})
})
Expand Down
2 changes: 1 addition & 1 deletion frontend/testing/unit/pages/ToolConfigTimeout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
})
10 changes: 9 additions & 1 deletion frontend/testing/unit/pages/Workflows.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
}],
})
})
})
Expand Down
Loading