Skip to content

security: Testing harness, TOFU fix, and transport hardening#19

Merged
CraZySacX merged 9 commits intomasterfrom
18-security-analysis
May 1, 2026
Merged

security: Testing harness, TOFU fix, and transport hardening#19
CraZySacX merged 9 commits intomasterfrom
18-security-analysis

Conversation

@CraZySacX
Copy link
Copy Markdown
Member

@CraZySacX CraZySacX commented Apr 29, 2026

Fixes #18

This pull request introduces several improvements to the moshpit-keygen tool and its supporting libraries, focusing on enhanced test coverage, improved key generation UX, and expanded CI/CD and fuzz testing infrastructure. The most significant changes include a major refactor and test addition for the key generation logic, the introduction of a fuzzing suite for libmoshpit, and updates to CI workflows for more robust automation and artifact handling.

Key changes:

Key Generation Refactor and Testing

  • Refactored the key generation logic in keygen/src/runtime.rs to modularize user prompts, file path handling, and key writing, improving maintainability and testability. Added comprehensive unit tests for these components. [1] [2]
  • Added CLI parsing and flag tests in keygen/src/cli.rs to ensure correct argument handling and improve reliability.
  • Applied #[cfg_attr(coverage_nightly, coverage(off))] to main entry points to improve code coverage reporting accuracy. [1] [2]

Fuzzing Infrastructure

  • Added a new libmoshpit-fuzz crate with fuzz targets and regression tests for core library components, along with initial corpus and artifact placeholder files. This enables automated fuzz testing for robustness. [1] [2] [3] [4] [5]
  • Integrated proptest as a dev-dependency in libmoshpit for property-based testing.

CI/CD and Workflow Enhancements

  • Added a "Fuzz Smoke Test" job to .github/workflows/audit.yml to run short fuzzing sessions and upload crash artifacts on failure, helping catch regressions early.
  • Updated permissions and structure in .github/workflows/release.yml for better security and to comply with GitHub Actions best practices. [1] [2] [3] [4] [5]

Dependency and Version Updates

  • Bumped libmoshpit and moshpit-keygen versions to 0.3.0 and updated internal dependencies accordingly. [1] [2] [3]
  • Added zeroize as a dependency to both the workspace and libmoshpit for secure memory handling. [1] [2]

These changes collectively improve the reliability, security, and maintainability of the codebase, while laying the groundwork for more robust automated testing and release processes.

Add the security testing and verification harness called for in Phase 5
of the hardening plan, fix the TOFU handshake regression, and correct an
overly-aggressive UDP frame size limit that caused client hangs.

TOFU handshake fix (moshpit/src/runtime.rs):
- Replace dialoguer::Confirm (which dropped the y/n keypress in raw mode)
  with dialoguer::Input requiring the user to type "yes" explicitly, matching
  OpenSSH UX.  Wrap in tokio::task::block_in_place so the async runtime
  continues processing while waiting for terminal input.

Auth/KEX negative unit tests (libmoshpit/src/kex/reader.rs):
- Add 8 hermetic unit tests for check_known_hosts and check_authorized_keys:
  host-key match and MITM-mismatch detection, TOFU accept/reject/no-callback
  paths, authorized_keys key match/mismatch, and bad file permissions
  (0o644 → rejected).  Tests use TempDir for filesystem isolation and a
  shared Mutex to serialize HOME mutations across parallel test threads.

Frame parser fuzz targets (libmoshpit/fuzz/):
- Add cargo-fuzz harness crate with two libFuzzer targets: fuzz_frame for
  Frame::parse and fuzz_encframe for EncryptedFrame::parse.  Both assert
  no panics on arbitrary byte input; FrameTooLarge and Ok(None) are the
  expected outcomes for random data.  Corpus directories committed.

CI fuzz smoke-test (.github/workflows/audit.yml):
- Add fuzz-smoke job that runs both fuzz targets for 30 seconds on every
  PR and scheduled run using nightly Rust + cargo-fuzz.  Crash artifacts
  are uploaded on failure.

UDP sequence property tests (libmoshpit/src/udp/reader.rs):
- Add proptest dev-dependency and 5 property tests sweeping arbitrary
  sequence numbers: in-order delivery, single-gap reordering, MAX_SEQ_JUMP
  DoS rejection, replay rejection, and recv_buffer size bounds.

Fix MAX_ENCFRAME_LENGTH regression (libmoshpit/src/frames/encframe.rs):
- Raise MAX_ENCFRAME_LENGTH from 2 KB to 64 KB.  The 2 KB limit silently
  dropped ScreenState frames (which carry vt100::Screen::contents_formatted
  output, typically 4-15 KB) causing the client to freeze and the server
  to spin at 100% retrying the screen sync.  64 KB matches the IPv4 UDP
  MTU ceiling and still provides meaningful DoS protection.
@CraZySacX CraZySacX self-assigned this Apr 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

❌ Patch coverage is 98.70130% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.41%. Comparing base (506f81b) to head (fa5a115).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
keygen/src/cli.rs 94.73% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #19      +/-   ##
==========================================
+ Coverage   54.35%   63.41%   +9.06%     
==========================================
  Files          33       32       -1     
  Lines        4686     5082     +396     
==========================================
+ Hits         2547     3223     +676     
+ Misses       2139     1859     -280     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Add `libmoshpit/fuzz/fuzz_targets/regression_frame.rs` and
  `regression_encframe.rs` to capture fuzzer-discovered edge cases.
- Include a specific regression test for `regression_crash_6720028039`,
  which was identified as an OOM issue in `Frame::parse`.
- Fix OOM vulnerability in both `Frame::parse` and `EncryptedFrame::parse`
  by enforcing a 64KB memory limit during bincode decoding. This
  prevents malicious payloads from triggering large allocations.
- Integrate the new fuzzer corpus generated during verification.
- Update root `.gitignore` to recursively ignore all `target/`
  directories (fixing accidental staging of fuzz build artifacts).
The periodic 50 ms screen-state sync task previously woke every tick,
held the vt100 emulator lock, formatted the entire screen into a byte
buffer, and hashed it — all to detect whether the screen had changed.
This caused continuous measurable CPU usage even when the terminal was
completely idle.

Replace the hash approach with an Arc<AtomicU64> dirty_counter stored
in SessionRecord.  The counter is incremented (Ordering::Relaxed) by:
  - spawn_pty_reader: once per MTU-sized PTY output chunk
  - spawn_pty: once per terminal Resize event

The sync task now does a single atomic load per 50 ms tick.  If the
counter has not advanced since the last tick the task continues
immediately with zero lock contention, no allocation, and no emulator
formatting.  Formatting only occurs when the screen has actually changed.

Also add unit tests for keygen module and fix associated clippy lints:
  - keygen/cli.rs: fix Cli::command() test ambiguity with explicit trait
  - keygen/runtime.rs: needless_pass_by_value, uninlined_format_args,
    manual_string_new
  - keygen/main.rs: mark main with #[cfg_attr(coverage_nightly, coverage(off))]
@CraZySacX CraZySacX merged commit e4a5ed3 into master May 1, 2026
29 checks passed
@CraZySacX CraZySacX deleted the 18-security-analysis branch May 1, 2026 15:21
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.

Security Analysis

1 participant