docs/edge-modules/ai-security.md
Tamper detection and behavioral anomaly profiling that protect the sensing system from manipulation. These modules detect replay attacks, signal injection, jamming, and unusual behavior patterns -- all running on-device with no cloud dependency.
| Module | File | What It Does | Event IDs | Budget |
|---|---|---|---|---|
| Signal Shield | ais_prompt_shield.rs | Detects replay, injection, and jamming attacks on CSI data | 820-823 | S (<5 ms) |
| Behavioral Profiler | ais_behavioral_profiler.rs | Learns normal behavior and detects anomalous deviations | 825-828 | S (<5 ms) |
ais_prompt_shield.rs)What it does: Detects three types of attack on the WiFi sensing system:
How it works:
use wifi_densepose_wasm_edge::ais_prompt_shield::PromptShield;
let mut shield = PromptShield::new(); // const fn, zero-alloc
let events = shield.process_frame(&phases, &litudes); // per-frame analysis
let calibrated = shield.is_calibrated(); // true after 100 frames
let frames = shield.frame_count(); // total frames processed
| Event ID | Constant | Value | Frequency |
|---|---|---|---|
| 820 | EVENT_REPLAY_ATTACK | 1.0 (detected) | On detection (cooldown: 40 frames) |
| 821 | EVENT_INJECTION_DETECTED | Fraction of subcarriers with spikes [0.25, 1.0] | On detection (cooldown: 40 frames) |
| 822 | EVENT_JAMMING_DETECTED | SNR drop in dB (10 * log10(baseline/current)) | On detection (cooldown: 40 frames) |
| 823 | EVENT_SIGNAL_INTEGRITY | Composite integrity score [0.0, 1.0] | Every 20 frames |
| Constant | Value | Purpose |
|---|---|---|
MAX_SC | 32 | Maximum subcarriers processed |
HASH_RING | 64 | Size of replay detection hash ring buffer |
INJECTION_FACTOR | 10.0 | Amplitude jump threshold (10x previous) |
INJECTION_FRAC | 0.25 | Minimum fraction of subcarriers with spikes |
JAMMING_SNR_FRAC | 0.10 | SNR must drop below 10% of baseline |
JAMMING_CONSEC | 5 | Consecutive low-SNR frames required |
BASELINE_FRAMES | 100 | Calibration period length |
COOLDOWN | 40 | Frames between repeated alerts (2 seconds at 20 Hz) |
The composite score (event 823) is emitted every 20 frames and ranges from 0.0 (compromised) to 1.0 (clean):
| Factor | Score Reduction | Condition |
|---|---|---|
| Replay detected | -0.4 | Frame hash matches ring buffer |
| Injection detected | up to -0.3 | Proportional to injection fraction |
| SNR degradation | up to -0.3 | Proportional to SNR drop below baseline |
The hash function quantizes three frame statistics to integer precision before hashing:
hash = FNV_OFFSET (2166136261)
for each of [mean_phase*100, mean_amp*100, amp_variance*100]:
for each byte in value.to_le_bytes():
hash ^= byte
hash = hash.wrapping_mul(FNV_PRIME) // FNV_PRIME = 16777619
This means two frames must have nearly identical statistical profiles (within 1% quantization) to trigger a replay alert.
Calibration (frames 1-100):
Normal CSI with varying phases -> baseline SNR established
No alerts emitted during calibration
Frame 150: Normal operation
phases = [0.31, 0.28, ...], amps = [1.02, 0.98, ...]
hash = 0xA7F3B21C -> stored in ring buffer
No alerts
Frame 200: Attacker replays frame 150 exactly
phases = [0.31, 0.28, ...], amps = [1.02, 0.98, ...]
hash = 0xA7F3B21C -> MATCH found in ring buffer!
-> EVENT_REPLAY_ATTACK = 1.0
-> EVENT_SIGNAL_INTEGRITY = 0.6 (reduced by 0.4)
Frame 300: Normal amplitudes
amps = [1.0, 1.1, 0.9, 1.0, ...]
Frame 301: Adversary injects strong signal
amps = [15.0, 12.0, 14.0, 13.0, ...] (>10x jump on all subcarriers)
injection_fraction = 1.0 (100% of subcarriers spiked)
-> EVENT_INJECTION_DETECTED = 1.0
-> EVENT_SIGNAL_INTEGRITY = 0.4
ais_behavioral_profiler.rs)What it does: Learns what "normal" behavior looks like over time, then detects anomalous deviations. It builds a 6-dimensional behavioral profile using online statistics (Welford's algorithm) and flags when new observations deviate significantly from the learned baseline.
How it works: Every 200 frames, the module computes a 6D feature vector from the observation window. During the learning phase (first 1000 frames), it trains Welford accumulators for each dimension. After maturity, it computes per-dimension Z-scores and a combined RMS Z-score. If the combined score exceeds 3.0, an anomaly is reported.
| # | Dimension | Description | Typical Range |
|---|---|---|---|
| 0 | Presence Rate | Fraction of frames with presence | [0, 1] |
| 1 | Average Motion | Mean motion energy in window | [0, ~5] |
| 2 | Average Persons | Mean person count | [0, ~4] |
| 3 | Activity Variance | Variance of motion energy | [0, ~10] |
| 4 | Transition Rate | Presence state changes per frame | [0, 0.5] |
| 5 | Dwell Time | Average consecutive presence run length | [0, 200] |
use wifi_densepose_wasm_edge::ais_behavioral_profiler::BehavioralProfiler;
let mut bp = BehavioralProfiler::new(); // const fn
let events = bp.process_frame(present, motion, n_persons); // per-frame
let mature = bp.is_mature(); // true after learning
let anomalies = bp.total_anomalies(); // cumulative count
let mean = bp.dim_mean(0); // mean of dimension 0
let var = bp.dim_variance(1); // variance of dim 1
| Event ID | Constant | Value | Frequency |
|---|---|---|---|
| 825 | EVENT_BEHAVIOR_ANOMALY | Combined Z-score (RMS, > 3.0) | On detection (cooldown: 100 frames) |
| 826 | EVENT_PROFILE_DEVIATION | Index of most deviant dimension (0-5) | Paired with anomaly |
| 827 | EVENT_NOVEL_PATTERN | Count of dimensions with Z > 2.0 | When 3+ dimensions deviate |
| 828 | EVENT_PROFILE_MATURITY | Days since sensor start | On maturity + periodically |
| Constant | Value | Purpose |
|---|---|---|
N_DIM | 6 | Behavioral dimensions |
LEARNING_FRAMES | 1000 | Frames before profiler matures |
ANOMALY_Z | 3.0 | Combined Z-score threshold for anomaly |
NOVEL_Z | 2.0 | Per-dimension Z-score threshold for novelty |
NOVEL_MIN | 3 | Minimum deviating dimensions for NOVEL_PATTERN |
OBS_WIN | 200 | Observation window size (frames) |
COOLDOWN | 100 | Frames between repeated anomaly alerts |
MATURITY_INTERVAL | 72000 | Frames between maturity reports (1 hour at 20 Hz) |
Each dimension maintains running statistics without storing all past values:
On each new observation x:
count += 1
delta = x - mean
mean += delta / count
m2 += delta * (x - mean)
Variance = m2 / count
Z-score = |x - mean| / sqrt(variance)
This is numerically stable and requires only 12 bytes per dimension (count + mean + m2).
Learning phase (day 1-2):
Normal pattern: 1 person, present 8am-10pm, moderate motion
Profile matures -> EVENT_PROFILE_MATURITY = 0.58 (days)
Day 3, 3am:
Observation window: presence=1, high motion, 1 person
Z-scores: presence_rate=2.8, motion=4.1, persons=0.3,
variance=3.5, transition=2.2, dwell=1.9
Combined Z = sqrt(mean(z^2)) = 3.4 > 3.0
-> EVENT_BEHAVIOR_ANOMALY = 3.4
-> EVENT_PROFILE_DEVIATION = 1 (motion dimension most deviant)
-> EVENT_NOVEL_PATTERN = 3 (3 dimensions above Z=2.0)
| Attack | Detection Module | Method | False Positive Rate |
|---|---|---|---|
| CSI frame replay | Signal Shield | FNV-1a hash ring matching | Low (1% quantization) |
| Signal injection (e.g., rogue AP) | Signal Shield | >25% subcarriers with >10x amplitude spike | Very low |
| Broadband jamming | Signal Shield | SNR drop below 10% of baseline for 5+ frames | Very low |
| Narrowband jamming | Partially -- Signal Shield | May not trigger if < 25% subcarriers affected | Medium |
| Behavioral anomaly (intruder at unusual time) | Behavioral Profiler | Combined Z-score > 3.0 across 6 dimensions | Low after maturation |
| Gradual environmental change | Behavioral Profiler | Welford stats adapt, may flag if change is abrupt | Very low |
| Attack | Why Not | Recommended Mitigation |
|---|---|---|
| Sophisticated replay with slight phase variation | FNV-1a uses 1% quantization; small perturbations change the hash | Add temporal correlation checks (consecutive frame deltas) |
| Man-in-the-middle on the WiFi channel | Modules analyze CSI content, not channel authentication | Use WPA3 encryption + MAC filtering |
| Physical obstruction (blocking line-of-sight) | Looks like a person leaving, not an attack | Cross-reference with PIR sensors |
| Slow amplitude drift (gradual injection) | Below the 10x threshold per frame | Add longer-term amplitude trend monitoring |
| Firmware tampering | Modules run in WASM sandbox, cannot detect host compromise | Secure boot + signed firmware (ADR-032) |
tmp_temporal_logic_guard.rs): Its safety invariants catch impossible state combinations (e.g., "fall alert when room is empty") that indicate sensor manipulation.aut_self_healing_mesh.rs): If a node in the mesh is being jammed, the mesh can automatically reconfigure around the compromised node.| Module | State Size (approx) | Static Event Buffer |
|---|---|---|
| Signal Shield | ~420 bytes (64 hashes + 32 prev_amps + calibration) | 4 entries |
| Behavioral Profiler | ~2.4 KB (200-entry observation window + 6 Welford stats) | 4 entries |
Both modules use fixed-size arrays and static event buffers. No heap allocation. Fully no_std compliant.