Conversation
Enforce fail-safe exit codes, interpreter allowlist, and 0600 file permissions while adding bash safe-mode reset and a 1 MiB paste limit across shell hooks and CLIIntroduce explicit rc handling in shell hooks for command and paste, add interpreter allowlisting in 📍Where to StartStart with interpreter gating in Macroscope summarized 9f2984c. |
e7550a1 to
383e66c
Compare
| let mut open_opts = OpenOptions::new(); | ||
| open_opts.create(true).append(true); | ||
| use std::os::unix::fs::OpenOptionsExt; | ||
| open_opts.mode(0o600); |
There was a problem hiding this comment.
🟢 Low
src/audit.rs:175 The test assumes mode(0o600) produces exactly 0o600 permissions, but the process umask is ANDed against the mode. Consider either saving/restoring umask around the test or documenting why this is acceptable for your CI environment.
🚀 Want me to fix this? Reply ex: "fix it for me".
383e66c to
418603c
Compare
| const ALLOWED_FAMILIES: &[&str] = &["python", "ruby", "perl", "node"]; | ||
|
|
||
| fn is_allowed_interpreter(interpreter: &str) -> bool { | ||
| let base = interpreter.rsplit('/').next().unwrap_or(interpreter); |
There was a problem hiding this comment.
🟢 Low
src/runner.rs:34 On Windows, paths use \ as separators, so rsplit('/') won't extract the basename correctly. Consider using std::path::Path::file_name() or splitting on both separators.
- let base = interpreter.rsplit('/').next().unwrap_or(interpreter);
+ let base = std::path::Path::new(interpreter)
+ .file_name()
+ .and_then(|s| s.to_str())
+ .unwrap_or(interpreter);🚀 Want me to fix this? Reply ex: "fix it for me".
|
|
||
| #[cfg(unix)] | ||
| #[test] | ||
| fn test_receipt_save_permissions_0600() { |
There was a problem hiding this comment.
🟢 Low
src/receipt.rs:190 This test manually recreates file creation logic rather than calling save(). If save() has a bug setting permissions, this test would still pass. Consider calling Receipt::save() directly and checking the resulting file's permissions.
🚀 Want me to fix this? Reply ex: "fix it for me".
dbf4dd5 to
ac6de5f
Compare
68c2479 to
3768713
Compare
…ist, and hardening Six security fixes from external audit: - SEC-CRIT-01: Handle unexpected tirith exit codes in all shell hooks. Bash enter mode degrades to preexec; zsh/fish/PS warn+execute; all paste paths fail-closed (discard). - SEC-HIGH-01: Interpreter allowlist in runner.rs — two-tier matching (exact names + versioned families like python3.11). Check runs before user confirmation prompt. - SEC-HIGH-03: Bounded stdin read in paste.rs — 1 MiB cap via Read::take(). - SEC-HIGH-04: File permissions 0600 on audit log, receipts, cache, and last-trigger files (new files + legacy hardening via set_permissions). - SEC-MED-03: SHA256 hex validation in receipt load/save/verify — prevents path traversal via crafted hash values. - Short-hash panic guard: safe truncation via truncate_bytes() replaces all &sha256[..12] slice operations. Also includes Issue #20 bash enter mode infrastructure (bind-x override, startup health gate, persistent safe mode, degrade-to-preexec) and CR normalization improvements from prior work on this branch. Additional fixes: - Fix audit test env var race (test OpenOptions pattern directly) - Trim whitespace from XDG_STATE_HOME in state_dir() - Bump version to 0.1.9 230 tests passing (148 unit + 44 integration + 18 golden + 17 policy + 3 CLI).
3768713 to
9f2984c
Compare
Summary
Six security fixes from external audit, plus Issue #20 bash enter mode infrastructure:
runner.rs— two-tier matching (exact names likesh/bash+ versioned families likepython3.11). Check runs before user confirmation prompt.paste.rs— 1 MiB cap viaRead::take().0600on audit log, receipts, cache, and last-trigger files (new files viaOpenOptionsExt::mode()+ legacy hardening viaset_permissions).load()/save()/verify()— prevents path traversal via crafted hash values.short_hash()viatruncate_bytes()replaces all&sha256[..12]slice operations.Also includes bash enter mode infrastructure (bind-x Enter override, startup health gate, persistent safe mode, PROMPT_COMMAND delivery, degrade-to-preexec) and CR normalization improvements.
230 tests passing (148 unit + 44 integration + 18 golden + 17 policy + 3 CLI).
Test plan
cargo fmt --allcleancargo clippy --workspace -- -D warningscleancargo test --workspace— 230/230 passembedded_shell_hooks_match_repo_hooks)bash_hook_unexpected_rc_degrades_in_pty)paste_oversized_input_rejected)receipt_verify_invalid_sha256_rejected)echo "test" | tirith paste --shell posix→ exit 0yes | head -c 2000000 | tirith paste --shell posix→ "exceeds 1 MiB"tirith receipt verify "../../etc/passwd"→ "invalid sha256"