Audit Findings Tracker
Live-status table of named findings from the 2026-05-11 comprehensive audit and 2026-05-08 adversarial audit.
Each finding's status updates with the commit that closes it. No finding is hidden from this page; when a remediation lands, the row flips and cites the SHA. The operating commitment is to drive the open-and-partial count to zero before TVL scales past Genesis.
Closed
9
Partial
2
Open
9
Mitigated
2
| ID | Severity | Surface | Finding | Status | Closing commit |
|---|---|---|---|---|---|
| 1.3a | CRIT | contracts | KerneVault rate-limit bypass on updateHedgingReserve and updateL1Assets when prior value was 0 Rate-limit now enforced on first writes. Paired with KernePrime free-collateral faucet closure in the same commit. | closed | 089d75292026-05-09 |
| 1.8 | CRIT | contracts | KernePrime accounting-only ledger could be wired to mint/burn kUSD without a backing check KernePrime free-collateral faucet patched alongside the rate-limit bypass. | closed | 089d75292026-05-09 |
| 1.18 | CRIT | contracts | KerneStaking lock-bypass via partial-unstake-then-restake path Source patched same-day with 7 regression tests. Deployed bytecode at 0x032A...D582 has not been re-verified to confirm the fix is on-chain; treat as partial until verified. | partial | on-box2026-05-08 |
| B4 | CRIT | contracts | InsuranceFund.checkAndInject targets degraded vault totalSupply Duplicate of TOP-3 in the audit's framing; tracked as a separate item because the source-level fix and the operational mitigation differ. | open | not yet |
| B7 | CRIT | contracts | KerneVault.setFactory race window enables clone hijack Factory not currently used for deploys; closing the race before any factory-driven vault is deployed. | open | not yet |
| B8 | CRIT | contracts | KerneZINRouter.onFlashLoan accepts any lender with attacker-chosen calldata ZIN router not currently in deploy path. Patch before re-enabling. | open | not yet |
| B9 | CRIT | contracts | KerneIntentExecutor V1 lacks the V2 hardening and remains callable V2 closed the equivalent class of bugs. V1 SOLVER_ROLE still ungated; pause + revoke needed before V1 sees production use. | open | not yet |
| B10 | CRIT | contracts | KerneVault.emergencyExit drains entire balance to arbitrary recipient Requires DEFAULT_ADMIN_ROLE + paused state, so blast radius is Safe-bound; still worth pinning recipient to treasury + adding a 24h delay. | open | not yet |
| B11 | CRIT | bot | RFQ /quote endpoint signs arbitrary EIP-712 orders with strategist key, no auth Bot is offline as of 2026-05-12 (HL-only restart 2026-05-13 with the RFQ surface still disabled). Attack surface inert; patch is still required before the RFQ endpoint is re-enabled. | mitigated | not yet |
| B12 | CRIT | bot | BotOrchestrator.deploy_instance writes raw private keys to /tmp env files Bot is single-instance HL-only; the orchestrator multi-container path is inactive. Patch required before orchestrator-style deploys are re-enabled. | mitigated | not yet |
| TOP-1 | CRIT | frontend (terminal) | Opal cron /api/opal/cron/accrue accepted spoofable x-vercel-cron header as auth Constant-time Bearer comparison against CRON_SECRET shipped 2026-05-11 (commit 35c05ec1). ACCRUE_SECRET legacy fallback dropped from source and removed from Vercel env 2026-05-21, closing the audit's rotation sub-task. CRON_SECRET is now the sole credential. Production probe with no Bearer returns 401; cron fires hourly on schedule. | closed | 35c05ec12026-05-21 |
| TOP-2 | CRIT | contracts | KerneVault pause path requires Safe co-sign; no on-chain pauser holds PAUSER_ROLE Bot's pre-flight pause simulation (commit 80c676aa) prevents the loop-spam failure mode, but a live solvency event still requires manual Safe co-sign to pause. Safe co-sign is out of scope for current ranked action plan. | open | not yet |
| TOP-3 | CRIT | contracts | KerneInsuranceFund.checkAndInject is permissionless and computes target against degraded vault totalSupply Mitigated today by the vault's degraded-state UI guard (deposits gated); the on-chain primitive remains callable by anyone. Requires source patch + Safe AUTHORIZED_ROLE strip. | open | not yet |
| TOP-4 | CRIT | infra | Database port on the ops host is reachable from the public internet Open, and named here rather than papered over. The public reachability is deliberate: it serves a live product surface. Closing it means removing that reachability entirely, which is a scoped project and not a configuration toggle, because an hourly job and several read paths depend on the current transport. Compensating controls, verified on-box 2026-07-29: the firewall rate-limits new connections per source; the database refuses unencrypted connections at the host-based access layer, so TLS 1.3 is mandatory; and authentication is scram-sha-256. Sustained automated probing from distributed sources is visible across the current log retention window, and every attempt terminated at the TLS requirement or failed authentication, with none establishing an authorized session. The exact port and firewall-rule syntax are withheld from this page on purpose; the severity is not. | open | not yet |
| TOP-5 | CRIT | secrets | Leaked OpenRouter API key committed in bot/solver Source was patched in the 2026-05-11 audit pass (commit 35c05ec1). This row is closed on 2026-07-30, but the closure corrects a bookkeeping drift rather than reporting new remediation, and the distinction is worth stating plainly: the key was already established as dead on 2026-05-17, recorded in the internal tracker at docs/security/COMPREHENSIVE_AUDIT_2026-05-11.md (row 5 and B5) as 'NEUTRALIZED, owning OpenRouter account no longer exists'. That conclusion was never propagated here, so this public row went on asserting for ten weeks that an operator rotation was still outstanding when the internal record already said it was not required. Re-verified from scratch on 2026-07-30 rather than taken on trust: the key was recovered from git history, presented to OpenRouter's key endpoint, and rejected with HTTP 401 'User not found', byte-identical to the response for a deliberately invalid control key issued in the same pass. A key that cannot authenticate cannot be billed against. Two related credentials from the same committed file were checked in the same pass and are recorded here because the original finding named only one: the Basescan key is likewise dead (Etherscan v2 returns 'Invalid API Key', identical to the control), and the committed CEX and Discord values were never live at all, being the literal placeholders 'your_api_key', 'your_secret' and 'your_discord_webhook_url'. One credential from that file remains outstanding and is deliberately named rather than folded into this row's closure: a Resend mail key, whose provider-side state could not be determined without an operator login. It is not this finding's subject, it is confirmed NOT to be the key production sends mail with, and its revocation is the one open item in docs/security/CREDENTIAL_ROTATION_2026-07-30.md. | closed | 35c05ec12026-07-30 |
| TOP-6 | CRIT | infra | VPS SSH posture: remote root login accepted password authentication Closed on-box 2026-07-29. Remote root access is now key-only: password and keyboard-interactive authentication are both refused by the daemon, and root login is restricted to public key. Verified against the running daemon from a separate connection rather than by reading the config file, because a distribution drop-in was silently overriding the main file and the file on its own would have misreported the state. One correction to the original finding text, which was wrong on a point of fact: fail2ban was already active on this host and had been banning brute-force sources throughout. Operator console recovery is deliberately retained so the host cannot be locked out of. No closing commit is cited because this is a host configuration change and has no corresponding source commit. | closed | on-box2026-07-29 |
| TOP-7 | CRIT | frontend (terminal) | Opal /api/opal/balance/[address] IDOR with write-on-read Removed the INSERT-on-GET path; balance reads are now read-only. | closed | 35c05ec12026-05-11 |
| TOP-8 | CRIT | contracts | kUSD.burnFrom callable via permit2 chain by any contract with allowance burnFrom is now gated behind BURNER_ROLE. The permit2-then-burnFrom primitive is closed. | closed | 4cd208262026-05-12 |
| TOP-10 | CRIT | infra | Postgres opal-pg TLS connection used rejectUnauthorized: false 35c05ec1 flipped to rejectUnauthorized: true with pinned CA cert. 982996d9 (2026-05-14) added explicit CN verification when the connection hostname (localhost.) does not match the cert's CN (134.209.46.179), which had been silently failing every Vercel cron invocation since 2026-05-11 23:00:50 UTC and froze the fragment ledger for 66 hours. | closed | 35c05ec1982996d92026-05-14 |
| B13 | HIGH | bot | Bot used 5% slippage on every Hyperliquid order Tightened to 0.3% with TWAP fallback for sizes over 5 ETH. | closed | 35c05ec12026-05-11 |
| B14 | HIGH | bot | All bot on-chain txs used legacy gasPrice instead of EIP-1559 panic.py + oracle_updater are on EIP-1559. ~12 other call sites (chain_manager, risk_engine, por_attestation, etc.) still use legacy gasPrice; pending a canonical helper rollout. | partial | cb8fc23ebebb30942026-05-12 |
| TOP-9 | HIGH | contracts | KerneYieldDistributor merkle root is updated without a 24h timelock window Distributor is currently inactive (0 KERNE in flight). Add timelock before any first distribution. | open | not yet |
How this page works
Every named finding from the 2026-05-11 comprehensive audit's Top-10 emergency fix list and B-series new criticals is enumerated here, plus the 2026-05-08 adversarial audit's §1 criticals that have seen a remediation commit since.
A status of closed means the finding is resolved. For a source-level finding that means a commit has shipped and the SHA is listed. For an infrastructure finding there is no source commit to cite, so the row is marked on-box with the date the change was made and verified on the machine itself. Partial means a remediation has shipped but not the whole class; the note explains what is still open. Open means the finding remains live in source today. Mitigated means the surface is not currently exposed (the affected service is offline, the contract is not deployed) but a future re-enable would require the patch first.
The full audit reports are linked from the Audit and Security Posture page. The live risk surface (wired thresholds vs. on-chain values) is at /risk.
How findings from the in-progress external Hexens audit will be triaged, remediated, and disclosed is pre-committed on the findings-response protocol page. The independent researchers who have responsibly disclosed to Kerne are credited on the researcher acknowledgments page.