Repository navigation
fix(ssh): validate hashed known_hosts fields through one strict base64 decoder (STA-4717) - #15345
Conversation
…4 decoder (STA-4717)
📝 WalkthroughWalkthroughKnown-hosts parsing now uses a shared canonical Base64 decoder for keys, hashed salts, and hashes. The decoder rejects empty, malformed, non-canonical, URL-safe, unpadded, and over-padded values. Hashed salts and hashes must decode to 20 bytes. Tests cover malformed fields and confirm that malformed entries return 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/main/ssh/ssh-known-hosts.ts (1)
89-104: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReduce the Base64 rationale comments.
Keep only the non-obvious OpenSSH compatibility rule. Remove detailed decoder behavior and manual verification narratives.
src/main/ssh/ssh-known-hosts.ts#L89-L104: reduce the decoder documentation to a brief canonical-Base64 requirement.src/main/ssh/ssh-known-hosts.ts#L122-L125: reduce the length-check rationale to one short requirement statement.src/main/ssh/ssh-known-hosts.test.ts#L356-L360: rely on the parameterized test names instead of documenting the full reproduction details.src/main/ssh/ssh-known-hosts.test.ts#L364-L367: reduce the padding-bit explanation to a brief reason for the fixture.As per coding guidelines, comments must be concise, non-obvious, and brief.
Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: ce256719-84d0-4864-8410-3c673014a803
📒 Files selected for processing (2)
src/main/ssh/ssh-known-hosts.test.tssrc/main/ssh/ssh-known-hosts.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
Cross-platform verificationRun on real hosts via Linux — Ubuntu 24.04 (kernel 7.0.0), node v26.1.0, pnpm 10.24.0, over SSH.
Clean on both. |
…4 decoder (STA-4717) (stablyai#15345)
…4 decoder (STA-4717) (stablyai#15345)
…4 decoder (STA-4717) (stablyai#15345)
ELI5
Your computer keeps an address book of servers it trusts, called
known_hosts. Each line has a scrambled server name and a fingerprint, both written in a code called base64.We were reading that code too forgivingly. If a line had junk characters smudged into it, the tool we used to decode it would quietly skip the junk and hand back a perfectly good-looking answer — so we'd say "yes, I recognise this server." But real
sshthrows that whole line in the bin as unreadable. So we could end up trusting a line your ownsshrefuses to even look at.This makes us check that the code is written exactly right, by decoding it and then re-encoding it to see if we get back what we started with. There was already a check like that, but only on one of the fields — the other two didn't have it. Now all three go through the same one check, so the next person to add a field can't forget it.
What you might notice: nothing, unless your
known_hostshas a hand-edited or corrupted line. If it does, that line now gets ignored — the same thingsshalready does with it.Resolves STA-4717. Follow-up from #14844.
Problem
parseHashedPatternsdecoded the salt and hash fields with plainBuffer.from(x, 'base64')plus a 20-byte length check, whiledecodeKey— a few lines above, in the same file — additionally re-encoded and compared to reject non-canonical input.That gap matters because
Buffer.from(x, 'base64')never throws: it silently skips invalid characters. A line realsshrejects outright (parse error in hostkeys file) could therefore parse here and be trusted by us. The length check isn't sufficient on its own — garbage characters get skipped and the result can still be exactly 20 bytes.Root cause
The strictness rule was implemented ad hoc at one call site rather than being the decode primitive every base64 field in the parser must go through. Copying the re-encode check into
parseHashedPatternswould have fixed this instance and left the next field free to forget it again.Fix
One strict decoder, used by both the key field and the hashed salt/hash fields, so a future field cannot bypass it.
Tests
Added cases to
ssh-known-hosts.test.tscovering non-canonical salt and hash fields that decode to the correct length but are not whatsshaccepts. 78 tests pass.