Skip to content

Releases: Guard-Core/guard-core-go

v4.3.2

Choose a tag to compare

@rennf93 rennf93 released this 09 Oct 07:39
Immutable release. Only release title and notes can be modified.
v4.3.2
2fce792

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.go and 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, and ValidatePatternSafety (redos_compiler.go) reproducing validate_pattern_safety's chain order. go_safety_xfail.json is 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 in parseHexEscape is bound-checked before conversion.
  • The sus-patterns runtime registry, pattern events and dynamic-rules application (#59): the SusPatternsManager runtime registry (the reference module singleton as the package default) with safety-validated AddPattern/RemovePattern (custom entries dedupe and persist through the patterns/custom Redis key), the Redis-persisted custom restore on InitializeRedis, DetectPatternMatch (redacted regex identity, the semantic: prefix, the unknown fallback), and the manager's Detect running the shipped corpus scan plus the runtime registry with the reference pattern_detected envelope; SecurityEvent gains the pattern_matched column, the pipeline's penetration detection rides the manager so runtime patterns participate, and the dynamic-rules suspicious_patterns application 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.CustomResponseModifier runs the user callback over engine-produced responses before they leave the middleware (a panicking callback is contained with the reference custom_response_modifier raised message and the unmodified response goes out; a nil result keeps the incoming response), wired at the reference call graph's sites (createErrorResponse/errorResponse last on every pipeline error response, the https_enforcement redirect with no header pass, the custom_request check's blocking response in blocking mode), with Engine.ModifyResponse exposing the pass to the adapters for pass-through composition.
  • The websocket handshake guard with shared suspicious counts (#61): Engine.GuardWebSocket runs the reference _run_websocket_checks sequence (identity resolution, the fail-secure unknown-address close, the ban probe, the is_ip_allowed verdict 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's suspiciousCountStore so the websocket detection pass and the HTTP suspicious_activity check 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_budget parity 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/Exists with the redis_error emission on contained failures), GeoIPManager.IsInitialized (the pure predicate that never triggers the lazy load), the cross-instance middleware state registry (the _middleware_state.py port: Engine.Initialize adopts 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), and MarkInitialized/AgentStats with the optional AgentStatsProvider seam (a warmed engine makes Initialize a no-op; agentless answers {enabled: false, degraded}, a wired handler merges its stats dict).

Changed

  • Dependencies: github.com/redis/go-redis/v9 to v9.23.0 (#67), carrying go.uber.org/atomic v1.12.0 and golang.org/x/sys v0.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

Choose a tag to compare

@rennf93 rennf93 released this 07 Oct 01:30
v4.3.1
056c785

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 eight guard.* 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 the sha256(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 like enrich_event's early return; CompositeAgentHandler gains the reference's enricher parameter (filter, enrich, then fan out), SecurityConfig the EnableEnrichment/AgentProjectID/OtelServiceName/OtelResourceAttributes block with the reference validation, the installed engine stream wraps the raw handler in the enriching composite with the live DynamicRuleManager as the rule-correlation matcher, and redaction is untouched (the bus still redacts at event build; enrichment only adds derived non-sensitive guard.* keys) (#56).
  • The composite, OTel and Logfire agent handlers plus the adaptation seam (#55): CompositeAgentHandler fans out to N sinks behind the EventFilter mute lists with per-child failure isolation (a failing sink is logged, never propagated), start-degradation tracking (Started/Degraded/FailedHandlers), Stop/Flush fan-out, dynamic rules resolved from the first child that provides them and all-children health; OtelHandler renders security events as guard.event.<type> spans with the guard.* attribute set and W3C traceparent linkage and maps metrics onto the guard.request.duration histogram and the guard.request.count/guard.error.count counters, speaking OTLP/HTTP JSON directly (guardcore keeps its three-direct-dependency rule and owns no global provider state); LogfireHandler emits events as spans and metrics as guard.metric.<type> structured log records over OTLP toward the Logfire API with the reference's already-configured guard reproduced as a per-process claim; and AgentHandlerFunc is the interface-mismatch alignment (guard-agent-go's context-carrying SendEvent and its own SecurityEvent wire type wrap through the seam onto the engine stream unchanged) (#55).
  • Structured JSON logging with the setup_custom_logging parity surface (guardcore/logging_json.go, #55): JsonFormatter renders 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, and SetupCustomLogging(logFile, logFormat) (re)installs the guardcore stream with own-handler replacement semantics, console+file fan-out, the unwritable-path fallback and the restoreStandardLogging escape hatch; SecurityConfig.LogFormat (text|json, validated) and LogFile wire through NewEngine before any manager is built, mirroring the reference middleware's construction-time setup_custom_logging call (#55).
  • The cost-parity detection program (guardcore/literal_prefilter.go, cost_budget_test.go + the 9-case cost_bodies corpus 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 RouteConfig only when they share a route id - the Go registry grants every Routes.Register(routeID, ...) call its own RouteConfig instance, so there is no shared-config last-wins overwrite to fix on this side, and the adapter contract (RequestState.GuardRouteID, the adapters' WithRouteID helpers) pins one id per decorated endpoint. GetEndpointID now resolves exactly like the reference get_endpoint_id: the request's route id wins, then the runtime-provided guard_endpoint_id extra, else METHOD:redacted-path - previously the route id was never read, so behavioral usage/return counters keyed on METHOD:path and collapsed across routes sharing a path shape (#141, #142).
  • The trusted-proxy XFF chain walk (guardcore/ipextraction.go, the ip_extraction.py parity, #55): the reference resolves the client identity through X-Forwarded-For when 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, and TrustedProxyDepth was 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-direct suspicious_request, handler ip_extraction, action spoofing_detected, the redacted display chain at debug level for private/loopback peers), the four once-per-process drift warnings carrying the reference texts, and Engine.Check resolving and caching the identity into RequestState.ClientIP before the pipeline so every consumer (rate limits, bans, geo, behavioral keys, events, block hooks) keys on the resolved client (#55).

v4.3.0

Choose a tag to compare

@rennf93 rennf93 released this 01 Oct 20:12
v4.3.0
4c48eb2

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-global https_violation dispatch; bus-routed events gated by agent_enable_events and 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 the MetricsCollector trio (response_time, request_count, error_rate on >= 400) under agent_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) and ip_ban_failed carry the ip_address kwarg, cloud_blocked announces the provider and network metadata with the route-tier block_clouds decorator_violation, the user-agent check splits the route decorator_violation from the global user_agent_blocked reason, 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_block carries the reference event reason, and custom_request_check carries 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 like PerformanceMonitor.__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); RecordMetric parity 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 reference SecurityHeadersCacheMixin plus the manager's headers TTL cache. The SecurityHeadersManager holds the resolved header-configuration state with the bounded TTL cache (1000 entries, 300s per-entry expiry, the reference cache-key grammar default / path_ + sha256(lower(path))[:16] with the per-instance prefix) and GetHeaders mirroring get_headers (disabled yields no headers, a hit returns the stored set, a miss computes through the shared responseHeaders builder). The cross-worker sync contract: LoadCachedConfig loads the csp/hsts/custom blocks independently with per-entry custom-header validation (failures log and keep the current state) and CacheConfiguration persists 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, and Reset purges the cache, restores the bound default, deletes the security_headers:* keys and detaches the handler (#43).
  • The RE2 pattern translation ledger (conformance/pattern_ledger.go + the generated pattern_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 \Z to \z rewrite 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.SetDownloadEndpoint and CloudManager.SetRangeFetcher replace 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 SecurityHeadersEventsMixin announces security_headers_applied on cache misses for non-empty paths with a handler attached and ValidateCSPReport gates on the three required fields, redacts the report fields and emits csp_violation (both ride SetAgentHandler and fail soft); RedisManager.Initialize emits redis_connection / redis_error handler-direct with the credential-redacted URL and error_type metadata; the pipeline emits security_bypass on the all-checks bypass, path_excluded on the exclusion matcher (once per path per the reference 300s TTL cache), content_filtered on the request-size and content-type arms, and the untrusted-proxy suspicious_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 emits ip_ban_failed and aborts the announcement exactly like the reference exception path, with SetBanFault as 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 ...
Read more

v4.2.0

Choose a tag to compare

@rennf93 rennf93 released this 27 Sep 18:43
v4.2.0
fdf1556

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

Choose a tag to compare

@rennf93 rennf93 released this 23 Sep 23:20
v4.0.4
375d0b9

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 is github.com/rennf93/guard-core-go/v4 and the release tag is v4.0.4; Go modules reject a v4+ tag unless the module path carries the /v4 suffix, so the migration is mandatory for this release to be fetchable. Update every import from github.com/rennf93/guard-core-go/guardcore to github.com/rennf93/guard-core-go/v4/guardcore (and the same for the examples/... internal packages). Installation is now go get github.com/rennf93/guard-core-go/v4@v4.0.4. The earlier v0.1.0 tag 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 matched 0x27 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 integration in docker), lint (gofmt check plus go vet), bump-version (via .github/scripts/bump_version.py, which scaffolds this changelog) and clean match the conventions used across the Python guard repos.