3 Commits

Author SHA1 Message Date
KaraZajac 6dcfb65686 Release 1.1.1: UI updates
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 21:44:51 -05:00
KaraZajac fef1380d3a UI Updates 2026-02-17 21:42:20 -05:00
KaraZajac ceeef351fd UI updates 2026-02-17 21:37:52 -05:00
5 changed files with 56 additions and 8 deletions
+8
View File
@@ -2,6 +2,14 @@
All notable changes to KAT are documented here. All notable changes to KAT are documented here.
## [1.1.1] - 2026-02-13
### Changed
- **UI updates** — Vulnerability panel (green border when vuln found, green “encryption broken” text); signal action menu shows TX Lock/Unlock/Trunk/Panic only for encoder-capable captures (unknown/decoded get Replay only).
---
## [1.1.0] - 2026-02-13 ## [1.1.0] - 2026-02-13
### Added ### Added
Generated
+1 -1
View File
@@ -444,7 +444,7 @@ dependencies = [
[[package]] [[package]]
name = "kat" name = "kat"
version = "1.0.2" version = "1.1.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"atty", "atty",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "kat" name = "kat"
version = "1.1.0" version = "1.1.1"
edition = "2021" edition = "2021"
description = "Keyfob Analysis Toolkit - HackRF/RTL-SDR signal capture, decode, and transmit (HackRF only)" description = "Keyfob Analysis Toolkit - HackRF/RTL-SDR signal capture, decode, and transmit (HackRF only)"
authors = ["KAT Team"] authors = ["KAT Team"]
+30 -5
View File
@@ -1006,12 +1006,18 @@ impl App {
// -- Signal Action Menu helpers -- // -- Signal Action Menu helpers --
/// Signal actions shown in the menu: all if HackRF (TX), else only export and delete. /// Signal actions shown in the menu. With HackRF: Replay always; Lock/Unlock/Trunk/Panic only when
/// the selected capture is encoder-capable (unknown or decoded-only signals get Replay only).
/// Without TX (e.g. RTL-SDR): only export and delete.
pub fn available_signal_actions(&self) -> Vec<SignalAction> { pub fn available_signal_actions(&self) -> Vec<SignalAction> {
if self.radio.as_ref().map_or(false, |r| r.supports_tx()) { let has_tx = self.radio.as_ref().map_or(false, |r| r.supports_tx());
SignalAction::ALL.to_vec() let encoder_capable = self
} else { .selected_capture
SignalAction::ALL .and_then(|idx| self.captures.get(idx))
.map_or(false, |c| c.status == crate::capture::CaptureStatus::EncoderCapable);
if !has_tx {
return SignalAction::ALL
.iter() .iter()
.filter(|a| { .filter(|a| {
matches!( matches!(
@@ -1020,6 +1026,25 @@ impl App {
) )
}) })
.copied() .copied()
.collect();
}
if encoder_capable {
SignalAction::ALL.to_vec()
} else {
// Unknown or decoded-only: only Replay + export + delete (no TX Lock/Unlock/Trunk/Panic)
SignalAction::ALL
.iter()
.filter(|a| {
!matches!(
a,
SignalAction::Lock
| SignalAction::Unlock
| SignalAction::Trunk
| SignalAction::Panic
)
})
.copied()
.collect() .collect()
} }
} }
+16 -1
View File
@@ -314,8 +314,22 @@ fn render_vulnerability_panel(
capture.model.as_deref(), capture.model.as_deref(),
capture.region.as_deref(), capture.region.as_deref(),
); );
let vuln_found = capture.status == CaptureStatus::EncoderCapable || !vulns.is_empty();
let mut lines = Vec::new(); let mut lines = Vec::new();
// When we can encode, the encryption is broken — complete emulation is available.
if capture.status == CaptureStatus::EncoderCapable {
let emu_style = Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD);
lines.push(Line::from(Span::styled(
" Encryption is broken — Complete emulation of the keyfob is available",
emu_style,
)));
lines.push(Line::from(Span::raw("")));
}
if vulns.is_empty() { if vulns.is_empty() {
let has_meta = capture.year.is_some() let has_meta = capture.year.is_some()
|| capture.make.is_some() || capture.make.is_some()
@@ -350,9 +364,10 @@ fn render_vulnerability_panel(
} }
} }
let border_color = if vuln_found { Color::Green } else { Color::Yellow };
let block = Block::default() let block = Block::default()
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(Style::default().fg(Color::Yellow)) .border_style(Style::default().fg(border_color))
.title(" Vulnerability "); .title(" Vulnerability ");
let inner = block.inner(area); let inner = block.inner(area);
frame.render_widget(block, area); frame.render_widget(block, area);