From 0965f629fbccd613a00c2e885daf5a66da656cd8 Mon Sep 17 00:00:00 2001 From: HitanshiThakar Date: Wed, 20 May 2026 00:01:46 +0530 Subject: [PATCH 1/2] test(plugins): add duplicate metadata validation --- plugins/waf_detector/metadata.json | 6 +-- testing/backend/unit/test_plugin_integrity.py | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/plugins/waf_detector/metadata.json b/plugins/waf_detector/metadata.json index 88906996..b642dcda 100644 --- a/plugins/waf_detector/metadata.json +++ b/plugins/waf_detector/metadata.json @@ -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.", @@ -10,7 +10,7 @@ "email": "dev@secuscan.local" }, "license": "MIT", - "icon": "\ud83d\udee0\ufe0f", + "icon": "🛠️", "engine": { "type": "cli", "binary": "wafw00f" @@ -54,5 +54,5 @@ "python_packages": [], "system_packages": [] }, - "checksum": "1e3dfcf6d4ba7847e398b9d9a4709dc275092f52a5f405e63d65cea0f8389cc0" + "checksum": "60b54af15ff7bad498a02cdbf08ee8611622e117944a3a65301cb3cae1582bb2" } diff --git a/testing/backend/unit/test_plugin_integrity.py b/testing/backend/unit/test_plugin_integrity.py index 3907d026..89d94a6e 100644 --- a/testing/backend/unit/test_plugin_integrity.py +++ b/testing/backend/unit/test_plugin_integrity.py @@ -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 @@ -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)) From 164fcea3dff43a280f0d83119f276e10b015cf02 Mon Sep 17 00:00:00 2001 From: HitanshiThakar Date: Wed, 20 May 2026 00:54:05 +0530 Subject: [PATCH 2/2] fix(validation): expand validate_url edge case coverage --- backend/secuscan/validation.py | 12 +++++++++++- testing/backend/unit/test_validation.py | 9 +++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/secuscan/validation.py b/backend/secuscan/validation.py index 10638f8d..225ba183 100644 --- a/backend/secuscan/validation.py +++ b/backend/secuscan/validation.py @@ -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: diff --git a/testing/backend/unit/test_validation.py b/testing/backend/unit/test_validation.py index a9a7c0b8..693def0d 100644 --- a/testing/backend/unit/test_validation.py +++ b/testing/backend/unit/test_validation.py @@ -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