Skip to main content
Version: Next

Security Disclosure

This page tracks the security hardening work delivered across Sharkable core, Sharkable.Cache.Redis, and Sharkable.AutoCrud.SqlSugar. Each entry summarizes the fix; for the full audit context, see local/security-audit.md in each repository.

Core library (Sharkable)

IDSummary
SHARK-SEC-003Replace Thread.Sleep with await Task.Delay in graceful shutdown drain — prevent ApplicationStopping thread block
SHARK-SEC-004Make SagaExecutor.LockTtl configurable + add LockRenewalInterval with periodic lock extension — prevent split-brain sagas when step duration exceeds lock TTL
SHARK-SEC-005Replace unconditional KeyDelete with check-and-delete Lua in RedisSagaStore.ReleaseLockAsync / RedisCronJobStore.ReleaseJobLockAsync; add CronScheduler.CronLockTtl + ICronJobStore.RenewJobLockAsync — prevent split-brain when LockTtl expires mid-work (cross-repo with Sharkable.Cache.Redis)
SHARK-SEC-006BREAKING — Add [CrudAllow] attribute for explicit field allowlist on AutoCrud insert/update; endpoints with Create | Update and zero [CrudAllow] properties now throw InvalidOperationException at startup. Prevents mass-assignment privilege escalation via JSON body (cross-repo with Sharkable.AutoCrud.SqlSugar)
SHARK-SEC-007Add JWT algorithm allowlist + RequireSignedTokens + RequireExpirationTime + reduce ClockSkew to 30s — prevent algorithm confusion attacks
SHARK-SEC-008Use CryptographicOperations.FixedTimeEquals for API key comparison — prevent timing oracle
SHARK-SEC-009Gate ScalarJwtToken / ScalarApiKeyValue to IHostEnvironment.IsDevelopment() — prevent token leakage to public /scalar/v1 UI
SHARK-SEC-010Implement AuditTrailMiddleware header redaction per RedactHeaders list — credential-bearing headers (Authorization, X-Api-Key, Cookie by default) have their values replaced with *** in audit log output
SHARK-SEC-011Add SharkOption.RequireAuthenticatedByDefault opt-in flag — enforce auth on all endpoints via per-endpoint [Authorize] metadata injection
SHARK-SEC-012Add ETagOptions.MaxResponseSize (default 10 MiB) + counting stream + incremental hashing — prevent OOM via huge response bodies
SHARK-SEC-013Add IMemoryCache SizeLimit (100k) + periodic eviction sweep to MemoryRateLimitStore — prevent slow-loris DoS via unique path explosion
SHARK-SEC-014Add IMemoryCache SizeLimit (10k) + entry.Size tracking to MemoryIdempotencyStore — prevent TB-DoS via unique idempotency keys
SHARK-SEC-015Require API key on profiler endpoint /_sharkable/profiler by default; return 404 if no API keys configured; cap top slow-requests surface at 50
SHARK-SEC-016Require API key on cron admin endpoint /_sharkable/jobs; redact LastError field to its first 100 characters + ... to prevent business-logic leakage
SHARK-SEC-017BREAKING — Make CronScheduler.Register async; ICronScheduler.Register replaced by RegisterAsync returning Task — eliminate sync-over-async deadlock risk with distributed stores
SHARK-SEC-028Pin Microsoft.OpenApi to 2.7.5 — suppress NU1903 (CVE-2026-49451, circular schema stack overflow)

Plugin: Sharkable.Cache.Redis

IDSummary
SHARK-SEC-018Redact RedisHealthCheck description — never expose endpoint topology or ex.Message on public /healthz; full diagnostic detail logged at LogWarning for operators only
SHARK-SEC-019Validate connection string at AddSharkableRedis — null-check + default abortConnect=false + optional TLS enforcement via RedisStoreOptions.RequireTls
SHARK-SEC-020Replace empty catch in RedisIdempotencyStore.GetAsync with typed exception filter + structured LogWarning + re-throw wrapped in InvalidOperationException — prevent silent double-execution when a corrupted record is encountered
SHARK-SEC-021Add UseSharkableRedisHealthCheck() extension — explicit opt-in to wire RedisHealthCheck into HealthCheckService under name "redis" and tag "ready". The check is no longer auto-surfaced on /healthz by default
SHARK-SEC-022Set TTL on RedisSagaStore.SaveProgressAsync via RedisStoreOptions.SagaProgressTtl (default 7d) — prevent unbounded Redis key growth from orphaned saga progress records after host crashes

Plugin: Sharkable.AutoCrud.SqlSugar

IDSummary
SHARK-SEC-023Add AutoCrudSqlSugar.AutoCrudRequireAuthorization opt-in flag — auto-attach .RequireAuthorization() to every generated CRUD endpoint when true. Default false preserves backward compat, but production deployments MUST enable. AddSqlSugar() logs a LogWarning at startup when the flag is false in non-AOT mode
SHARK-SEC-024Defense-in-depth: also exclude SafeSoftDeleteField from the [CrudAllow] allow-list by case-insensitive name match — protects entities whose C# property name matches the configured soft-delete column but lacks a [SugarColumn] rename
SHARK-SEC-025Add AutoCrudSqlSugar.MaxPageNumber (default 1M) + overflow check on (page - 1) * pageSize — prevent pagination DoS via page=int.MaxValue producing a negative OFFSET
SHARK-SEC-026Redact SqlSugarHealthCheck description — never expose dbType or ex.Message on public /healthz; full diagnostic detail (DB type, exception) logged at LogWarning for operators only
SHARK-SEC-027Escape SQL LIKE wildcards (%, _, \) with ESCAPE '\' clause + cap filter value length via AutoCrudSqlSugar.MaxFilterValueLength (default 200) + cap IN / NOT IN array size via AutoCrudSqlSugar.MaxInArraySize (default 100) in AutoCrud search — prevent LIKE wildcard DoS and large-IN clause DoS

Reporting vulnerabilities

Please report security issues privately via GitHub Security Advisories on the affected repository (Sharkable, Sharkable.Cache.Redis, or Sharkable.AutoCrud.SqlSugar). Do not open public issues for suspected vulnerabilities.