Repository navigation
Releases: Guard-Core/guard-core-go
Release list
v4.3.2
v4.3.2 (2026-10-09)
The adapter-parity release: the ReDoS static-safety trio, the sus-patterns runtime registry, the custom_response_modifier response pass, the engine websocket guard, the fifteen SecurityConfig knobs with the performance-monitor wiring, and the lifecycle and state surface the adapters drive
guard-core-go v4.3.2 mirrors the guard-core 4.3.2 release: the reference's ReDoS static-safety chain ports verdict-exact onto the engine and takes over the pattern_safety corpus (the registry retires), the sus-patterns runtime registry lands with its telemetry and dynamic-rules application, engine-produced responses gain the custom_response_modifier pass, the websocket guard the adapters expose ports at the engine with suspicious counts shared with the HTTP pipeline, the remaining reference SecurityConfig surface arrives (fifteen knobs plus the performance-monitor wiring), and the lifecycle/state surface the Go adapters drive (manager exports, is_initialized, the cross-instance middleware state registry, MarkInitialized/AgentStats) closes the rows the fastapi-guard parity work left open. The dependency train clears the stdlib-adjacent x/sys exposure, and the post-transfer metadata sweep repoints the repo at the Guard-Core org.
Added
- The ReDoS static-safety trio, with the pattern_safety corpus going registry-free (#58): a Python-re-compatible pattern parser (
guardcore/redos_parser.go+redos_escape.go, sre_parse's group numbering and octal-vs-group-reference disambiguation mirrored) feeding the ordered structural prefilters (redos_structure.go,redos_terminator.go,redos_ambiguous.go), the dangerous-construct gate with the reference's three regexes verbatim (redos_prefilters.go), the reach-probe cost machinery (probe synthesis, interval algebra, class-intersection units, adversarial literal runs,redos_reach_probe.goand friends), stray verification against the compiled engine under a MatchTimeout and the cost arbiter (size ladders, growth-ratio extrapolation to the content cap, load-factor normalization, the measured-override branch) with the fail-closed equivalent of the reference's killable subprocess, andValidatePatternSafety(redos_compiler.go) reproducingvalidate_pattern_safety's chain order.go_safety_xfail.jsonis deleted and its 54 cases come off the registry with matching verdicts and reason classes (94/94 pass, 0 divergences, and the runner fails on a re-added baseline file); a CodeQL-flagged uint32-to-rune narrowing inparseHexEscapeis bound-checked before conversion. - The sus-patterns runtime registry, pattern events and dynamic-rules application (#59): the
SusPatternsManagerruntime registry (the reference module singleton as the package default) with safety-validatedAddPattern/RemovePattern(custom entries dedupe and persist through thepatterns/customRedis key), the Redis-persisted custom restore onInitializeRedis,DetectPatternMatch(redacted regex identity, thesemantic:prefix, the unknown fallback), and the manager'sDetectrunning the shipped corpus scan plus the runtime registry with the referencepattern_detectedenvelope;SecurityEventgains thepattern_matchedcolumn, the pipeline's penetration detection rides the manager so runtime patterns participate, and the dynamic-rulessuspicious_patternsapplication is real (every pattern runs the registry's safety-validated add, rejections log with the reference honesty). The three sus-patterns event xfails leave the registry (6 to 3, the rest being host error-text renderings). - The custom_response_modifier response pass (#60):
SecurityConfig.CustomResponseModifierruns the user callback over engine-produced responses before they leave the middleware (a panicking callback is contained with the referencecustom_response_modifier raisedmessage and the unmodified response goes out; a nil result keeps the incoming response), wired at the reference call graph's sites (createErrorResponse/errorResponselast on every pipeline error response, the https_enforcement redirect with no header pass, the custom_request check's blocking response in blocking mode), withEngine.ModifyResponseexposing the pass to the adapters for pass-through composition. - The websocket handshake guard with shared suspicious counts (#61):
Engine.GuardWebSocketruns the reference_run_websocket_checkssequence (identity resolution, the fail-secure unknown-address close, the ban probe, theis_ip_allowedverdict with the whitelist gate and its country-stage skip, the ws-endpoint rate limit, the penetration detection pass) with the six reference close reasons (WebSocketCloseReason, 1008 policy violations and 1013 try-again-later); the engine retains the pipeline'ssuspiciousCountStoreso the websocket detection pass and the HTTPsuspicious_activitycheck key the same per-IP registry, the detection check runs with an inert event stream exactly like the reference's None-handler bus, and Redis containment mirrors_guarded_redis_call(fail-open rate-limit arm, surfaced errors reaching the fail-secure 1013 close). - The fifteen SecurityConfig knobs and the performance-monitor wiring (#62): the five redis tuning knobs (socket connect/read timeouts as tri-state pointers, health check interval, pool cap, retries),
body_read_timeout+sync_body_read_max_concurrent(every engine-side body read raced against the timeout under a package-level slot budget, the reference daemon-thread join semantics),log_country_check_level(the global country stage's verdict lines),agent_strict+on_error(the agent_init and geoip hook stages with panic containment),detection_pattern_validation_cache_path(the disk-backed cache over the empirical cost-verdict arm, keyed by pattern and flags with a pinned engine version), and the per-request scan budgets (detection_max_scan_values,detection_max_scan_chars,detection_max_json_depth, the_scan_value_budgetparity with once-per-request client-named warnings and the JSON walk serializing too-deep containers back to text). - The lifecycle and state surface the adapters drive (#63, #64, #65, #66): the manager surface exports (
InMemoryCloudIPStore.Clear/RedisCloudIPStore.Clear,GeoIPManager.EntryCount,RedisManager.GetConnection/SafeOperation/Incr/Existswith theredis_erroremission on contained failures),GeoIPManager.IsInitialized(the pure predicate that never triggers the lazy load), the cross-instance middleware state registry (the_middleware_state.pyport:Engine.Initializeadopts a registered warm state for its (config, decorator) key instead of re-initializing and registers itself after a successful startup, failed startups register nothing, and the websocket detection pass resolves the registered stack's suspicious-counts store before its own), andMarkInitialized/AgentStatswith the optionalAgentStatsProviderseam (a warmed engine makesInitializea no-op; agentless answers{enabled: false, degraded}, a wired handler merges its stats dict).
Changed
- Dependencies:
github.com/redis/go-redis/v9to v9.23.0 (#67), carryinggo.uber.org/atomicv1.12.0 andgolang.org/x/sysv0.48.0, which clears on the engine side the stdlib-adjacent x/sys exposure the adapters clear through the x/net v0.60.0 bumps; govulncheck stays clean. - Post-transfer metadata sweep (7b862bc): repo URLs, the docs site, issue-template links, the ecosystem-gate matrix, mkdocs repo fields, SECURITY advisory links, the CoC contact and the FUNDING github entry point at the Guard-Core org, and
.github/CODEOWNERS(* @rennf93) lands so the master code-owner ruleset is enforced. Module paths, Go imports, and the CHANGELOG history line are deliberately unchanged (the canonical import path rename is a separate operator decision; old URLs keep resolving via GitHub redirects).
v4.3.1
v4.3.1 (2026-10-07)
The family-parity release: route-id ownership with per-route behavioral counters, the trusted-proxy XFF chain walk, agent event enrichment, the composite/OTel/Logfire agent handlers, structured JSON logging and the cost-parity detection loop
guard-core-go v4.3.1 tracks the guard-core 4.3.1 engine release from the consumer side: the route-id ownership contract from @HardMax71's report lands (every decorated endpoint owns its route id, and behavioral counters key on it), the trusted-proxy identity resolution walks the X-Forwarded-For chain exactly like the reference instead of keying every verdict on the proxy IP, the agent stream gains the reference enrichment tier and the pluggable composite/OTel/Logfire handlers with structured JSON logging, and the detection loop carries the cross-engine cost-parity program (literal prefilter, rune-API scan migration, fail-closed cost ceilings) with verdicts pinned unchanged.
Added
- Agent event enrichment: the reference enrichment tier (
guardcore/enricher.go, #56): the eightguard.*wire keys (project id, service name, deployment environment, threat score, rule id/version, behavior correlation key plus the recent event count),ThreatScoreFor's deterministic per-type map (default 20), the 300s behavior-correlation window and thesha256(ip|service|bucket)[:16]correlation key, with the enrichment order mirroring the reference strategy chain (identity, threat score, rule correlation, behavior correlation) and events without a metadata map shipping unenriched likeenrich_event's early return;CompositeAgentHandlergains the reference's enricher parameter (filter, enrich, then fan out),SecurityConfigtheEnableEnrichment/AgentProjectID/OtelServiceName/OtelResourceAttributesblock with the reference validation, the installed engine stream wraps the raw handler in the enriching composite with the liveDynamicRuleManageras the rule-correlation matcher, and redaction is untouched (the bus still redacts at event build; enrichment only adds derived non-sensitiveguard.*keys) (#56). - The composite, OTel and Logfire agent handlers plus the adaptation seam (#55):
CompositeAgentHandlerfans out to N sinks behind theEventFiltermute lists with per-child failure isolation (a failing sink is logged, never propagated), start-degradation tracking (Started/Degraded/FailedHandlers),Stop/Flushfan-out, dynamic rules resolved from the first child that provides them and all-children health;OtelHandlerrenders security events asguard.event.<type>spans with theguard.*attribute set and W3C traceparent linkage and maps metrics onto theguard.request.durationhistogram and theguard.request.count/guard.error.countcounters, speaking OTLP/HTTP JSON directly (guardcore keeps its three-direct-dependency rule and owns no global provider state);LogfireHandleremits events as spans and metrics asguard.metric.<type>structured log records over OTLP toward the Logfire API with the reference's already-configured guard reproduced as a per-process claim; andAgentHandlerFuncis the interface-mismatch alignment (guard-agent-go's context-carryingSendEventand its own SecurityEvent wire type wrap through the seam onto the engine stream unchanged) (#55). - Structured JSON logging with the
setup_custom_loggingparity surface (guardcore/logging_json.go, #55):JsonFormatterrenders the reference record shape one JSON object per line (timestamp in the Python asctime format, level, logger, message) while the reference text line stays the default, andSetupCustomLogging(logFile, logFormat)(re)installs the guardcore stream with own-handler replacement semantics, console+file fan-out, the unwritable-path fallback and therestoreStandardLoggingescape hatch;SecurityConfig.LogFormat(text|json, validated) andLogFilewire throughNewEnginebefore any manager is built, mirroring the reference middleware's construction-timesetup_custom_loggingcall (#55). - The cost-parity detection program (
guardcore/literal_prefilter.go,cost_budget_test.go+ the 9-casecost_bodiescorpus suite, #54): the tempered-loop anchored recon families skip when none of their alternation literals occur in the text (a match-impossible condition, so verdicts cannot change; the extractor is unit-tested against the full pattern table to fire only on the intended shapes), the base64 scan loops migrate to the rune API (convert once, scan runes; the string API re-converted the remaining suffix to runes on every match attempt, quadratic across a scan), and the corpus's self-relative scan-cost ceilings are enforced fail-closed (K=5 x the 8 KiB anchor's linear projection + 250 ms floor; a workload over ceiling fails and an entry listed as over ceiling that returns under it fails too). Measured: 8 KiB 54.1 -> 20.0 ms, 64 KiB 1100 -> 142 ms, 256 KiB 12253 -> 710 ms, 1 MiB 138586 -> 4626 ms; verdicts 193/193 unchanged; the full conformance+cost run drops from 635 s to 25.8 s (#54).
Fixed
- Route-id ownership and per-route behavioral counters (reported by @HardMax71 in guard-core #140; the reference fix shipped in guard-core #141/#142 and 4.3.1): endpoints built by one decorator factory (or one handler-wrapper table) share one
RouteConfigonly when they share a route id - the Go registry grants everyRoutes.Register(routeID, ...)call its ownRouteConfiginstance, so there is no shared-config last-wins overwrite to fix on this side, and the adapter contract (RequestState.GuardRouteID, the adapters'WithRouteIDhelpers) pins one id per decorated endpoint.GetEndpointIDnow resolves exactly like the referenceget_endpoint_id: the request's route id wins, then the runtime-providedguard_endpoint_idextra, elseMETHOD:redacted-path- previously the route id was never read, so behavioral usage/return counters keyed onMETHOD:pathand collapsed across routes sharing a path shape (#141, #142). - The trusted-proxy XFF chain walk (
guardcore/ipextraction.go, theip_extraction.pyparity, #55): the reference resolves the client identity throughX-Forwarded-Forwhen the direct peer is a configured trusted proxy; this port shipped peer-address-only resolution, so behind a load balancer bans, rate limits, geo rules and behavioral keys all keyed on the proxy IP, andTrustedProxyDepthwas validated but never read. Faithful port: CIDR-aware trusted-peer matching (mapped forms resolve through the prefix, bare entries match textually like the reference), the depth-selected entry counting from the right with the right-to-left walk taking over when the depth over-counts hops, chain-shorter-than-depth/malformed/all-trusted chains keeping the peer, the untrusted-peer spoof arm (handler-directsuspicious_request, handlerip_extraction, actionspoofing_detected, the redacted display chain at debug level for private/loopback peers), the four once-per-process drift warnings carrying the reference texts, andEngine.Checkresolving and caching the identity intoRequestState.ClientIPbefore the pipeline so every consumer (rate limits, bans, geo, behavioral keys, events, block hooks) keys on the resolved client (#55).
v4.3.0
v4.3.0 (2026-10-01)
The corpus-parity release: the pattern_safety, events and redis_interop corpus kinds run against the engine, the spec 12 event stream lands, and the geo country verdict moves to the manager
guard-core-go v4.3.0 tracks the guard-core 4.3.0 safety-corpus release from the consumer side: the conformance runner now consumes every corpus suite kind the reference publishes, the engine's observable event surface is ported and validated against the events corpus (32 of 38 cases reproduce the reference envelopes end to end, the remaining 6 carry narrowed fail-closed baseline reasons), the detection performance monitor, the security-headers Redis cache and the RE2 pattern translation ledger complete the spec parity wave, and the coverage and staticcheck gates are wired fail-closed into CI.
Added
- The security event bus, metrics collector and dynamic-rules agent pipeline (spec 12's observable event stream) (
guardcore/events.go+eventswiring.go, #42): the full 39-event plus 3-metric vocabulary pinned by a vocabulary test including the two documented asymmetries (behavioral_violation,emergency_mode_activated); the reference envelope (timestamp, event_type, ip_address with the unknown fallback, country via the geo resolver, redacted user_agent and endpoint, method, response_time, decorator_type, rule_type, handler_name middleware, metadata with traceparent/tracestate forwarding) with the route-vs-globalhttps_violationdispatch; bus-routed events gated byagent_enable_eventsand the event mute filter while the handler-direct emitters (ip_ban, rate_limit, behavior, dynamic_rules, cloud, ipinfo) bypass both exactly like the reference handlers, send failures logged and never raised; and theMetricsCollectortrio (response_time, request_count, error_rate on >= 400) underagent_enable_metrics. The four detection-engine anomaly/callback names are owned by the performance monitor port with no duplicate declarations (#41). A review-pass fidelity wave then aligned every emission the corpus pins:ip_blocked(filter_type banned) andip_ban_failedcarry the ip_address kwarg,cloud_blockedannounces the provider and network metadata with the route-tierblock_cloudsdecorator_violation, the user-agent check splits the route decorator_violation from the globaluser_agent_blockedreason, the tiered rate-limit events quote the tier's configured limit with the reference route/geo/endpoint reason strings instead of the tripping count, dynamic-rules deliveries validate the reference ge=1 constraints on auto_ban_threshold/auto_ban_duration whole (an out-of-range delivery is rejected with the previous rules left active and an unusable last-known snapshot is skipped in hydration), handler-direct events bypass the mute filter,emergency_mode_blockcarries the reference event reason, andcustom_request_checkcarries check_function (#42). - The detection-engine performance monitor (
guardcore/performance_monitor.go, #41): a stdlib-only, concurrency-safe port of the reference monitor family (monitor.py,monitor_types.py,monitor_anomalies.py,monitor_reporting.py). The constructor clamps exactly likePerformanceMonitor.__init__(anomaly_threshold [1, 10], slow_pattern_threshold [0.01, 10], history_size [100, 10000], max_tracked_patterns [100, 5000], anomaly_emission_cooldown [1, 3600] seconds, min_samples_for_anomaly [10, 1000]); the anomaly trio is the reference's (timeout, slow execution suppressed for timeout samples, and the statistical z-score over the rolling window with the n-1 denominator where the current sample joins the window before the check, one sample able to trip slow plus statistical);RecordMetricparity covers the 100-rune pattern-name truncation with the...[truncated]suffix, negative-input clamping, timeout samples counted but never admitted to the timing window, first-inserted eviction at max_tracked_patterns and the history/window ring caps; and callbacks receive anomalies with the pattern name run through the ported_redact_pattern_source(escape-decoding, non-token stripping, sensitive-name collapse to[REDACTED]) (#41). - The security-headers Redis cache (
guardcore/securityheaders_cache.go, #43): the referenceSecurityHeadersCacheMixinplus the manager's headers TTL cache. TheSecurityHeadersManagerholds the resolved header-configuration state with the bounded TTL cache (1000 entries, 300s per-entry expiry, the reference cache-key grammardefault/path_ + sha256(lower(path))[:16]with the per-instance prefix) andGetHeadersmirroringget_headers(disabled yields no headers, a hit returns the stored set, a miss computes through the shared responseHeaders builder). The cross-worker sync contract:LoadCachedConfigloads the csp/hsts/custom blocks independently with per-entry custom-header validation (failures log and keep the current state) andCacheConfigurationpersists every non-empty block as JSON with the 86400s TTL; a loaded configuration overrides the bound state so the next cache miss picks it up, andResetpurges the cache, restores the bound default, deletes thesecurity_headers:*keys and detaches the handler (#43). - The RE2 pattern translation ledger (
conformance/pattern_ledger.go+ the generatedpattern_ledger.json, #40): the specs' default regex-engine direction (RE2 plus recorded translations, the corpus as referee). Every distinct regex pattern firing in the vendored spec 4.1.0 detect corpus (71 patterns) lands in exactly one status: as_is (46, compiles unchanged with stdlib regexp), translated (3, the recorded\Zto\zrewrite with verified_on corpus cases whose recorded match and position the translation reproduces on the raw input) or unmatchable (22, the RE2-blocking constructs with a documented detection limit per entry, not silence). The referee tests recompute every status from the live corpus and fail on an unexpected status change, verify the translated entries still reproduce their corpus evidence, and guard against vacuous passes (#40). - The conformance runner consumes the full corpus: the pattern_safety, events and redis_interop kinds (#48): the vendored suites refresh to the reference 4.2.0 stamp with every existing detect and pipeline case byte-identical, and the three new kinds gain runners that drive the real engine and compare per the index comparison blocks. pattern_safety (safety_gates.json, 94 cases) maps the reference verdicts where the Go surface reaches: 29 safe cases pass compile plus bounded execution over the corpus test strings, 11 of 12 compile_failed cases reproduce exactly, and the structural/dangerous-construct/over_budget classes ride the fail-closed baseline with the class divergence tied to the Go source. events (event_stream.json, 39 cases) drives a recording agent handler over the real bus and performance monitor (12 cases reproduced end to end when the runner landed, flipped to 31 by the closures below and 32 by the geo verdict). redis_interop (redis_interop.json, 14 cases) drives the real handlers against live Redis with a loud skip without REDIS_HOST: 10 cases produce byte-identical keys, types, TTL semantics, values and member shapes. All three baselines are fail-closed in the established style: an unbaselined failure is red, a baselined case that starts reproducing the reference verdict is red (stale), and a baselined case that never ran is red. Engine changes the corpus forced, kept minimal: the dynamic rules last-known snapshot dump normalizes nil collections to the pydantic model defaults (restoring the spec 08 byte-equality contract, pinned by a unit test), the exported lifecycle seams
GeoIPManager.SetDownloadEndpointandCloudManager.SetRangeFetcherreplace the corpus harnesses' monkeypatch points with unit coverage, and the detect runner and pattern ledger skip non-detect kinds by schema probe (#48). - The events surface closed to reference parity (#50): the events runner moves from 12 to 31 of 38 passing, the remaining seven carrying narrowed per-case reasons in the fail-closed baseline. New surface, each mapped against its reference emitter: the
SecurityHeadersEventsMixinannouncessecurity_headers_appliedon cache misses for non-empty paths with a handler attached andValidateCSPReportgates on the three required fields, redacts the report fields and emitscsp_violation(both rideSetAgentHandlerand fail soft);RedisManager.Initializeemitsredis_connection/redis_errorhandler-direct with the credential-redacted URL and error_type metadata; the pipeline emitssecurity_bypasson the all-checks bypass,path_excludedon the exclusion matcher (once per path per the reference 300s TTL cache),content_filteredon the request-size and content-type arms, and the untrusted-proxysuspicious_request(spoofing_detected, handler ip_extraction); the identity-violation escalation is ported (a global IP deny that carries an attack payload records its categories in the shared registry, applies the threshold ban with per-category threat entries first then the flat total, and emits the Identity violation escalated penetration_attempt, while a ban failure emitsip_ban_failedand aborts the announcement exactly like the reference exception path, withSetBanFaultas the exported deterministic seam); and envelope parity lands (the decorator_type/rule_type kwargs stay in metadata beside the promoted columns per the reference_build_event, behavioral_violation reports the rule action with the rule_type column, rate_limited rides every tripped tier with the full middleware columns and the display_config limit, the route auth denial carries the raw auth reason, and custom_request_check quotes the configured ...
v4.2.0
v4.2.0 (2026-09-27)
The parity release: full parity with guard-core 4.2.0, validated against the conformance corpus (spec 4.1.0)
guard-core-go v4.2.0 is the parity release for the guard-core 4.2.0 engine release: every behavior surface that shipped since v4.1.0 is ported and validated against the shared conformance corpus (guard-core-spec-4.1.0, 219 cases across the five pipeline-kind suites). Note on the 4.1.0 family tags: the 4.1.0 engine tags across the family were a version-accuracy error (the tagged trees did not carry the full advertised surface) and were yanked/unpublished; v4.2.0 is the accurate parity baseline. ### Added - Behavior rules: the reference behavioral surface runs instead of fail-closed rejecting global_behavior_rules (guard_core handlers/behavior_handler.py, core/behavioral/processor.py): SecurityConfig.GlobalBehaviorRules/BehaviorScanResponseBody/BehaviorMaxResponseBodyInspectBytes, per-route BehaviorRules, the BehaviorTracker sliding windows over Redis with the shared key layout, ApplyAction ban/log/throttle/alert dispatch with passive-mode logging and the 3600s ban fallback, usage/return/global-return pattern rules (status:/json:/regex:/substring, correlate_with_detection threshold halving over the shared suspicious-count store), and the new Engine.ProcessResponse for adapters' response-side return rules (#26). - Geo lifecycle and events: the reference IPInfoManager lifecycle (bearer-authenticated download of the free country_asn database with three attempts and 1s/2s/4s backoff, atomic temp-file write, Redis database cache copy with the max-age TTL served before any download, mtime-based staleness, fail-soft initialize/refresh) plus country_blocked, geo_lookup_failed, database_download_failed and the route-level decorator_violation events with reference attribution fields, fired through the new OnGeoEvent hook (#27). - Per-route detection exclusions: RouteConfig.ExcludedDetectionHeaders/Params/BodyFields, EnabledDetectionCategories and DetectionScanBody plus the global DetectionScanBody, resolved through the reference _resolve_* shape (headers always merge over the hardcoded defaults), and the suspicious_activity check applies the per-route enable_suspicious_detection verdict (#28). ### Fixed - 429 responses carry Retry-After from the tier window that tripped, and the rate-limit check resolves the route tier (RouteConfig.RateLimit/RateLimitWindow) alongside the endpoint and global tiers like the reference (#29). - CORS response surface corrections: normal responses compose Access-Control-Allow-Methods/Headers and the reference's 3600 Max-Age, and the wildcard plus credentials combination is accepted at construction and downgraded at policy resolution (credentials dropped, wildcard answers without the allow-credentials header) matching the reference _compute_cors_config (#29, #30). - Passive-mode on_block hook payloads carry the reference log-format reasons with an empty trigger_info, report a null status_code, and the ip_security/deny paths fire inline in passive mode like the reference (#30). ### Conformance - The spec 4.1.0 corpus is vendored (guard-core-spec-4.1.0/cases, byte-identical to the guard-core specs fixtures) with a fail-closed xfail baseline runner (TestPipelineConformance); the 26 baseline entries shipped with the corpus adoption are all cleared: pipeline gate 35 passed, 0 failed, 0 xfail, 0 config divergences (#29, #30).
v4.0.4
Full parity with guard-core 4.0.4, binary-noise gates, and the /v4 module path (v4.0.4)
Breaking Changes
- Import paths now end in
/v4. The module path isgithub.com/rennf93/guard-core-go/v4and the release tag isv4.0.4; Go modules reject av4+tag unless the module path carries the/v4suffix, so the migration is mandatory for this release to be fetchable. Update every import fromgithub.com/rennf93/guard-core-go/guardcoretogithub.com/rennf93/guard-core-go/v4/guardcore(and the same for theexamples/...internal packages). Installation is nowgo get github.com/rennf93/guard-core-go/v4@v4.0.4. The earlierv0.1.0tag was a burned pre-release snapshot of the port and remains on the un-suffixed path.
Added
- Full check parity with the Python guard-core 4.0.4 engine: 17/17 security checks. The port now covers the complete check catalogue of the Python engine, including the 4.0.x additions.
- Binary-noise gates for detection, including the SQLi comment-terminator binary gate. Pattern sources prone to firing inside text-decoded binary bodies (PDFs, compressed streams) are registered in a noise-prone registry and gated by binary-density analysis, while genuine ASCII-region matches still detect. The SQLi comment-terminator source joins the registry in this release (parity with upstream guard-core
f5d53ca5): the pattern's apostrophe-plus-whitespace-before---shape routinely matched0x27 0x0A 0x2D 0x2D-style byte runs inside binary content. - Corpus harmonization with guard-core 4.0.3/4.0.4. The conformance corpus tracks the Python engine's fixtures at spec 4.0.3/4.0.4, including binary-body vectors, so the two engines are validated against the same detection expectations.
- Interop harness at 82/82. The cross-implementation runner (
go test -tags interop) executes the Python-engine fixture corpus against the Go engine with full agreement.
Changed
- Makefile harmonized with the Python guard family.
install,test(unit plus-tags integrationin docker),lint(gofmtcheck plusgo vet),bump-version(via.github/scripts/bump_version.py, which scaffolds this changelog) andcleanmatch the conventions used across the Python guard repos.