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
12 changes: 11 additions & 1 deletion backend/secuscan/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,17 @@ def validate_url(url: str) -> Tuple[bool, str]:
r'(?:/?|[/?]\S+)$', re.IGNORECASE
)

return (True, "") if url_pattern.match(url) else (False, "Invalid URL format")
if not url_pattern.match(url):
return False, "Invalid URL format"

# Validate optional port range if provided
port_match = re.search(r':(\d+)(?:/|\?|$)', url.split('://', 1)[1])
if port_match:
port = int(port_match.group(1))
if port < 1 or port > 65535:
return False, "Invalid URL format"

return True, ""


def sanitize_input(value: str) -> str:
Expand Down
6 changes: 3 additions & 3 deletions plugins/waf_detector/metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "waf_detector",
"name": "WAF Detector",
"name": "WAF Detection Scanner",
"version": "1.0.0",
"description": "Automatically identify Web Application Firewalls protecting targets.",
"long_description": "Automatically identify Web Application Firewalls protecting targets.",
Expand All @@ -10,7 +10,7 @@
"email": "dev@secuscan.local"
},
"license": "MIT",
"icon": "\ud83d\udee0\ufe0f",
"icon": "🛠️",
"engine": {
"type": "cli",
"binary": "wafw00f"
Expand Down Expand Up @@ -54,5 +54,5 @@
"python_packages": [],
"system_packages": []
},
"checksum": "1e3dfcf6d4ba7847e398b9d9a4709dc275092f52a5f405e63d65cea0f8389cc0"
"checksum": "60b54af15ff7bad498a02cdbf08ee8611622e117944a3a65301cb3cae1582bb2"
}
37 changes: 37 additions & 0 deletions testing/backend/unit/test_plugin_integrity.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import asyncio
import json
from collections import defaultdict
from pathlib import Path

import pytest

from backend.secuscan.plugins import PluginManager
from backend.secuscan.config import settings

Expand All @@ -18,3 +21,37 @@ def test_plugins_have_checksums():
for path in metadata_files:
data = json.loads(path.read_text(encoding="utf-8"))
assert data.get("checksum"), f"Missing checksum in {path}"


def test_plugin_metadata_ids_and_names_are_unique():
metadata_files = list(Path(settings.plugins_dir).glob("*/metadata.json"))
assert metadata_files, "Expected plugin metadata files"

ids = defaultdict(list)
names = defaultdict(list)

for path in metadata_files:
data = json.loads(path.read_text(encoding="utf-8"))
plugin_id = data.get("id")
plugin_name = data.get("name")
assert plugin_id, f"Missing plugin id in {path}"
assert plugin_name, f"Missing plugin name in {path}"

ids[plugin_id].append(path.parent.name)
names[plugin_name].append(path.parent.name)

duplicate_ids = {plugin_id: folders for plugin_id, folders in ids.items() if len(folders) > 1}
duplicate_names = {plugin_name: folders for plugin_name, folders in names.items() if len(folders) > 1}

if duplicate_ids or duplicate_names:
messages = []
if duplicate_ids:
messages.append("Duplicate plugin IDs found:")
for plugin_id, folders in sorted(duplicate_ids.items()):
messages.append(f" {plugin_id}: {', '.join(sorted(folders))}")
if duplicate_names:
messages.append("Duplicate plugin display names found:")
for plugin_name, folders in sorted(duplicate_names.items()):
messages.append(f" {plugin_name}: {', '.join(sorted(folders))}")

pytest.fail("\n".join(messages))
9 changes: 7 additions & 2 deletions testing/backend/unit/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ def test_validate_port():

def test_validate_url():
assert validate_url("http://localhost:8080")[0] is True
assert validate_url("https://example.com/path?param=value")[0] is True
assert validate_url("http://192.168.1.1")[0] is True
assert validate_url("https://localhost/path?param=value")[0] is True
assert validate_url("http://192.168.1.1:8080/path")[0] is True
assert validate_url("https://127.0.0.1/secure?x=1")[0] is True

assert validate_url("ftp://example.com")[0] is False
assert validate_url("http:///path")[0] is False
assert validate_url("http://example.com /path")[0] is False
assert validate_url("http://localhost:99999")[0] is False
assert validate_url("http://example.com:port")[0] is False
assert validate_url("not_a_url")[0] is False
assert validate_url("http://")[0] is False

Expand Down
Loading