v1.1.7: deep security & reliability audit — 33 bugs fixed
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled

Critical (5):
- Reject empty JWT secret when authEnabled (server.nim)
- Fix 2PC marking uncontacted participants as prepared/committed (disttxn.nim)
- Fix Raft commit index calculation for even-sized clusters (raft.nim)
- Fix REP/DISTTXN protocol auth bypass (server.nim)
- Fix HTTP backup/restore path traversal (httpserver.nim)

High (11):
- Fix WAL write race with flush (lsm.nim)
- Fix MVCC savepoint/rollback deep-copy writeSet (mvcc.nim)
- Fix table mutation during deadlock iteration (mvcc.nim)
- Fix LIMIT 0 returning all rows (executor.nim)
- Fix COUNT(col) counting NULL values — 3 locations (executor.nim)
- Fix EXISTS subquery lowering missing subqueryPlan (executor.nim)
- Fix Raft appendEntries/applyCommitted array vs logical index (raft.nim)
- Fix timing attacks on constantTimeCompare and SCRAM (auth.nim, scram.nim)
- Fix B-tree leaf merge phantom separator key (btree.nim)
- Fix SSL verifyPeer not applied to newContext (ssl.nim)
- Fix sharding connectWithTimeout missing SO_ERROR check (sharding.nim)
- Fix sync replication returning success on partial ack (replication.nim)
- Fix WebSocket JWT expiration not validated (websocket.nim)

Medium (13):
- Fix writeSSTable partial file → tmp + atomic rename (lsm.nim)
- Fix multi-CTE table loss (executor.nim)
- Fix nl_to_sql DML restricted to superuser (executor.nim)
- Fix unbounded plan cache — max 10000 (adaptive.nim)
- Fix migration lock crash persistence — timestamp + stale detection (executor.nim)
- Fix admin panel auth (httpserver.nim)
- Fix MVCC unbounded txn tracking — prune in compactVersions (mvcc.nim)
- Fix connection pool maxLifetime check (pool.nim)
- Fix JWT JSON parser backslash escapes (auth.nim)
- Fix substr(s, start) returning single char (udf.nim)
- Fix loadSSTable minimum file-size check (lsm.nim)
- Fix compaction mmap leak (compaction.nim)
- Fix JSON injection in hybrid_search_filtered (executor.nim)

Low (4):
- Raft loadState logs error instead of silent discard
- Replication healthCheck double-close fixed
- Lexer readIdent double column counting fixed
- WebSocket frame 32-bit overflow guard

All 448 tests passing, 0 failures. Bump version to 1.1.7.
This commit is contained in:
2026-05-29 14:17:41 +03:00
parent 37a8ed52ba
commit 42043f3946
27 changed files with 408 additions and 86 deletions
+12
View File
@@ -463,6 +463,10 @@ proc backupHandler(server: HttpServer): RequestHandler =
let allDatabases = if body != nil and "all" in body: body["all"].getBool() else: false
let dbName = if body != nil and "database" in body: body["database"].getStr() else: ""
let outputFile = if body != nil and "output" in body: body["output"].getStr() else: "backup_" & $getTime().toUnix() & ".tar.gz"
# Path traversal protection: reject paths with .. or absolute paths outside dataRoot
if ".." in outputFile or outputFile.startsWith("/"):
ctx.json(%*{"error": "Invalid output path: must be relative and not contain '..'"}, 400)
return
let compression = if body != nil and "level" in body: body["level"].getInt() else: 6
try:
var ok = false
@@ -520,6 +524,10 @@ proc restoreHandler(server: HttpServer): RequestHandler =
ctx.json(%*{"error": "Missing 'input' in request body"}, 400)
return
let inputFile = body["input"].getStr()
# Path traversal protection: reject paths with .. or absolute paths
if ".." in inputFile or inputFile.startsWith("/"):
ctx.json(%*{"error": "Invalid input path: must be relative and not contain '..'"}, 400)
return
let allDatabases = if body != nil and "all" in body: body["all"].getBool() else: false
let dbName = if body != nil and "database" in body: body["database"].getStr() else: ""
let dataRoot = server.registry.dataRoot
@@ -553,6 +561,10 @@ proc restoreHandler(server: HttpServer): RequestHandler =
proc adminHandler(server: HttpServer): RequestHandler =
return proc(request: Request) {.gcsafe.} =
{.cast(gcsafe).}:
let ctx = newContext(request)
if server.config.authEnabled and not server.checkAuth(request, ctx):
return
let html = """
<!DOCTYPE html><html><head>
<meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'>