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

@@ -380,10 +380,19 @@ if settings.metrics_enabled:
if settings.is_development and settings.enable_test_endpoints:
@app.get(f"{settings.api_prefix}/dev/config")
async def dev_config():
"""Get current configuration (development only)."""
"""Get current configuration (development only).
Returns a sanitized view -- secret keys and passwords are redacted.
"""
_sensitive = {"secret", "password", "token", "key", "credential", "auth"}
raw = settings.dict()
sanitized = {
k: "***REDACTED***" if any(s in k.lower() for s in _sensitive) else v
for k, v in raw.items()
}
domain_config = get_domain_config()
return {
"settings": settings.dict(),
"settings": sanitized,
"domain_config": domain_config.to_dict()
}

View File

@@ -220,27 +220,8 @@ class AuthMiddleware(BaseHTTPMiddleware):
except Exception as e:
raise ValueError(f"Token verification error: {e}")
def _log_authentication_event(self, request: Request, event_type: str, details: Dict[str, Any] = None):
"""Log authentication events for security monitoring."""
client_ip = request.client.host if request.client else "unknown"
user_agent = request.headers.get("user-agent", "unknown")
log_data = {
"event_type": event_type,
"timestamp": datetime.utcnow().isoformat(),
"client_ip": client_ip,
"user_agent": user_agent,
"path": request.url.path,
"method": request.method
}
if details:
log_data.update(details)
if event_type in ["authentication_failed", "token_expired", "invalid_token"]:
logger.warning(f"Auth event: {log_data}")
else:
logger.info(f"Auth event: {log_data}")
# TODO: Wire up authentication event logging in dispatch() for
# security monitoring (login failures, token expiry, etc.).
class TokenBlacklist:

View File

@@ -323,107 +323,3 @@ class RateLimitMiddleware(BaseHTTPMiddleware):
del self.blocked_clients[client_id]
class AdaptiveRateLimit:
"""Adaptive rate limiting based on system load."""
def __init__(self):
self.base_limits = {}
self.current_multiplier = 1.0
self.load_history = deque(maxlen=60) # Keep 1 minute of load data
def update_system_load(self, cpu_percent: float, memory_percent: float):
"""Update system load metrics."""
load_score = (cpu_percent + memory_percent) / 2
self.load_history.append(load_score)
# Calculate adaptive multiplier
if len(self.load_history) >= 10:
avg_load = sum(self.load_history) / len(self.load_history)
if avg_load > 80:
self.current_multiplier = 0.5 # Reduce limits by 50%
elif avg_load > 60:
self.current_multiplier = 0.7 # Reduce limits by 30%
elif avg_load < 30:
self.current_multiplier = 1.2 # Increase limits by 20%
else:
self.current_multiplier = 1.0 # Normal limits
def get_adjusted_limit(self, base_limit: int) -> int:
"""Get adjusted rate limit based on system load."""
return max(1, int(base_limit * self.current_multiplier))
class RateLimitStorage:
"""Abstract interface for rate limit storage (Redis implementation)."""
async def get_count(self, key: str, window: int) -> int:
"""Get current request count for key within window."""
raise NotImplementedError
async def increment(self, key: str, window: int) -> int:
"""Increment request count and return new count."""
raise NotImplementedError
async def is_blocked(self, client_id: str) -> bool:
"""Check if client is blocked."""
raise NotImplementedError
async def block_client(self, client_id: str, duration: int):
"""Block client for duration seconds."""
raise NotImplementedError
class RedisRateLimitStorage(RateLimitStorage):
"""Redis-based rate limit storage for production use."""
def __init__(self, redis_client):
self.redis = redis_client
async def get_count(self, key: str, window: int) -> int:
"""Get current request count using Redis sliding window."""
now = time.time()
pipeline = self.redis.pipeline()
# Remove old entries
pipeline.zremrangebyscore(key, 0, now - window)
# Count current entries
pipeline.zcard(key)
results = await pipeline.execute()
return results[1]
async def increment(self, key: str, window: int) -> int:
"""Increment request count using Redis."""
now = time.time()
pipeline = self.redis.pipeline()
# Add current request
pipeline.zadd(key, {str(now): now})
# Remove old entries
pipeline.zremrangebyscore(key, 0, now - window)
# Set expiration
pipeline.expire(key, window + 1)
# Get count
pipeline.zcard(key)
results = await pipeline.execute()
return results[3]
async def is_blocked(self, client_id: str) -> bool:
"""Check if client is blocked."""
block_key = f"blocked:{client_id}"
return await self.redis.exists(block_key)
async def block_client(self, client_id: str, duration: int):
"""Block client for duration seconds."""
block_key = f"blocked:{client_id}"
await self.redis.setex(block_key, duration, "1")
# Global adaptive rate limiter instance
adaptive_rate_limit = AdaptiveRateLimit()

View File

@@ -17,16 +17,13 @@ from src.api.dependencies import (
get_current_user_ws,
require_auth
)
from src.api.websocket.connection_manager import ConnectionManager
from src.api.websocket.connection_manager import connection_manager
from src.services.stream_service import StreamService
from src.services.pose_service import PoseService
logger = logging.getLogger(__name__)
router = APIRouter()
# Initialize connection manager
connection_manager = ConnectionManager()
# Request/Response models
class StreamSubscriptionRequest(BaseModel):

View File

@@ -181,7 +181,7 @@ class ConnectionManager:
if connection.is_active:
try:
await connection.websocket.close()
except:
except Exception:
pass # Connection might already be closed
# Remove connection