-
Notifications
You must be signed in to change notification settings - Fork 1
Plugin System
Scanners are independent PyPI packages. The orchestrator (and worker nodes) discover them via Python entry points at startup. The core never contains scanner logic — install what you need, uninstall what you don't.
# In the scanner package's pyproject.toml:
[project.entry-points."gloomproxy.scanners"]
xss = "gloomscan_xss.scanner:XSSScanner"from gloomproxy_sdk import BaseScanner, Finding, ScanContext, Target
from gloomproxy_sdk.manifest import PluginManifest, TrustLevel
class XSSScanner(BaseScanner):
name = "xss"
version = "1.0.0"
description = "Reflected and stored XSS detection"
author = "CommonHuman-Lab"
tags = ["xss", "active", "http"]
@classmethod
def manifest(cls) -> PluginManifest:
return {
"trust_level": TrustLevel.COMMUNITY,
"resources": {"max_runtime": 120, "max_findings": 500},
"sdk_min_version": "0.1.0",
}
def initialize(self, context: ScanContext) -> None:
self._cfg = context.config
async def scan(self, target: Target) -> list[Finding]:
return [
Finding(
scanner="xss",
type="reflected_xss",
severity="high",
target=target.url,
evidence="<script>alert(1)</script> reflected unescaped",
title="Reflected XSS",
)
]
def teardown(self) -> None:
pass # close HTTP sessions etc.Every plugin optionally declares a manifest() classmethod. The sandbox reads it at execution time to resolve resource limits and select the right isolation policy. If omitted, COMMUNITY defaults apply.
@classmethod
def manifest(cls) -> PluginManifest:
return {
"trust_level": TrustLevel.COMMUNITY, # CORE | VERIFIED | COMMUNITY | EXPERIMENTAL
"resources": {
"max_runtime": 120, # seconds — capped by trust-tier ceiling
"max_memory_mb": 256, # MB — advisory in asyncio, hard in subprocess/container
"max_findings": 500, # gateway rejects findings beyond this
"max_events_per_sec": 10.0, # token-bucket rate
"max_event_burst": 50, # burst capacity
},
"sdk_min_version": "0.1.0",
}All findings pass the validation gateway before reaching the event bus. The orchestrator injects correlation_id, worker_id, and schema_version automatically — scanners do not set these.
{
"id": "uuid",
"schema_version": "1.0",
"scanner": "string (required)",
"type": "string (required)",
"severity": "info | low | medium | high | critical",
"target": "url string (required)",
"evidence": "string (required, max 64 KB)",
"title": "string",
"description": "string",
"remediation": "string",
"confidence": "float 0.0–1.0",
"request": "raw HTTP request",
"response": "raw HTTP response",
"references": ["url"],
"tags": ["string"],
"extra": {},
"correlation_id": "uuid (orchestrator-injected)",
"worker_id": "string (orchestrator-injected)",
"timestamp": "unix float"
}The SDK is the only package plugin authors need to import. It provides the scanner base class, finding model, scan context, event emitter, and plugin manifest types.
from gloomproxy_sdk import (
BaseScanner, Finding, ScanContext, Target,
PluginManifest, TrustLevel,
)
from gloomproxy_sdk.exceptions import InitializationError, ScanError
from gloomproxy_sdk.utils.http import ScanHttpClientThe SDK is versioned independently. Workers and orchestrators log a compat warning at startup for any installed plugin whose sdk_min_version or sdk_max_version bounds do not include the installed SDK version. Incompatible plugins are loaded but their warning is visible in GET /api/plugins.
# During development — install editable from the scanner package dir
pip install -e /path/to/stingxss
# Or from PyPI once published
pip install stingxss
# Reload without restarting:
curl -X POST http://localhost:8000/api/plugins/reload
# or click Reload in the Plugins UI