Documentation
¶
Overview ¶
Package engine provides SQL token fingerprints and contextual XSS detection. The SQL path is a pure Go approximation of libinjection's fingerprint approach.
Package engine provides HTTP protocol enforcement and smuggling detection. Checks observable framing conflicts, invalid protocol fields, and header injection. net/http owns raw chunk framing/size validation before handlers see a request.
Package engine provides sandboxed execution guards for the detection pipeline. All detector invocations are protected against ReDoS, memory exhaustion, and panics.
Package engine defines core interfaces for the WAF detection pipeline.
Index ¶
- Constants
- Variables
- func ClientIP(r *http.Request) string
- func ClientIPWithTrustedProxies(r *http.Request, trustedCIDRs []string) string
- func ClientIPWithTrustedProxyProviders(r *http.Request, trustedCIDRs []string, providerCIDRs map[string][]string) string
- func Guard[T any](fn func() (T, error)) (result T, err error)
- func GuardContext[T any](ctx context.Context, fn func() (T, error)) (result T, err error)
- func GuardSync[T any](fn func() (T, error)) (result T, err error)
- func NormalizeRequestPath(raw string) (string, bool)
- func PathMatchesPrefix(requestPath, prefix string) bool
- func ProcessBudgetExhaustedPass() uint64
- func RecordBudgetExhaustedPass()
- func RegexComplexityScore(pattern string) int
- func ResetBudgetExhaustedPassForTest()
- func SQLLibinjectionFingerprint(input string) (string, bool)
- func SecurityPathViews(raw string) ([]string, bool)
- func SemanticQueueStats() (jobs, waitNanos, overloads uint64, depth int)
- func SetDetectionBudgetExhaustedHook(hook func())
- func XSSLibinjectionFingerprint(input string) bool
- type Action
- type BoundedRegex
- type DetectionResult
- type Detector
- type Pipeline
- func (p *Pipeline) Add(detector Detector)
- func (p *Pipeline) Detect(ctx context.Context, reqCtx *RequestContext) (*DetectionResult, error)
- func (p *Pipeline) DetectionBudget(reqCtx *RequestContext) time.Duration
- func (p *Pipeline) Detectors() []Detector
- func (p *Pipeline) SetDetectionBudget(budget time.Duration)
- type ProtocolViolation
- type RequestContext
- func NewRequestContext(r *http.Request, siteID string) (*RequestContext, error)
- func NewRequestContextDeferredBody(r *http.Request, siteID string, trustedCIDRs []string, maxBodyBytes int64) (*RequestContext, error)
- func NewRequestContextDeferredBodyWithTrustedProxyPolicy(r *http.Request, siteID string, policy *TrustedProxyPolicy, maxBodyBytes int64) (*RequestContext, error)
- func NewRequestContextWithLimits(r *http.Request, siteID string, trustedCIDRs []string, maxBodyBytes int64) (*RequestContext, error)
- func NewRequestContextWithTrustedProxies(r *http.Request, siteID string, trustedCIDRs []string) (*RequestContext, error)
- type Severity
- type TrustedProxyPolicy
Constants ¶
const ( // MaxDecodedBytes limits post-decompression/decoding expansion. MaxDecodedBytes = 2 * 1024 * 1024 // 2MB // MaxRegexMatchTime is the deadline for any single regex match. MaxRegexMatchTime = 50 * time.Millisecond // MaxRegexComplexityScore rejects patterns likely to cause catastrophic backtracking. MaxRegexComplexityScore = 30 )
Variables ¶
var ( // ErrRegexMatchTimeout and ErrRegexMatchOverload let callers that need // fail-closed accounting distinguish an incomplete match from a clean // negative result. The legacy bool methods retain their compatibility shape. ErrRegexMatchTimeout = errors.New("regular expression match timed out") ErrRegexMatchOverload = errors.New("regular expression matcher overloaded") )
var ErrDetectionOverload = errors.New("detection overload: too many in-flight guards")
ErrDetectionOverload reports that Guard could not start detector work because every bounded worker slot was already occupied.
var ErrRequestBodyReadOverload = errors.New("request body inspection overloaded")
ErrRequestBodyReadOverload means bounded reader or body-byte capacity is full. It is an incomplete-inspection condition and must never be treated as clean.
var ErrRequestBodyReadTimeout = errors.New("request body read idle timeout")
ErrRequestBodyReadTimeout means an upload stopped making progress. Upload time is bounded separately from the detector CPU budget.
var ErrRequestBodyTooLarge = errors.New("request body exceeds configured limit")
Functions ¶
func ClientIPWithTrustedProxies ¶
ClientIPWithTrustedProxies accepts only the standardized forwarding chain. Provider-specific headers require ClientIPWithTrustedProxyProviders.
func ClientIPWithTrustedProxyProviders ¶
func ClientIPWithTrustedProxyProviders(r *http.Request, trustedCIDRs []string, providerCIDRs map[string][]string) string
ClientIPWithTrustedProxyProviders resolves provider-specific headers only when the socket peer matches that provider's explicitly configured CIDRs.
func Guard ¶
Guard runs a detection function with panic recovery and timeout protection. It is the compatibility wrapper for callers without a context; request paths should prefer GuardContext so cancellation can end the wait early.
func GuardContext ¶
GuardContext runs a detector with panic recovery, a caller deadline (or a compatibility timeout when none is set), and caller cancellation. The detector runs in a bounded goroutine so a function that ignores ctx cannot hold the request path past its budget. When the caller returns early, the guard slot remains occupied until the detector exits; this preserves the leak bound enforced by guardSlots.
A nil context is treated like context.Background for compatibility with callers that do not have a request scope.
func GuardSync ¶
GuardSync protects a non-blocking detector without creating a goroutine or timer. The caller's pipeline context still enforces the request deadline.
func NormalizeRequestPath ¶
NormalizeRequestPath cleans a URL path for security policy matching. It repeatedly URL-decodes (up to a safe cap), then path.Clean, ensures a leading "/", and rejects empty paths, NUL bytes, residual encodings, and residual ".." segments after cleaning.
func PathMatchesPrefix ¶
PathMatchesPrefix reports whether requestPath equals prefix or is a child under prefix using segment boundaries. Trailing slashes on prefix are ignored except that "/" matches every absolute path. Empty prefix matches all paths.
Examples: prefix "/api" or "/api/" matches "/api" and "/api/foo" but not "/apixyz".
func ProcessBudgetExhaustedPass ¶
func ProcessBudgetExhaustedPass() uint64
ProcessBudgetExhaustedPass returns the number of budget-exhausted requests forwarded upstream for this process lifetime.
func RecordBudgetExhaustedPass ¶
func RecordBudgetExhaustedPass()
RecordBudgetExhaustedPass records one request that was forwarded upstream after the detection budget ran out. The proxy calls this from the explicit ActionLog branch so that "allow" stays a decision rather than a fallthrough.
func RegexComplexityScore ¶
RegexComplexityScore estimates the backtracking risk of a regex pattern. Higher score = more dangerous. Based on OWASP ReDoS detection heuristics.
func ResetBudgetExhaustedPassForTest ¶
func ResetBudgetExhaustedPassForTest()
ResetBudgetExhaustedPassForTest clears the process counter for isolated tests. Used by the proxy's fail-open tests, which assert on an exact count.
func SQLLibinjectionFingerprint ¶
SQLLibinjectionFingerprint tokenizes an SQL string and returns a fingerprint string. Returns empty string if the input doesn't look like SQL. If the fingerprint matches known SQLi patterns, the input is SQLi.
func SecurityPathViews ¶ added in v0.4.5
SecurityPathViews preserves existing raw/clean policy meanings and adds the routing interpretation used by backends that strip matrix parameters. Use every view for protective requirements, not to broaden allowlist exemptions.
func SemanticQueueStats ¶ added in v0.4.5
SemanticQueueStats exposes cumulative queue delay and admission failures. Latency is measured before detector execution, independently of CPU work.
func SetDetectionBudgetExhaustedHook ¶
func SetDetectionBudgetExhaustedHook(hook func())
SetDetectionBudgetExhaustedHook installs an optional metrics hook without introducing an import cycle with semantic metrics.
func XSSLibinjectionFingerprint ¶
XSSLibinjectionFingerprint retains the historical API name but performs context-aware substring matching; it is not a token fingerprint implementation.
Types ¶
type Action ¶
type Action int
Action represents the action to take when a detection matches. 检测匹配后的动作。
type BoundedRegex ¶
type BoundedRegex struct {
// contains filtered or unexported fields
}
BoundedRegex wraps a regexp.Regexp with timeout protection for ReDoS.
func CompileSafe ¶
func CompileSafe(pattern string) (*BoundedRegex, error)
CompileSafe compiles a regex pattern and rejects dangerously complex ones.
func (*BoundedRegex) Match ¶
func (b *BoundedRegex) Match(b2 []byte) bool
Match performs bounded matching on a byte slice with ReDoS protection.
func (*BoundedRegex) MatchStatus ¶
func (b *BoundedRegex) MatchStatus(b2 []byte) (bool, error)
MatchStatus is the byte-slice counterpart of MatchStringStatus.
func (*BoundedRegex) MatchString ¶
func (b *BoundedRegex) MatchString(s string) bool
MatchString performs a complete RE2 match. Go's regexp engine has linear complexity; callers choosing the explicit deadline API must use Status and handle its error instead of silently treating an incomplete match as false.
func (*BoundedRegex) MatchStringStatus ¶
func (b *BoundedRegex) MatchStringStatus(s string) (bool, error)
MatchStringStatus performs the complete match without truncating the subject. Go's regexp engine is RE2-based and linear-time; truncation here would create a security bypass whenever a payload is appended after the old cutoff. Callers that need to surface an incomplete inspection should use the returned error.
func (*BoundedRegex) Regexp ¶
func (b *BoundedRegex) Regexp() *regexp.Regexp
Regexp returns the compiled stdlib pattern behind the bounded wrapper.
CompileSafe is also a construction-time gate: callers that must keep stdlib match semantics (no input truncation, no deadline) use Regexp to run the match themselves while still requiring the complexity gate up front. That matters for detectors, where silently truncating the subject would let an attacker append a payload past the truncation point.
type DetectionResult ¶
type DetectionResult struct {
Detected bool `json:"detected"` // 是否检测到威胁 / Whether a threat was detected
DetectorID string `json:"detector_id"` // 检测器标识 / Detector identifier
Category string `json:"category"` // 攻击类别 (sqli/xss/rce/lfi...) / Attack category
Severity Severity `json:"severity"` // 严重程度 / Severity level
Action Action `json:"action"` // 建议动作 / Recommended action
Message string `json:"message"` // 人类可读描述 / Human-readable description
Confidence float64 `json:"confidence"` // 置信度 0.0-1.0 / Confidence score
Payload string `json:"payload"` // 触发的恶意载荷 / Malicious payload that triggered detection
}
DetectionResult holds the result of a single detector's analysis. 单个检测器的分析结果。
type Detector ¶
type Detector interface {
// ID returns the unique identifier for this detector.
// 返回检测器的唯一标识。
ID() string
// Name returns a human-readable name.
// 返回人类可读的名称。
Name() string
// Detect analyzes the request context and returns detection results.
// 分析请求上下文并返回检测结果。
Detect(ctx context.Context, reqCtx *RequestContext) (*DetectionResult, error)
// Priority returns the execution order (lower = earlier).
// 返回执行优先级(数值越小越先执行)。
Priority() int
}
Detector is the core interface for all WAF detection modules. Each layer in the detection pipeline implements this interface. 所有 WAF 检测模块的核心接口,检测流水线的每一层都实现此接口。
type Pipeline ¶
type Pipeline struct {
// contains filtered or unexported fields
}
func NewPipeline ¶
func (*Pipeline) Detect ¶
func (p *Pipeline) Detect(ctx context.Context, reqCtx *RequestContext) (*DetectionResult, error)
func (*Pipeline) DetectionBudget ¶ added in v0.4.5
func (p *Pipeline) DetectionBudget(reqCtx *RequestContext) time.Duration
DetectionBudget returns the effective analysis budget without starting it. Callers inspecting multiple identities can share this same bounded budget.
func (*Pipeline) SetDetectionBudget ¶ added in v0.4.5
SetDetectionBudget sets the CPU analysis budget, excluding body upload time. The bounded ceiling avoids accidentally retaining detector workers forever.
type ProtocolViolation ¶
type ProtocolViolation struct {
Detected bool
Type string // smuggling, chunked_abuse, encoding_abuse, header_injection
Severity Severity
Confidence float64
Message string
}
ProtocolViolation holds detected protocol-level violations.
func DetectProtocolViolations ¶
func DetectProtocolViolations(r *http.Request) *ProtocolViolation
DetectProtocolViolations checks the HTTP request for protocol-level attacks.
type RequestContext ¶
type RequestContext struct {
Request *http.Request // 原始 HTTP 请求 / Original HTTP request
ClientIP string // 客户端真实 IP / Real client IP
TraceID string // 溯源 ID / Trace ID for block pages
SiteID string // 站点 ID / Site identifier
// NormalizedPath is the canonical path used by security policies.
NormalizedPath string
// HostValidated is true only after the caller has matched Request.Host to
// an allowed site/tenant. Request-aware same-origin optimizations must not
// trust a raw, attacker-controlled Host value without this provenance.
HostValidated bool
// TrustedProxyCIDRs carries the immutable proxy trust scope used for
// request-aware protocol decisions (for example X-Forwarded-Proto).
TrustedProxyCIDRs []string
DecodedURI string // 解码后的 URI / Decoded URI
DecodedBody []byte // 解码后的请求体 / Decoded request body
Results []DetectionResult // 检测结果集合 / Detection results
Metadata map[string]any // 扩展元数据 / Extension metadata
// contains filtered or unexported fields
}
RequestContext carries all information about the current HTTP request through the detection pipeline. 承载当前 HTTP 请求在检测流水线中流转的所有信息。
func NewRequestContext ¶
func NewRequestContext(r *http.Request, siteID string) (*RequestContext, error)
func NewRequestContextDeferredBody ¶
func NewRequestContextDeferredBody(r *http.Request, siteID string, trustedCIDRs []string, maxBodyBytes int64) (*RequestContext, error)
NewRequestContextDeferredBody skips body I/O until EnsureBody (hot-path lazy-once).
func NewRequestContextDeferredBodyWithTrustedProxyPolicy ¶
func NewRequestContextDeferredBodyWithTrustedProxyPolicy(r *http.Request, siteID string, policy *TrustedProxyPolicy, maxBodyBytes int64) (*RequestContext, error)
NewRequestContextDeferredBodyWithTrustedProxyPolicy uses a precompiled proxy policy and skips body I/O until EnsureBody.
func NewRequestContextWithLimits ¶
func NewRequestContextWithLimits(r *http.Request, siteID string, trustedCIDRs []string, maxBodyBytes int64) (*RequestContext, error)
NewRequestContextWithLimits builds a context and eagerly reads the body.
func (*RequestContext) DetectionView ¶ added in v0.4.5
func (c *RequestContext) DetectionView(identity *http.Request) (*RequestContext, error)
DetectionView isolates one request identity while replaying this context's bounded immutable body snapshots. The identity's Body is never consumed.
func (*RequestContext) EnsureBody ¶
func (c *RequestContext) EnsureBody() error
EnsureBody reads and rewinds the request body at most once. Callers without a request context still receive the independent upload idle bound.
func (*RequestContext) EnsureBodyContext ¶
func (c *RequestContext) EnsureBodyContext(ctx context.Context) error
EnsureBodyContext materializes one shared body snapshot and waits for it with the caller's context. Only one reader worker is created per RequestContext; concurrent callers wait on the same completion channel. Snapshot publication is transactional: a read/decode error or cancellation never replaces the transport Body with bytes from an incomplete read.
type TrustedProxyPolicy ¶
type TrustedProxyPolicy = proxytrust.Policy
TrustedProxyPolicy is an immutable compiled client-IP trust policy.
func NewTrustedProxyPolicy ¶
func NewTrustedProxyPolicy(trustedCIDRs []string, providerCIDRs map[string][]string) (*TrustedProxyPolicy, error)
NewTrustedProxyPolicy binds provider-specific headers to their own CIDRs.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package decoder provides safe, bounded decoding helpers for the detection pipeline.
|
Package decoder provides safe, bounded decoding helpers for the detection pipeline. |
|
Package response detects sensitive data in upstream responses.
|
Package response detects sensitive data in upstream responses. |
|
Package rules implements configurable request matching for CheeseWAF.
|
Package rules implements configurable request matching for CheeseWAF. |
|
Package semantic provides semantic functionality for CheeseWAF.
|
Package semantic provides semantic functionality for CheeseWAF. |