T09 · Insecure Skill Coding Practices
- Location
scripts/download_ics.py:25- Finding
Unbounded Download and Expansion of Untrusted ICS Calendar Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/download_ics.py:25-29,scripts/holiday_checker.py:21-51, andscripts/holiday_checker.py:93
Vulnerability Type: Uncontrolled resource consumption and terminal output manipulation
Risk Level: MediumVulnerable Code
scripts/download_ics.py:25-29:python response = requests.get(url, timeout=10) response.raise_for_status() with open(DATA_PATH, 'wb') as f: f.write(response.content)scripts/holiday_checker.py:21-51:python with open(file_path, 'rb') as f: try: cal = Calendar.from_ical(f.read()) for component in cal.walk(): if component.name == "VEVENT": summary = str(component.get('summary')) dtstart = component.get('dtstart') dtend = component.get('dtend') if not dtstart: continue # Get the start date start_val = dtstart.dt if isinstance(start_val, datetime.datetime): start_date = start_val.date() else: start_date = start_val # Get the end date, if present if dtend: end_val = dtend.dt if isinstance(end_val, datetime.datetime): end_date = end_val.date() else: end_date = end_val else: # Treat an event without an end date as a single-day event end_date = start_date + datetime.timedelta(days=1) # Add every date covered by the event curr = start_date while curr < end_date: holiday_map[curr] = summary curr += datetime.timede ...[truncated 3238 chars]- Remediation
View remediation
Remediation Suggestions
- Use
requests.get(..., stream=True)and read the response in bounded chunks. Reject downloads once a conservative maximum size is exceeded. - Restrict sources to HTTPS and, where configuration is not intended to be arbitrary, validate destinations against an explicit hostname allowlist.
- Validate the HTTP status, final redirect destination, and expected calendar media type before accepting the response.
- Download into a temporary file in the same directory, parse and validate it, then atomically replace the active calendar using
os.replace. Preserve the previous valid file if validation fails. - Enforce limits on total file size, calendar component count, event count, summary length, and recurrence complexity.
- Reject events whose dates fall outside a defined supported range or whose duration exceeds a reasonable maximum.
- Avoid eagerly creating a map entry for every day of every event. Store bounded intervals and compare the requested date against those intervals instead.
- Remove or escape terminal control characters from external summaries before printing them.
- Log validation failures without including unsanitized attacker-controlled values.
- Use
