Skip to content

Kimi-K3 audit fixes - #4

Open
jamesob wants to merge 2 commits into
masterfrom
jamesob/ai-fixes
Open

Kimi-K3 audit fixes#4
jamesob wants to merge 2 commits into
masterfrom
jamesob/ai-fixes

Conversation

@jamesob

@jamesob jamesob commented Aug 13, 2026

Copy link
Copy Markdown
Owner

2026-08 security audit fixes

Addresses all 12 findings from the security audit (2 medium, 8 low, 2 info).
BIP32 test vectors are unchanged.

Vulnerabilities addressed

ID Sev Defect Fix
FND-001 medium Path components ≥ 2³² silently truncated mod 2³²; stale errno spuriously rejects Reset errno; range-check wide strtoul value before narrowing; reject components > 2³¹−1
FND-002 medium Trailing garbage in paths silently ignored (m/1h2m/1h) Strict per-segment grammar: reject anything but /⟨digits⟩[marker]
ENT-001 low Sub-128-bit (incl. 0-byte) seeds accepted — publicly computable master keys bip32_from_seed rejects seeds outside 16–64 bytes per BIP32
KEY-001 low Secret stack temporaries (seed, decoded xprv, IL‖‖IR, key copies) unwiped on some paths Single-exit wipe discipline; every secret temporary sodium_memzero'd on every exit
KEY-002 low bip32_get_public masks pubkey failure: success + all-zero pubkey Check return; zero buffer and fail
KEY-003 low ctypes BIP32Key has phantom ctx field — field reads return shifted bytes incl. wrong private key Drop field; import-time asserts pin sizeof=80 and offsets
KEY-004 low Missing bip32_from_seed ctypes prototype → deterministic SIGSEGV in BIP32.from_seed() Add prototype and pass arguments explicitly
FND-003 low In-place bip32_index_derive stamps child's fingerprint as parent's Snapshot parent key material + fingerprint before mutation
FND-004 low CLI passes uninitialized out_size — stock binary always fails Initialize to sizeof(serialized); make test CLI smoke test
SIG-001 low Python b58_encode buffer len*2 too small for 1-byte inputs ≥ 0x3a Two-call sizing via C-reported required length
SIG-003 info CKD fails instead of retrying with next index on invalid tweak (BIP32 deviation) Retry loop per BIP32; child_number reflects actual index
ENT-002 info Side-effecting calls inside assert() compiled out under NDEBUG Replace with explicit checks (libsodium init, context randomize)

Changes

  • bip32.c — seed-length enforcement; strict path parser; CKD retry loop; snapshot-before-mutation in bip32_index_derive; checked bip32_fingerprint/bip32_pubkey_from_privkey returns; complete stack zeroization; NDEBUG-safe init checks.
  • bip32.hBIP32_{MIN,MAX}_SEED_BYTES; docs for seed requirements, strict paths, in-place derivation, wipe-on-failure.
  • examples/py/bindings.pybip32_from_seed prototype; FFI layout fixed + pinned by asserts; exact-size b58 buffers.
  • examples/py/test_fuzz_cross_impl.py — base58 TODO workaround removed; oracle seed constructors wrapped so failure comparison is robust.
  • examples/cli.c — initialize out_size.
  • Tests — C regression suite (weak seeds, ≥2³² components, stale errno, 13 malformed paths, invalid-key neutering, in-place fingerprint equivalence); Python tests (from_seed vector, field access, weak seeds, 1-byte b58); CLI smoke test in make test.
  • CHANGELOG.md — 0.0.3 entry.

Verification

  • BIP32 vectors 1–3: exact match; ASan/UBSan clean.
  • Full hypothesis cross-impl fuzz vs python-bip32 and verystable: pass.
  • Go binding tests: pass.
  • NDEBUG build keeps sodium_init + secp256k1_context_randomize (object-level check).
  • All 12 audit repro kits re-run against this tree: NOT REPRODUCED, control assertions still passing.

Note: oracles (python-bip32, verystable) do not reject out-of-range seed lengths; fuzz seeds stay clamped to 16–64 bytes since rejection behavior cannot be cross-compared. Our rejection is pinned by unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant