Skip to content

registry/hive: reject malformed cell sizes instead of panicking#17

Merged
psycep merged 1 commit intomainfrom
fix-hive-readcell-panic
Apr 23, 2026
Merged

registry/hive: reject malformed cell sizes instead of panicking#17
psycep merged 1 commit intomainfrom
fix-hive-readcell-panic

Conversation

@psycep
Copy link
Copy Markdown
Collaborator

@psycep psycep commented Apr 23, 2026

Summary

Fixes the panic: runtime error: slice bounds out of range [5052:5048] crash documented in KNOWN_ISSUES.md #2 under secretsdump's cached-domain-logon parse path.

readCell() in pkg/registry/hive.go trusted the 4-byte cell-size header on the wire without validating the positive side of it:

  • Negative raw size = allocated cell (|size| total bytes including the 4-byte header)
  • Positive raw size = free cell
  • Zero = malformed, but occurs in real hives

The old code checked if size > 0 (free) but let zero fall through. It then did size = -size (still 0) and computed the final slice as h.data[pos+4 : pos+0], which panics. Same for raw values -1, -2, -3 (negation gives 1, 2, 3 respectively, still less than the 4-byte header).

The fix

Treat rawSize >= 0 as "free or malformed, return error", and after negation require size >= 4 so the slice can never be inverted. Both paths return a descriptive error instead of crashing.

Test plan

  • New regression test pkg/registry/hive_test.go synthesizes a minimal hive with each previously-panicking input (raw size 0, positive, -1, -3) and asserts readCell returns an error rather than panicking
  • Happy-path test that a raw size of -16 still reads 12 bytes correctly
  • Verified the old code really did panic on the synthetic input by git stash-ing the fix, running the test, and watching it fail with the exact [x+4 : x] slice-bounds shape before restoring
  • go build ./... clean
  • go vet ./... clean
  • Full go test ./... passes

Impact for secretsdump

The cached-domain-logon parse path walks SECURITY hive NL$N values, which occasionally encounter a bogus cell header. Previously this crashed the whole tool after SAM and LSA secrets had already been dumped (so you'd lose the cached creds and the process would exit non-zero). The tool now skips the bad entry with an error and continues to the next.

Also removes the now-resolved entry from KNOWN_ISSUES.md and renumbers the remaining sections.

readCell trusted the cell's size header without bounds-checking the
positive side, so any cell whose raw size field was 0 or a negative
value with absolute magnitude smaller than the 4-byte cell header
produced an inverted slice expression (h.data[pos+4 : pos+size] with
size < 4) and crashed the process. Reported as a runtime panic
`slice bounds out of range [5052:5048]` in secretsdump's cached
domain logon parse path.

Treat raw size >= 0 as free/invalid (return error) and require the
allocated size to be at least 4 bytes so the data slice is never
inverted. Regression test synthesizes a minimal hive with each of
the previously-panicking inputs.

Removes the now-resolved entry from KNOWN_ISSUES.md and renumbers
the remaining sections.
@psycep psycep merged commit af32683 into main Apr 23, 2026
2 checks passed
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