T09 · Insecure Skill Coding Practices
- Location
scripts/validate_lesson.py:17- Finding
Unhandled Null Array Fields Cause Validator Denial of Service
- Content
View full analysis
Vulnerability Details
File Location:
scripts/validate_lesson.py, lines 17–48
Vulnerability Type: Improper input type handling resulting in an uncaught exception
Risk Level: Lowpython for key in ("assumptions", "objectives", "agenda", "slides", "activities", "quiz", "homework"): if not isinstance(data.get(key), list): errors.append(f"{key}: must be an array") for index, item in enumerate(data.get("agenda", [])): if not isinstance(item, dict): errors.append(f"agenda[{index}]: must be an object") continue for key in ("title", "teacher_action", "learner_action", "check"): if not isinstance(item.get(key), str) or not item[key].strip(): errors.append(f"agenda[{index}].{key}: must be a non-empty string") minutes = item.get("minutes") if not isinstance(minutes, int) or isinstance(minutes, bool) or minutes <= 0: errors.append(f"agenda[{index}].minutes: must be a positive integer") if isinstance(duration, int) and not isinstance(duration, bool) and all( isinstance(item, dict) and isinstance(item.get("minutes"), int) and not isinstance(item.get("minutes"), bool) for item in data.get("agenda", []) ): total = sum(item["minutes"] for item in data.get("agenda", [])) if total != duration: errors.append(f"agenda minutes total {total}, expected duration_minutes {duration}") for section, fields in { "slides": ("title", "key_point", "teacher_notes"), "activities": ("title", "mode", "instructions", "expected_observation", "fallback"), "quiz": ("question", "answer", "explanation", "next_step"), }.items(): for index, item in enumerate(data.get(section, [])): if not isinstance(item, dict): errors.append(f"{section}[{index}]: must be an object") continue for key in fields: if not isinstance(item.get(key), str) or not item[key].strip ...[truncated 2310 chars]- Remediation
View remediation
Remediation Suggestions
Normalize or guard every collection before iterating over it. After recording a type error, nested validation should be skipped for that field.
A suitable approach is:
python agenda = data.get("agenda") if not isinstance(agenda, list): errors.append("agenda: must be an array") agenda = [] for index, item in enumerate(agenda): # Validate agenda entries. for section, fields in section_fields.items(): items = data.get(section) if not isinstance(items, list): errors.append(f"{section}: must be an array") continue for index, item in enumerate(items): # Validate section entries.Use the normalized
agendavariable consistently for iteration, duration checks, and summation. Apply equivalent guards to all expected arrays, includingassumptions,objectives,slides,activities,quiz, andhomework.Add regression tests covering explicit
null, strings, objects, numbers, and booleans for every array field. Tests should verify that malformed input produces controlled validation messages and the intended nonzero exit code without a traceback.
