T09 · Insecure Skill Coding Practices
Note
- Location
- drift_guard.py:210
- Finding
- Unbounded Drift History Growth Can Cause Local Resource Exhaustion## Vulnerability Details **File Location**: `drift_guard.py`, lines 210-221; related configuration in `config_example.py` defines `max_history_size` but the monitor does not enforce it. **Vulnerability Type**: Uncontrolled resource consumption and unbounded persistent storage **Risk Level**: Low ### Technical Analysis Every call to `monitor()` creates a measurement containing metrics and detailed drift data. `record_measurement()` appends that record to the in-memory history and then serializes the entire history back to disk: ```python record = { 'timestamp': time.time(), 'datetime': datetime.now().isoformat(), 'metrics': metrics, 'drift_score': drift_score, 'drift_details': drift_details } self.history.append(record) # Save to file history_path = Path(self.config.get('history_file', 'drift_history.json')) with open(history_path, 'w') as f: json.dump(self.history, f, indent=2) ``` The provided configuration defines a finite default: ```python # How many measurements to keep in history (0 = unlimited) 'max_history_size': 10000, ``` However, `record_measurement()` never reads or enforces `max_history_size`. Consequently, history grows without an effective bound even when an administrator believes a retention limit has been configured. The full history is also loaded into memory during initialization and rewritten on every measurement. As the file grows, each invocation consumes progressively more memory, CPU time, disk I/O, and storage. The cumulative write complexity becomes increasingly expensive because all prior records are serialized again for each new record. ### Attack Path 1. An attacker or untrusted integration obtains the ability to submit responses to a service or workflow that invokes `DriftGuard.monitor()`. 2. The attacker repeatedly submits responses, causing `record_measurement()` to append a new entry for every invocation. 3. The configured `max_history_ ...[truncated 1179 chars]
- Remediation
- ## Remediation Suggestions Enforce the configured retention limit before persisting history: ```python self.history.append(record) max_history_size = int(self.config.get('max_history_size', 10000)) if max_history_size > 0: self.history = self.history[-max_history_size:] ``` Additional hardening should include: 1. Validate that `max_history_size` is a non-negative integer and reject invalid configuration values. 2. Use an append-oriented format such as JSON Lines instead of rewriting the complete history for every measurement. 3. Implement file rotation based on record count, file size, or age. 4. Set an explicit maximum history-file size and fail safely or rotate the file when the limit is reached. 5. Write updates atomically through a temporary file followed by replacement to reduce corruption risk during interrupted writes. 6. Apply file locking if concurrent monitor processes can write to the same history file. 7. Add automated tests verifying that finite retention settings are respected and that `0` remains the only explicitly unlimited mode. 8. Monitor disk usage and emit a local warning before storage reaches a critical threshold.
