T09 · Insecure Skill Coding Practices
- Location
check_ipo.py:48- Finding
Untrusted Remote Content Is Emitted as Agent-Facing Markdown Without Sanitization
- Content
View full analysis
]*>[^<]*', '', name).strip() listing_date_str = match.group(3).strip() current_price = match.group(4).strip().replace(" ", "").strip() ipo_price = match.group(5).strip().replace(" ", "").strip() def format_subscription(item: dict) -> str: """Format subscription item for notification.""" price = item.get("confirmed_price") or item.get("expected_price") or "-" date_str = format_date_with_weekday(item['date_range'], item['start_date']) url = item.get('url', '') name_with_link = f"[{item['name']}]({url})" if url else item['name'] return f"📋 {name_with_link}\n 청약: {date_str}\n 공모가: {price}\n 주간사: {item['underwriter']}" def format_listing(item: dict) -> str: """Format listing item for notification.""" price = item.get("ipo_price") or "-" try: listing_date = datetime.fromisoformat(item['listing_date']).date() wd = get_weekday_kr(listing_date) date_str = f"{listing_date.month:02d}/{listing_date.day:02d}({wd})" except: date_str = item['listing_date'] url = item.get('url', '') name_with_link = f"[{item['name']}]({url})" if url else item['name'] ...[truncated 2845 chars]- Remediation
View remediation
`, and `#`. 2. **Apply strict field validation.** - Limit company and underwriter names to expected Unicode letters, digits, spaces, and a small allowlist of punctuation. - Validate prices against an expected numeric and separator format. - Reject unexpected line breaks and control characters. - Enforce reasonable maximum lengths for every extracted field. 3. **Separate untrusted data from agent instructions.** Mark fetched values explicitly as external data and ensure downstream prompts state that notification content must not be interpreted as commands or policy instructions. 4. **Prefer plain-text output where rich Markdown is unnecessary.** If Markdown links are retained, construct all link destinations exclusively from locally validated identifiers and escape the visible label. 5. **Use a dedicated sanitization helper**, for example: ```python def sanitize_text(value: str, max_length: int = 120) -> str: value = re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]", "", value) value = value.replace("\r", " ").replace("\n", " ") value = re.sub(r"\s+", " ", value).strip() value = value[:max_length] for char in ("\\", "[", "]", "(", ")", "*", "_", "`", "~", ">", "#"): value = value.replace(char, "\\" + char) return value ``` 6. **Apply sanitization immediately after parsing** so every later formatter receives normalized data rather than raw external content. 7. **Add security tests** containing Markdown links, multiline instruction text, control characters, oversized fields, and malformed Unicode to verify that generated alerts remain inert. ]]>
