T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/pet_food_calculator.py:233
- Finding
- Insufficient Validation of Numeric Feeding and Cost Parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pet_food_calculator.py:97-98`, `scripts/pet_food_calculator.py:144-150`, and `scripts/pet_food_calculator.py:233-244` **Vulnerability Type**: Improper input validation of numeric parameters **Risk Level**: Medium ### Vulnerable Code Argument definitions accept arbitrary floating-point values: ```python ap.add_argument("--target-weight", type=float, help="ideal/target weight (starts weight-loss plan)") ap.add_argument("--food-calories", type=float, help="metabolizable energy kcal/kg (printed on the bag)") ap.add_argument("--food-price", type=float, help="price of one bag") ap.add_argument("--bag-kg", type=float, help="bag size in kg") ap.add_argument("--adult-weight", type=float, help="expected adult weight for puppies") ``` The supplied food-calorie value is used as a divisor without verifying that it is finite and positive: ```python grams_per_day = food_kcal / (args.food_calories / 1000.0) \ if args.food_calories else None ``` The bag size is also used as a divisor without validation: ```python if args.food_price and args.bag_kg and grams_per_day: monthly_kg = grams_per_day * 30.4 / 1000.0 res["cost"] = { "monthly_kg": round(monthly_kg, 2), "monthly_cost": round(monthly_kg / args.bag_kg * args.food_price, 2), "currency_note": "in the same currency as --food-price", "bag_lasts_days": round(args.bag_kg / monthly_kg * 30.4), } ``` Only current body weight receives an explicit positivity check: ```python if args.weight <= 0: ap.error("--weight must be positive") if args.target_weight and args.target_weight >= args.weight: print("Note: target weight ≥ current weight — no weight-loss plan " "will be generated.", file=sys.stderr) ``` ### Technical Analysis Python's `float` parser accepts negative values, `nan`, `inf`, and `-inf`. The calculator does not consistently reject these va ...[truncated 3006 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Create a reusable argument parser that rejects non-finite and non-positive values: ```python def positive_finite(value: str) -> float: try: number = float(value) except ValueError as exc: raise argparse.ArgumentTypeError("must be a number") from exc if not math.isfinite(number) or number <= 0: raise argparse.ArgumentTypeError( "must be a finite number greater than zero" ) return number ``` 2. Apply it to every parameter that must be positive: ```python ap.add_argument("--weight", type=positive_finite, required=True) ap.add_argument("--target-weight", type=positive_finite) ap.add_argument("--food-calories", type=positive_finite) ap.add_argument("--food-price", type=positive_finite) ap.add_argument("--bag-kg", type=positive_finite) ap.add_argument("--adult-weight", type=positive_finite) ``` 3. Add realistic domain bounds where appropriate. For example, reject implausible animal weights, food energy densities, bag sizes, and expected adult weights rather than accepting arbitrarily large finite values. 4. Validate relationships between fields before calling `compute()`: - Ensure target weight is biologically plausible. - Clearly distinguish maintenance, weight-loss, and weight-gain requests. - Require `--food-price` and `--bag-kg` together if either is supplied. - Permit `--adult-weight` only for growing dogs, or explicitly document other behavior. 5. Add defensive checks immediately before every division so future refactoring cannot reintroduce zero or non-finite divisors. 6. Configure JSON serialization to reject non-finite values: ```python json.dumps(res, indent=2, allow_nan=False) ``` 7. Add regression tests covering: - Zero and negative values for every numeric parameter. - `nan`, `inf`, and `-inf`. - Extremely small and extremely large finite values. - Invalid ta ...[truncated 213 chars]
