auditspec

package
v0.12.1 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2026 License: MPL-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package auditspec is the policy model and evaluation engine for gowdk audit.

A Policy is a named, composable set of Rules applied to targets (routes, endpoints, contracts, or the frontend surface) selected by Selectors. The built-in Baseline encodes the production-readiness gates from docs/engineering/security.md; declared *.audit.gwdk policies extend or override it. Evaluate matches the policies against a securitymanifest posture and returns registry-coded Findings; it never decides severity — that comes only from internal/diagnostics.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SortFindings

func SortFindings(findings []Finding)

SortFindings orders findings deterministically by severity, code, then target.

func Status

func Status(summary Summary) string

Status reports "fail" when any error finding exists, "warning" when only warnings exist, and "ok" otherwise.

Types

type Finding

type Finding struct {
	Code        string               `json:"code"`
	Severity    diagnostics.Severity `json:"severity"`
	CodeSource  string               `json:"codeSource,omitempty"`
	Fingerprint string               `json:"fingerprint,omitempty"`
	Target      string               `json:"target,omitempty"`
	Policy      string               `json:"policy,omitempty"`
	Rule        string               `json:"rule,omitempty"`
	Confidence  string               `json:"confidence,omitempty"`
	Evidence    string               `json:"evidence,omitempty"`
	CWE         []string             `json:"cwe,omitempty"`
	OWASP       []string             `json:"owasp,omitempty"`
	Suppression *Suppression         `json:"suppression,omitempty"`
	Message     string               `json:"message"`
	Source      string               `json:"source,omitempty"`
	Remediation string               `json:"remediation,omitempty"`
}

Finding is one policy violation or policy-resolution error.

func EnrichFindings added in v0.8.0

func EnrichFindings(findings []Finding) []Finding

EnrichFindings fills stable triage metadata on findings without changing the policy result itself. It is safe to call more than once.

func Evaluate

func Evaluate(manifest securitymanifest.SecurityManifest, policies []Policy) []Finding

Evaluate matches policies against the posture manifest and returns findings. It first reports policy-resolution problems (cycles, unknown extends), then the per-target rule violations. Findings are returned in a stable order. Declared waivers are applied without digest pinning; use EvaluateWithWaivers to validate waivers against the current policy and posture digests.

func EvaluateWithWaivers added in v0.8.0

func EvaluateWithWaivers(manifest securitymanifest.SecurityManifest, policies []Policy, waiverCtx WaiverContext) []Finding

EvaluateWithWaivers is Evaluate with the current policy and posture digests so declared waivers that pin a digest can be validated against drift.

type Policy

type Policy struct {
	Name      string
	Extends   []string
	Selectors []Selector
	Rules     []Rule
	Source    string
	Builtin   bool
}

Policy is a named, composable set of rules applied to selected targets.

func Baseline

func Baseline() []Policy

Baseline returns the built-in policy set that gowdk audit applies with zero configuration. It encodes the production-readiness gates from docs/engineering/security.md and docs/engineering/security-threat-model.md so security is enforced by default, not by opt-in. Declared *.audit.gwdk policies extend or override these via matching selectors and rules.

Severity is never set here; each rule references a registry code and the engine resolves severity from internal/diagnostics.

func ComposeBaseline

func ComposeBaseline(declared []Policy) []Policy

ComposeBaseline returns the built-in baseline with declared policies appended.

Built-in baseline policies are monotonic: a declared policy can extend or tighten the baseline (with `extends`) or suppress a specific finding (with an explicit `waive`), but it can no longer silently replace a baseline policy by reusing its name. A same-name declared policy is kept here and reported by resolve as policy_baseline_override; its rules are not applied, so the baseline can never be weakened by omission. This keeps the fail-closed production story honest: removing a built-in error requires an attributable, expiring waiver.

func PoliciesFromIR

func PoliciesFromIR(specs []gwdkir.AuditSpec) []Policy

PoliciesFromIR converts parsed *.audit.gwdk specs into engine policies.

type Rule

type Rule struct {
	Kind   RuleKind
	Value  string
	Code   string
	Source string
	Attrs  map[string]string
}

Rule is one policy constraint. Code is the diagnostic code emitted when the rule is violated; Value carries the rule argument (a guard ID, header name, byte size, or allowlist entry) when the rule kind needs one. Source records where a declared rule originated so code-override validation can point at it.

type RuleKind

type RuleKind string

RuleKind classifies one policy rule.

const (
	// RuleRequireCSRF requires a matched endpoint to enforce CSRF.
	RuleRequireCSRF RuleKind = "require_csrf"
	// RuleRequireAnyGuard requires a matched target to state access (any guard,
	// including guard public) rather than be denied by omission.
	RuleRequireAnyGuard RuleKind = "require_any_guard"
	// RuleRequireGuard requires a specific guard ID (for example role:admin).
	RuleRequireGuard RuleKind = "require_guard"
	// RuleDenyPublic forbids guard public on a matched target.
	RuleDenyPublic RuleKind = "deny_public"
	// RuleMaxBody caps a matched endpoint's request body limit.
	RuleMaxBody RuleKind = "max_body"
	// RuleRequireRequestLimits requires a matched endpoint to declare an effective
	// request-limit posture: a positive raw body cap installed before the body is
	// parsed, and a multipart cap when multipart bodies are accepted.
	RuleRequireRequestLimits RuleKind = "require_request_limits"
	// RuleRequireHeader requires the app to be configured to emit a response
	// header.
	RuleRequireHeader RuleKind = "require_header"
	// RuleCheckSecurityHeaders audits the semantic strength of configured
	// security response headers (CSP, nosniff, Referrer-Policy, HSTS, framing).
	RuleCheckSecurityHeaders RuleKind = "check_security_headers"
	// RuleCheckCORS audits the generated cross-origin policy for risky
	// combinations such as a wildcard origin (optionally with credentials).
	RuleCheckCORS RuleKind = "check_cors"
	// RuleRequireClientRouteGuards reports client-visible routes that rely on
	// default-deny because the source declared no guard.
	RuleRequireClientRouteGuards RuleKind = "require_client_route_guards"
	// RuleNoSecretsInBundle forbids secret-shaped values in embedded output.
	RuleNoSecretsInBundle RuleKind = "no_secrets_in_bundle"
	// RuleDenyRawHTMLSinks reports every raw-HTML sink not allowlisted by a
	// RuleAllowRawHTML rule in any resolved frontend policy.
	RuleDenyRawHTMLSinks RuleKind = "deny_raw_html_sinks"
	// RuleAllowRawHTML allowlists one raw-HTML sink (source:field); every sink
	// not allowlisted is reported. This is the legacy coarse allowlist; prefer
	// RuleExceptRawHTML for an exact, justified, expiring exception.
	RuleAllowRawHTML RuleKind = "allow_raw_html"
	// RuleExceptRawHTML suppresses exactly one raw-HTML sink by its fingerprint,
	// and only when the exception carries an owner, justification, unexpired
	// expiry, and sanitizer/trusted-type contract.
	RuleExceptRawHTML RuleKind = "except_raw_html"
	// RuleDenyRolelessContract reports a web-exposed command or query contract
	// that declares no roles, so the data-layer authorization gate has no role to
	// admit. The contract must declare at least one role (or RoleAny to be
	// intentionally public).
	RuleDenyRolelessContract RuleKind = "deny_roleless_contract"
	// RuleRequireVerifiedGuards reports guards whose implementation is app-owned
	// and not backed by audit fixture evidence.
	RuleRequireVerifiedGuards RuleKind = "require_verified_guards"
	// RuleCheckObservability reports unsafe generated trace endpoint posture.
	RuleCheckObservability RuleKind = "check_observability"
	// RuleWaive suppresses one finding (by diagnostic code and target) when the
	// waiver carries an owner, justification, and unexpired expiry, and any pinned
	// policy/posture digest still matches. A waived finding is recorded with its
	// suppression metadata instead of blocking, so a suppression is always an
	// explicit, attributable, expiring decision rather than a silent override.
	RuleWaive RuleKind = "waive"
)

type Selector

type Selector struct {
	Raw  string
	Kind SelectorKind
}

Selector targets a set of routes, endpoints, or the frontend surface.

func ParseSelector

func ParseSelector(raw string) Selector

ParseSelector classifies a raw selector string.

type SelectorKind

type SelectorKind string

SelectorKind classifies a policy target selector.

const (
	SelectorRoute         SelectorKind = "route"
	SelectorEndpoint      SelectorKind = "endpoint"
	SelectorContract      SelectorKind = "contract"
	SelectorObservability SelectorKind = "observability"
	SelectorFrontend      SelectorKind = "frontend"
	SelectorUnknown       SelectorKind = "unknown"
)

type Summary

type Summary struct {
	Errors   int `json:"errors"`
	Warnings int `json:"warnings"`
	Info     int `json:"info"`
	Waived   int `json:"waived"`
}

Summary counts findings by severity. Waived findings (suppressed by an explicit waiver) are counted only under Waived so a justified, unexpired suppression does not block, while the suppression stays recorded in the report.

func Summarize

func Summarize(findings []Finding) Summary

Summarize counts findings by their registry severity, excluding waived findings from the error/warning/info counts.

type Suppression added in v0.8.0

type Suppression struct {
	Owner         string `json:"owner,omitempty"`
	Justification string `json:"justification,omitempty"`
	Expires       string `json:"expires,omitempty"`
	Ticket        string `json:"ticket,omitempty"`
	DigestScope   string `json:"digestScope,omitempty"`
}

Suppression is reserved for explicit waiver records once the audit DSL grows waiver syntax. Keeping the shape in JSON now lets downstream tooling preserve the field without inventing an incompatible suppression contract later.

type Waiver added in v0.8.0

type Waiver struct {
	Code          string
	Target        string
	Owner         string
	Justification string
	Expires       string
	Ticket        string
	PolicyDigest  string
	PostureDigest string
	Policy        string
	Source        string
}

Waiver is one declared `waive` rule: an explicit, attributable, expiring decision to suppress a specific finding by diagnostic code and target. A waiver only suppresses when it carries an owner, justification, and unexpired expiry, and when any pinned policy/posture digest still matches the current build. Invalid or stale waivers are reported instead of silently doing nothing.

type WaiverContext added in v0.8.0

type WaiverContext struct {
	Now           time.Time
	PolicyDigest  string
	PostureDigest string
}

WaiverContext carries the current policy and posture digests so a waiver that pins a digest can be invalidated when the policy set or posture drifts. A zero Now falls back to the package clock.

Jump to

Keyboard shortcuts

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