Download the PHP package rennf93/guard-core-php without Composer
On this page you can find all versions of the php package rennf93/guard-core-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download rennf93/guard-core-php
More information about rennf93/guard-core-php
Files in rennf93/guard-core-php
Package guard-core-php
Short Description PHP port of guard-core: behavioral WAF engine (detection engine conformance milestone)
License MIT
Informations about the package guard-core-php
guard-core-php
Guard Core PHP - API Security Core Engine for PHP language
guard-core-php
Guard Core PHP: the API security core engine for PHP. A framework-agnostic port of the guard-core detection engine that powers the PHP adapters: psr15-guard, laravel-guard, symfony-guard, and slim-guard.
Docs: https://rennf93.github.io/guard-core-php/
Install
Requires PHP ^8.2 with ext-pcre, ext-mbstring, and ext-json. The engine is consumed through the adapter packages or driven directly:
IP lists: whitelist vs exempt_ips
whitelist and exempt_ips answer different questions. A non-empty whitelist is restrictive: every IP not on it is denied by the global IP check. exempt_ips is noise reduction for known-friendly automation (monitoring probes, VPN egress, a partner's server): a listed IP or CIDR skips the rate-limit, user-agent and per-route cloud-provider checks, but it is not immunity. The blacklist, dynamic IP bans, the global block_cloud_providers list and penetration detection still apply to exempt IPs, the whitelist deny path is unchanged (an exempt IP does not pass a restrictive whitelist it is not on), and an invalid entry fails closed at config construction. Entries accept IPv4, IPv6 and IPv4-mapped forms with the same matching semantics as the whitelist.
Geo rate limits
Routes can carry per-country rate-limit tiers: RouteConfig::$geoRateLimits maps a country code ('DE') or the '*' fallback to a {limit, window} tier, mirroring the reference engines' @geo_rate_limit decorator. Country resolution is pluggable and the tiers only activate when a country resolver is configured on the rate limit handler: without a resolver the geo tier is inert and the default limit applies (a route can carry the map, but nothing fires until one is wired). The resolver is a Closure(string): string from client ip to country code (empty string when unknown, which takes the '*' fallback); adapters wire it after engine construction:
A request from a resolved country enforces that country's tier first ('*' when the country is missing from the map, nothing when neither matches), the tier shares the route's hashed bucket, and exempt and whitelisted clients still skip the check entirely.
Geo country blocking
Set blockedCountries and/or whitelistCountries and the ip_security check enforces them after the global IP lists: a non-empty whitelistCountries is restrictive (only listed countries pass, an unresolved country is denied), blockedCountries denies its matches, loopback IPs are exempt, and a global whitelist match skips the country stage entirely. Country rules with no resolver fail config construction: point geoIpDbPath at a locally provisioned MMDB file with top-level country records (the ipinfo country_asn.mmdb layout) or inject a CountryResolver. The engine never downloads databases.
CORS
Set enableCors: true and the engine runs the reference CorsHandler behavior: a preflight (OPTIONS carrying Access-Control-Request-Method) executes the security pipeline and is short-circuited with 200 OK or 400 Disallowed CORS: origin, method, headers, every blocked response carries the CORS verdict headers, and a disallowed origin on a normal request simply gets no CORS headers (the browser enforces). The wildcard-origin plus corsAllowCredentials combination fails config construction.
For pass-through (non-blocked) responses, adapters merge the per-request CORS map into their outgoing headers:
Security headers
By default the engine computes the reference security header set (port of
guard-core handlers/security_headers_handler.py): the ten class defaults
(X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN,
X-XSS-Protection: 1; mode=block,
Referrer-Policy: strict-origin-when-cross-origin,
Permissions-Policy: geolocation=(), microphone=(), camera=(),
X-Permitted-Cross-Domain-Policies: none, X-Download-Options: noopen, COEP/COOP/CORP
require-corp/same-origin/same-origin) plus
Strict-Transport-Security: max-age=31536000; includeSubDomains. Blocked
responses carry the headers engine-side (the fail-secure 500s included), and
blocked responses compose them with the CORS verdict headers when CORS is
enabled. For pass-through responses the adapter merges
GuardEngine::responseHeaders() with its outgoing headers. Setting
securityHeaders: ['enabled' => false] removes every security header.
Behavior rules
Attach behavior rules to a route (or globally with globalBehaviorRules):
usage/frequency rules count requests the pipeline allowed per (endpoint,
client) over a sliding window and dispatch ban/log/throttle/alert
when the count exceeds the threshold; return_pattern rules match outgoing
responses (status:<code>, json:<path>==<expected>, regex:<pattern>, or
a bare substring) and dispatch the same actions. Body-reading patterns
require behaviorScanResponseBody: true (they fail config construction
otherwise, mirroring the reference's fail-closed check) and read at most
behaviorMaxResponseBodyInspectBytes of the leading body.
Per-route detection exclusions
RouteConfig carries the reference detection-exclusion surface: enableSuspiciousDetection (route-level kill switch or opt-in, winning over the global flag), excludedDetectionParams, excludedDetectionBodyFields and enabledDetectionCategories (a non-null route set replaces the global one, an empty category list disables every category), excludedDetectionHeaders (always merged on top of the defaults and the global set, suppressing ssrf address-chain false positives only) and detectionScanBody (a false skips the request-body surface only).
Detection limits
Size-gated pattern family (large single-line subjects)
A family of detection patterns anchored at \A walks the subject one character
(or one path segment) at a time: the etc/passwd, boot.ini, proc/self/environ
and var/log line walks, the keyword-lookahead double walks, and the anchored
path-walk segment loops for .htaccess, wp-admin, .env, .git, recon path
targets and siblings (PatternData::SIZE_GATED_PATTERN_INDICES). PCRE2 consumes
stack proportional to the walked line, so on stock php:8.3 ini a benign
single-line subject can exhaust PCRE2 and abort detection entirely:
pcre.jit=1(default): failures from ~24.5KB subjects (PREG_JIT_STACKLIMIT_ERROR) for the line-walk shapes, and from ~16.4KB for the segment-loop shapes once a trailing target follows ~16KB of path segments (a/repeated is the stack-densest input, floor cliff ~16392 bytes).pcre.jit=0: failures from ~100KB subjects (PREG_RECURSION_LIMIT_ERROR).
Mitigation: when a view subject's first line reaches
SusPatterns::GATED_PATTERN_MAX_SUBJECT_BYTES (15360, 15 KiB), the preg calls
of that family are skipped for the rest of the scan (no match contribution) and
detection completes normally. The threshold sits below the ~16.4KB segment-loop
cliff and above the largest conformance corpus content (14725 bytes), so it
holds under either pcre.jit setting (ini-independent) and never changes
conformance behavior.
Coverage trade-off: walk and segment patterns are line-scoped, so skipping above the gate only forgoes their coverage on very long single-line subjects (15KB or more in one line). All other patterns still scan the full subject, and probes in shorter lines or multiline bodies are unaffected.
All versions of guard-core-php with dependencies
ext-pcre Version *
ext-mbstring Version *
ext-json Version *