T09 · Insecure Skill Coding Practices
Error
- Location
- templates/safe_motion_skill.py:58
- Finding
- Non-Finite Numeric Values Bypass Physical Motion Safety Limits<![CDATA[ ## Vulnerability Details **File Location**: `templates/safe_motion_skill.py`, lines 58–98 **Vulnerability Type**: Improper validation of non-finite floating-point values **Risk Level**: High ### Vulnerable Code ```python if max_forward_m <= 0 or max_left_m <= 0 or max_turn_degrees <= 0: return "Refused: all movement limits must be positive." if max_forward_m > 1.0 or max_left_m > 1.0 or max_turn_degrees > 90.0: return "Refused: requested limits are too large for a safe default wrapper." self.max_forward_m = max_forward_m self.max_left_m = max_left_m self.max_turn_degrees = max_turn_degrees return ( "Safe motion limits updated: " f"forward={self.max_forward_m} m, " f"left={self.max_left_m} m, " f"turn={self.max_turn_degrees} degrees." ) @skill def safe_relative_move( self, forward: float = 0.0, left: float = 0.0, degrees: float = 0.0, ) -> str: """Move the robot a small relative amount after validating safety limits. Args: forward: Forward/backward distance in meters. Positive is forward. left: Left/right distance in meters. Positive is left. degrees: Turn in degrees. Positive is counterclockwise. """ if abs(forward) > self.max_forward_m: return f"Refused: forward={forward} exceeds limit {self.max_forward_m}." if abs(left) > self.max_left_m: return f"Refused: left={left} exceeds limit {self.max_left_m}." if abs(degrees) > self.max_turn_degrees: return f"Refused: degrees={degrees} exceeds limit {self.max_turn_degrees}." if forward == 0.0 and left == 0.0 and degrees == 0.0: return "No movement requested." result = self._motion.relative_move(forward=forward, left=left, degrees=degrees) return f"Safe relative move requested. Underlying result: {result}" ``` ### Technical Analysis The validation relies exclusively on ordered comparisons. Under IEEE-754 floating-point semantics, comparisons such as `NaN <= 0`, `NaN > 1.0` ...[truncated 2096 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Reject all non-finite inputs before performing range comparisons or updating state: ```python from math import isfinite limits = (max_forward_m, max_left_m, max_turn_degrees) if not all(isfinite(value) for value in limits): return "Refused: all movement limits must be finite." if max_forward_m <= 0 or max_left_m <= 0 or max_turn_degrees <= 0: return "Refused: all movement limits must be positive." ``` Apply the same rule to every motion request: ```python values = (forward, left, degrees) if not all(isfinite(value) for value in values): return "Refused: all movement values must be finite." ``` Additional hardening should include: - Validate all fields before mutating any limit. - Keep immutable, trusted maximum ceilings separate from agent-configurable limits. - Consider removing `configure_safe_motion_limits` from agent-facing tools and loading limits from trusted deployment configuration. - Make the downstream motion provider independently validate finite values and enforce its own physical bounds. - Add unit tests for `NaN`, positive infinity, negative infinity, signed zero, exact boundaries, and values just above each boundary. - Verify whether the MCP JSON layer rejects non-standard numeric constants and configure strict JSON parsing where available. ]]>
