security: Fix 10 vulnerabilities, remove 12 dead code instances

Critical fixes:
- Remove hardcoded admin/admin123 credentials from UserManager
- Enable JWT signature verification (was disabled for debugging)
- Redact secrets from /dev/config endpoint (was exposing os.environ)
- Remove hardcoded SSH admin/admin credentials from hardware service
- Add channel validation to prevent command injection in router interface

Rust fixes:
- Replace partial_cmp().unwrap() with .unwrap_or(Equal) to prevent
  NaN panics in 6 locations across core, signal, nn, mat crates
- Replace .expect()/.unwrap() with safe fallbacks in utils, csi_receiver
- Replace SystemTime unwrap with unwrap_or_default

Dead code removed:
- Duplicate imports (CORSMiddleware, os, Path, ABC, subprocess)
- Unused AdaptiveRateLimit/RateLimitStorage/RedisRateLimitStorage (~110 lines)
- Unused _log_authentication_event method
- Unused Confidence::new_unchecked in Rust
- Fix bare except: clause to except Exception:

https://claude.ai/code/session_01Ki7pvEZtJDvqJkmyn6B714
This commit is contained in:
Claude
2026-02-28 07:04:22 +00:00
parent ea452ba5fc
commit 7afdad0723
23 changed files with 81 additions and 192 deletions

View File

@@ -172,16 +172,6 @@ impl Confidence {
/// Creates a confidence value without validation (for internal use).
///
/// # Safety
///
/// The caller must ensure the value is in [0.0, 1.0].
#[must_use]
#[allow(dead_code)]
pub(crate) fn new_unchecked(value: f32) -> Self {
debug_assert!((0.0..=1.0).contains(&value));
Self(value)
}
/// Returns the raw confidence value.
#[must_use]
pub fn value(&self) -> f32 {
@@ -1009,7 +999,12 @@ impl PoseEstimate {
pub fn highest_confidence_person(&self) -> Option<&PersonPose> {
self.persons
.iter()
.max_by(|a, b| a.confidence.value().partial_cmp(&b.confidence.value()).unwrap())
.max_by(|a, b| {
a.confidence
.value()
.partial_cmp(&b.confidence.value())
.unwrap_or(std::cmp::Ordering::Equal)
})
}
}

View File

@@ -98,8 +98,11 @@ pub fn moving_average(data: &Array1<f64>, window_size: usize) -> Array1<f64> {
let mut result = Array1::zeros(data.len());
let half_window = window_size / 2;
// Safe unwrap: ndarray Array1 is always contiguous
let slice = data.as_slice().expect("Array1 should be contiguous");
// ndarray Array1 is always contiguous, but handle gracefully if not
let slice = match data.as_slice() {
Some(s) => s,
None => return data.clone(),
};
for i in 0..data.len() {
let start = i.saturating_sub(half_window);