checks

package
v0.0.1-rc5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 28, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package checks defines the Check interface, the result types, and the shared registry/catalog used by both the scanner orchestrator and the HTTP API.

Concrete check implementations live in subpackages of internal/scanner (e.g. internal/scanner/wellknown, internal/scanner/tls, ...). They satisfy the Check interface defined here and self-register at init.

Index

Constants

View Source
const DefaultUserAgent = "WebSec0/0.1.0 (+https://websec0.example/about; passive-scan)"

DefaultUserAgent is used when a Target is constructed without one set.

Variables

This section is empty.

Functions

func Register

func Register(c Check)

Register is a convenience for c.Default().Register(c).

Types

type Check

type Check interface {
	ID() string
	Family() Family
	DefaultSeverity() Severity
	Run(ctx context.Context, target *Target) (*Finding, error)
}

Check is the contract every individual security check fulfils. ID is the stable SCREAMING-KEBAB-CASE identifier (e.g. TLS-PROTOCOL-LEGACY-SSL3).

Run must:

  • return a *Finding describing the outcome (one Finding per check, even for "pass" status — pass results power the catalog/coverage UI),
  • or return a non-nil error if the check itself failed to execute (the orchestrator turns that into a synthetic Finding with status=error).

type CheckMeta

type CheckMeta struct {
	ID              string   `json:"id"`
	Family          Family   `json:"family"`
	DefaultSeverity Severity `json:"default_severity"`
	Title           string   `json:"title,omitempty"`
	Description     string   `json:"description,omitempty"`
	RFCRefs         []string `json:"rfc_refs,omitempty"`
}

CheckMeta is the static metadata exposed via GET /api/v1/checks. It must remain serializable independently of any in-flight scan state.

type Describer

type Describer interface {
	Title() string
	Description() string
	RFCRefs() []string
}

Describer is an optional interface that checks can implement to enrich their catalog entry with human-facing documentation.

type Family

type Family string

Family groups checks by domain. Open-ended on purpose: third-party plugins (post-MVP) may introduce their own families.

const (
	FamilyTLS       Family = "tls"
	FamilyHeaders   Family = "headers"
	FamilyCookies   Family = "cookies"
	FamilyDNS       Family = "dns"
	FamilyEmail     Family = "email"
	FamilyWellKnown Family = "wellknown"
	FamilyExposures Family = "exposures"
	FamilyHTTP      Family = "http"
)

type Finding

type Finding struct {
	ID          string         `json:"id"`
	Family      Family         `json:"family"`
	Severity    Severity       `json:"severity"`
	Status      FindingStatus  `json:"status"`
	Title       string         `json:"title,omitempty"`
	Description string         `json:"description,omitempty"`
	Evidence    map[string]any `json:"evidence,omitempty"`
	Remediation map[string]any `json:"remediation,omitempty"`
}

Finding is the unit of output produced by a Check. JSON tags align with the OpenAPI Finding schema for direct serialization on the SSE wire.

type FindingStatus

type FindingStatus string

FindingStatus is the per-check outcome.

const (
	StatusPass    FindingStatus = "pass"
	StatusFail    FindingStatus = "fail"
	StatusWarn    FindingStatus = "warn"
	StatusError   FindingStatus = "error"
	StatusSkipped FindingStatus = "skipped"
)

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry is the in-memory catalogue of available checks. A process-wide default Registry exposes Default() for self-registration from check packages' init() functions.

func Default

func Default() *Registry

Default returns the process-wide registry used by self-registering check packages.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty Registry.

func (*Registry) All

func (r *Registry) All() []Check

All returns all registered checks sorted by ID.

func (*Registry) Catalog

func (r *Registry) Catalog() []CheckMeta

Catalog returns the static metadata for every registered Check. The HTTP layer renders the result as JSON on GET /api/v1/checks.

Checks may optionally implement Describer to enrich the catalog entry. When they don't, only the four interface-mandated fields are populated.

func (*Registry) Get

func (r *Registry) Get(id string) (Check, bool)

Get returns the check with the given id and whether it exists.

func (*Registry) Len

func (r *Registry) Len() int

Len returns the count of registered checks.

func (*Registry) Register

func (r *Registry) Register(c Check)

Register adds c. It panics on duplicate id (a programmer error: every check has a stable, unique identifier).

type Resolver

type Resolver interface {
	LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error)
}

Resolver mirrors the small subset of net.Resolver we depend on. It exists so tests can inject a stub without spinning up a real DNS server.

type Severity

type Severity string

Severity grades the impact of a finding. Values match the OpenAPI Severity enum; conversion between checks.Severity and client.Severity is a no-op string cast.

const (
	SeverityInfo     Severity = "info"
	SeverityLow      Severity = "low"
	SeverityMedium   Severity = "medium"
	SeverityHigh     Severity = "high"
	SeverityCritical Severity = "critical"
)

type Target

type Target struct {
	// Hostname is the canonical lowercase hostname (no scheme, no port,
	// no path). It is the value scoped by the SSRF/blocklist filters.
	Hostname string
	// Host is Hostname plus an optional `:port` suffix, used when
	// composing URLs (so tests against httptest.NewServer can target
	// 127.0.0.1:NNNN). For real scans Host == Hostname.
	Host string
	// Original is the unmodified user-supplied string (URL or hostname).
	Original string
	// UserAgent is the User-Agent header used by HTTP-based checks.
	// Defaults to DefaultUserAgent when empty.
	UserAgent string
	// HTTPClient is the HTTP client used by HTTP-based checks. nil means
	// http.DefaultClient.
	HTTPClient *http.Client
	// DNSResolverAddr is the host:port of the resolver consulted by
	// internal/scanner/dns. Empty means a sensible package default
	// (Cloudflare 1.1.1.1:53). Tests inject mock servers here.
	DNSResolverAddr string

	// PinnedIPs is the immutable set of IPs the SSRF gatekeeper resolved
	// at admission. All outbound connections from the scanner must use
	// one of these — see internal/scanner/safety. Empty in tests / CLI
	// when running without a Policy.
	PinnedIPs []net.IP
	// contains filtered or unexported fields
}

Target is the input handed to every Check during a scan. It holds the canonical hostname, the original input string, and a per-scan DNS cache that all checks share to avoid redundant lookups (cf. SPECIFICATIONS.md §4.5).

func NewTarget

func NewTarget(input string, resolver Resolver) (*Target, error)

NewTarget validates the input and returns a Target with an empty DNS cache. resolver may be nil to use net.DefaultResolver.

func (*Target) CacheValue

func (t *Target) CacheValue(key string, factory func() (any, error)) (any, error)

CacheValue runs factory at most once per key for the lifetime of the Target — concurrent callers either join the in-flight call or hit the cached result. Safe for use as a per-scan, per-target memo.

func (*Target) Client

func (t *Target) Client() *http.Client

Client returns the configured *http.Client (or http.DefaultClient).

func (*Target) DialAddress

func (t *Target) DialAddress(port string) string

DialAddress returns the "host:port" string that outbound TCP dials should use. When PinnedIPs is set, the hostname is replaced by the pinned IP; otherwise the original hostname is used.

func (*Target) FirstPinnedIP

func (t *Target) FirstPinnedIP() net.IP

FirstPinnedIP returns the first IP captured at admission, or nil when no policy was applied (tests / standalone CLI without --strict).

func (*Target) Resolve

func (t *Target) Resolve(ctx context.Context, host string) ([]net.IP, error)

Resolve returns the IP addresses for host, caching the answer for the lifetime of the Target. Subsequent calls for the same host hit the cache.

func (*Target) UA

func (t *Target) UA() string

UA returns the configured User-Agent (or the package default).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL