Plugins & ExtensionsPro
Native extensions powered by Go plugin embed your security logic directly into the request pipeline — zero IPC overhead, millisecond response, shared memory with the main process.
What It Can Do
Detection Extensions
Inject business-specific detection on top of the built-in OWASP rule set: JWT validation, signature checks, bespoke regex, third-party threat-intel integration, etc.
Request / Response Rewriting
Inject headers, strip sensitive fields and rewrite response bodies before/after forwarding — for gray-release, A/B testing and compliance masking.
Audit & Alerting
Ship hit events to Kafka / Webhook / log platforms and enrich audit context with customer-specific fields.
Dynamic Rule Sources
Pull rules from a remote source / database / config center and hot-reload into the engine — differentiated delivery by tenant, domain and path.
Hook Positions
Each plugin declares its mount position in plugin.yaml, which decides at what stage of the request pipeline it intervenes; within the same position, plugins run in ascending order.
| Position | When It Fires | Typical Use |
|---|---|---|
front | Earliest — before ACL | Rewrite requests, deny by country / ASN, pre-counting |
before_cc | After ACL, before the CC check | Business-level rate limiting on traffic that already passed ACL |
before_waf | After CC, before the WAF rule engine (default) | UA validation, filename checks, scanner probing |
before_origin | After WAF passes, before forwarding to origin | Rewrite URL, inject headers |
after | After the origin responds, just before the response is written back | Log enrichment, response rewriting (use with care) |
Besides the pre-request hook, a plugin can also export the AfterResponse post-response hook, fired after the upstream response is written back — it only receives the request, status code and response headers (no body), ideal for status-code statistics and behavioral analysis. The built-in scan-guard uses it to detect 404 brute-forcing.
Lifecycle
- Load — Once a Pro license is active, scan the plugin directory for
.sofiles, resolve symbols viaplugin.Openand reject forbidden symbols. - Register — Call the exported
Initand, using the returned name, order and enabled state together with the position fromplugin.yaml, mount the plugin onto the matching hook. - Run — Each request triggers the hooks at the relevant position in
order; calls are wrapped inrecover, so a panic in one plugin never affects the main chain. - Hot Reload — Via the console or
POST /api/plugins/reload, re-readplugin.yamlto update the enabled state, order, position and target sites in real time — no restart required.
Minimal Example
Skeleton of a detection plugin (only depends on the net/http standard library, no extra SDK):
// myplugin-1.0.0/source/main.go
package main
import "net/http"
// Init returns (name, order, enabled, handler)
func Init() (string, int, bool, func(http.ResponseWriter, *http.Request) (*http.Request, bool)) {
return "myplugin", 10, true, Handler
}
// Handler is the pre-request hook
// Returns (newReq, stop): stop=true means blocked, stop=false continues the pipeline
func Handler(w http.ResponseWriter, r *http.Request) (*http.Request, bool) {
if r.Header.Get("X-Fake") == "1" {
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("blocked by myplugin"))
return nil, true
}
return r, false
}
Compile to a .so and deploy to the target node, then enable it in the console. See Plugin development guide.
Host API & Event Logging
A plugin may optionally export SetHostAPI to obtain controlled capabilities injected by the main process, and must export SetPluginLogger to report real-time events.
| Host API | Description |
|---|---|
addACLBlock | Write an IP into the central ACL blocklist with a TTL — managed together with the console ACL |
getClientIP | Resolve the client IP using the main process's trusted-proxy rules, fully consistent with WAF / ACL / CC |
isWhitelisted | Always returns false under the zero-trust policy; a plugin must never skip detection because an IP is whitelisted |
Real-time event logging is mandatory: call the logger on every block / hit / threshold trigger. The main process pushes events to the Plugin Management page over WebSocket, so you can see what a plugin is blocking at millisecond granularity.
Plugin Market & Import
No local Go environment needed: upload a zip source package under Plugin Management in the console, or paste a public zip URL for the main process to download — either path compiles with the same Go toolchain as the main program and hot-loads automatically.
- A plugin package is a single top-level directory named
<name>-<version>, containing thesource/code,version.jsonandREADME.md. - The main process validates the directory structure and version consistency; a compile failure is returned directly as an error, while success writes the plugin to the plugins directory and takes effect immediately.
- Imports include SSRF protection and zip-extraction safeguards, with a 50MB per-file limit.
Open-source Built-in Plugins
The repository's plugins/ directory ships 9 ready-to-use, reference-grade plugins (all mounted at before_waf):
| Plugins | What It Does |
|---|---|
ai-shield | AI training-crawler UA blocklist and prompt-injection detection; a hit triggers a temporary block |
auth-guard | Login-endpoint brute-force / credential-stuffing protection; a sliding-window failure count triggers an ACL block |
cloud-ssrf | Blocks cloud metadata addresses and dangerous schemes, with IP radix normalization |
filename-validator | Blocks dangerous characters, path traversal and null bytes in multipart filenames |
graphql-guard | GraphQL query-depth / alias limits and introspection blocking |
scan-guard | Directory-scan / 404 brute-force detection; a sliding-window threshold triggers a temporary block |
smuggler-guard | Detects HTTP request smuggling, CRLF injection and abnormal Content-Length |
tool-fingerprint | Scanner UA fingerprinting and OOB-domain detection; a hit triggers a block |
useragent-validator | Blocks empty / overlong User-Agents and scanner keywords |
Build Constraints
- Plugins must be compiled with the exact same Go toolchain version as the running main program (the current default build uses official
go1.26.4) and matching dependency versions — ABI mismatches cause load failures. This is an inherent constraint of Go'spluginpackage, not FOXWAF-specific. - Native
.sois supported only on Linuxamd64/arm64; on Windows / non-glibc distros use the script extension mechanism. - Plugins run as native code: enable only artifacts from trusted sources that have passed signature verification, and validate in a staging environment before production.
Open-source Repository
The SDK, example plugins and public rule sets live in the repositories below. Issues and PRs are welcome: