- cache: fix LRU race — check expiry before MoveToFront within same lock
critical section; previously a stale entry could be promoted before
expiry was verified
- cache: drop stale ETag/Content-Md5/Digest headers when body is
rewritten by refreshCachedResponseMeta to avoid misrepresenting the
new body to clients
- ratelimit: cap buckets map at 100k entries with stale-eviction fallback
and shared overflow bucket to prevent unbounded memory growth under
high-cardinality traffic
- ratelimit: fix clientRateLimitKey comment — credentials are tried
second (before IP), not as a "last resort"
Co-Authored-By: Virgil <virgil@lethean.io>
Go:
- cache: fix TOCTOU race in get() — re-verify entry pointer under lock before
evicting to prevent corrupting s.currentBytes and removing a newly-set entry
- bridge: fix writeErrorResponse recorder out of sync — buffer into w.body/
w.headers and call commit() so Status(), Header(), Size() reflect error response
- bridge: fix ValidateResponse number precision — use json.Decoder+UseNumber for
initial envelope decode to preserve large integers (matches Validate path)
- ratelimit: fix unreachable credential branches — move X-API-Key and
Authorization hashing before IP fallback so NAT'd clients are bucketed by key
- openapi: gate cacheSuccessHeaders on sb.CacheEnabled flag, not just method==get
- openapi: use isNilRouteGroup in prepareRouteGroups to catch typed-nil RouteGroup
PHP:
- RateLimitExceededException: remove ad-hoc CORS handling — let framework CORS
middleware apply correct headers for all responses including errors
- SeoReportService.extractCharset: parse charset token from Content-Type value
instead of returning the full "text/html; charset=utf-8" string
- SeoReportService: validate IP literals directly with filter_var before DNS
lookup so ::ffff:127.0.0.1-style hosts don't bypass private-IP checks
- SeoReportService.isPrivateIp: extract isPrivateIpv4 helper; handle
IPv4-mapped IPv6 (::ffff::/96) by checking embedded IPv4 against private
ranges; add 0.0.0.0/8 to private range list
Co-Authored-By: Virgil <virgil@lethean.io>
Go:
- codegen: pass trimmed specPath to buildArgs instead of raw g.SpecPath
- cmd/sdk: use local resolvedSpecFile to avoid mutating flag variable per-invocation
- export: write to temp file + atomic rename to prevent destination truncation on failure
- openapi: gate effectiveGraphQLPath/SwaggerPath/WSPath/SSEPath on enable flags; use effectiveSwaggerPath in effectiveAuthentikPublicPaths
- cache: reject oversized replacement before mutating LRU state for existing keys
- ratelimit: move setRateLimitHeaders before c.Next() so headers are sent; hash credential headers with SHA-256 to avoid storing raw secrets; prefer validated principal from context
- response_meta: track size separately from body buffer so Size() is accurate after body rewrites and in passthrough mode
- bridge: limit request body reads with http.MaxBytesReader (10 MiB); allow missing data key in ValidateResponse for nil/zero success responses; update recorder status in writeErrorResponse
- pkg/provider/proxy: validate target scheme and host after url.Parse to catch hostless inputs
- cmd_test: snapshot/restore global spec registry in TestAPISpecCmd_Good_RegisteredSpecGroups
PHP:
- HasApiResponses.php, config.php: add declare(strict_types=1)
- RateLimitExceededException: validate Origin against cors.allowed_origins before reflecting in CORS header
- ApiUsageService: import and use Core\Api\Models\ApiKey instead of fully-qualified Mod\ path
- SeoReportService: add SSRF protection (scheme check, private-IP rejection); add .throw() for HTTP error handling; disable automatic redirects
Co-Authored-By: Virgil <virgil@lethean.io>
Add an optional maxEntries cap to WithCache so the in-memory cache can evict old entries instead of growing without bound.\n\nCo-Authored-By: Virgil <virgil@lethean.io>