Skip to content

klyrek-core

Status: live on PyPI — pip install klyrek-core

The foundation every other package builds on: the shared data model, authorization scope, config, logging, and the plugin registry.

from klyrek_core.models import Target, Endpoint, Technology, Finding, Severity, ScanResult
from klyrek_core.scope import AuthorizationScope
from klyrek_core.plugins import Plugin, register_plugin

scope = AuthorizationScope(authorized_hosts=["shop.sandbox.klyrek.com", "*.sandbox.klyrek.com"])
scope.is_authorized("https://api.sandbox.klyrek.com/api/")   # True
scope.is_authorized("https://evil.example.com/")             # False

See Authorization & Scope for the full safety model, and Plugins for writing your own detector.

API reference

klyrek_core.models

Common domain models shared across Klyrek packages.

These are the shapes every module (crawler, api, tech, auth, js, assets, headers, report, ...) reads and writes, so a scan built from multiple packages composes into one coherent application map instead of a pile of unrelated outputs.

Endpoint dataclass

Endpoint(url: str, method: str = 'GET', id: str = _new_id(), source: str = 'crawler', status_code: int | None = None, content_type: str | None = None, params: list[str] = list(), requires_auth: bool | None = None, discovered_by: str | None = None, discovered_at: datetime = _now())

A discovered page, form action, or API route.

Finding dataclass

Finding(title: str, severity: Severity, id: str = _new_id(), description: str = '', endpoint: Endpoint | None = None, evidence: list[str] = list(), module: str | None = None, created_at: datetime = _now())

An observation surfaced for human review — not a confirmed vulnerability.

ScanResult dataclass

ScanResult(target: Target, id: str = _new_id(), endpoints: list[Endpoint] = list(), technologies: list[Technology] = list(), findings: list[Finding] = list(), started_at: datetime = _now(), finished_at: datetime | None = None, metadata: dict[str, str] = dict())

The aggregate output of a scan: everything Klyrek learned about a target.

Target dataclass

Target(base_url: str, id: str = _new_id(), hosts: list[str] = list(), notes: str | None = None, created_at: datetime = _now())

The authorized root of a scan.

Technology dataclass

Technology(name: str, category: str, version: str | None = None, confidence: float = 1.0, evidence: list[str] = list(), discovered_by: str | None = None)

A fingerprinted technology observed on the target (framework, server, CMS, ...).

klyrek_core.scope

Authorization scope enforcement.

Every Klyrek package that makes a network request is expected to call AuthorizationScope.check() (or is_authorized()) first. This is the mechanism behind Klyrek's "authorized assessments only" principle: a scan can only ever touch hosts the operator has explicitly declared, so a typo'd target, a redirect to a third-party domain, or a misconfigured crawl can't silently reach out-of-scope infrastructure.

AuthorizationScope dataclass

AuthorizationScope(authorized_hosts: list[str] = list())

The set of hosts a scan is authorized to touch.

Patterns support fnmatch-style wildcards, e.g. *.target.com.

check

check(url_or_host: str) -> None

Raise ScopeViolationError if the given URL/host is not in scope.

Source code in klyrek_core\scope.py
def check(self, url_or_host: str) -> None:
    """Raise ScopeViolationError if the given URL/host is not in scope."""
    if not self.is_authorized(url_or_host):
        raise ScopeViolationError(_hostname(url_or_host))

klyrek_core.plugins

Plugin architecture shared across Klyrek packages.

Downstream packages (klyrek-tech, klyrek-osint, ...) register capabilities as plugins under a category (e.g. "tech-fingerprint", "osint-source") rather than being hard-wired into the core, so third parties can extend Klyrek without forking it.

Plugin

Bases: ABC

Base class for anything pluggable into a Klyrek scan.

run abstractmethod

run(*args: Any, **kwargs: Any) -> Any

Execute the plugin's capability.

Source code in klyrek_core\plugins.py
@abstractmethod
def run(self, *args: Any, **kwargs: Any) -> Any:
    """Execute the plugin's capability."""

PluginRegistry

PluginRegistry()

Holds registered plugins, keyed by category then name.

Source code in klyrek_core\plugins.py
def __init__(self) -> None:
    self._plugins: dict[str, dict[str, type[Plugin]]] = defaultdict(dict)

register_plugin

register_plugin(plugin_cls: type[Plugin]) -> type[Plugin]

Class decorator: register a plugin on the default registry.

Example

@register_plugin class WordPressFingerprint(Plugin): name = "wordpress" category = "tech-fingerprint"

def run(self, response): ...
Source code in klyrek_core\plugins.py
def register_plugin(plugin_cls: type[Plugin]) -> type[Plugin]:
    """Class decorator: register a plugin on the default registry.

    Example:
        @register_plugin
        class WordPressFingerprint(Plugin):
            name = "wordpress"
            category = "tech-fingerprint"

            def run(self, response): ...
    """
    return registry.register(plugin_cls)