diff --git a/bin/cli.py b/bin/cli.py index 92267b1..5c9181c 100644 --- a/bin/cli.py +++ b/bin/cli.py @@ -2,6 +2,7 @@ import argparse from datetime import datetime, timezone +import html import ipaddress import json import os @@ -364,7 +365,7 @@ def format_markdown_output( records: List[Dict[str, Any]] ) -> str: def scalar_to_text(value: Any) -> str: - return str(value) + return html.escape(str(value)) def format_nested_value(value: Any, indent_level: int = 0) -> List[str]: indent_prefix = " " * (indent_level * 2) @@ -376,10 +377,10 @@ def format_nested_value(value: Any, indent_level: int = 0) -> List[str]: child = value[key] if isinstance(child, (dict, list)): nested = format_nested_value(child, indent_level + 1) - lines.append(f"{indent_prefix}{key}:") + lines.append(f"{indent_prefix}{scalar_to_text(key)}:") lines.extend(nested) else: - lines.append(f"{indent_prefix}{key}: {scalar_to_text(child)}") + lines.append(f"{indent_prefix}{scalar_to_text(key)}: {scalar_to_text(child)}") return lines if isinstance(value, list): if not value: @@ -398,7 +399,7 @@ def format_nested_value(value: Any, indent_level: int = 0) -> List[str]: def to_inline(value: Any) -> str: if isinstance(value, (dict, list)): return "
".join(format_nested_value(value)) - return str(value) + return scalar_to_text(value) def response_to_table(response: Any) -> List[str]: if isinstance(response, dict): @@ -406,7 +407,7 @@ def response_to_table(response: Any) -> List[str]: return ["| Key | Value |", "| --- | --- |", "| _(empty)_ | |"] lines = ["| Key | Value |", "| --- | --- |"] for key in sorted(response.keys()): - safe_key = str(key).replace("\n", " ").replace("|", "\\|") + safe_key = scalar_to_text(key).replace("\n", " ").replace("|", "\\|") safe_value = to_inline(response[key]).replace("\n", " ").replace("|", "\\|") lines.append(f"| `{safe_key}` | {safe_value} |") return lines @@ -418,7 +419,7 @@ def response_to_table(response: Any) -> List[str]: safe_value = to_inline(item).replace("\n", " ").replace("|", "\\|") lines.append(f"| `{idx}` | {safe_value} |") return lines - safe_value = str(response).replace("\n", " ").replace("|", "\\|") + safe_value = scalar_to_text(response).replace("\n", " ").replace("|", "\\|") return ["| Value |", "| --- |", f"| `{safe_value}` |"] generated_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%SZ") @@ -440,10 +441,10 @@ def response_to_table(response: Any) -> List[str]: "## Summary", "", f"- Generated at (UTC): `{generated_at}`", - f"- Input value: `{input_value}`", - f"- Explicit type: `{explicit_type or 'auto-guessed'}`", + f"- Input value: `{html.escape(input_value)}`", + f"- Explicit type: `{html.escape(explicit_type) if explicit_type else 'auto-guessed'}`", f"- Query all guesses: `{all_guesses}`", - f"- Selected modules filter: `{', '.join(selected_modules) if selected_modules else 'none'}`", + f"- Selected modules filter: `{html.escape(', '.join(selected_modules)) if selected_modules else 'none'}`", f"- Total module query attempts: `{len(records)}`", f"- Successful queries: `{success_count}`", f"- Failed queries: `{failed_count}`", @@ -462,12 +463,12 @@ def response_to_table(response: Any) -> List[str]: for idx, record in enumerate(records, start=1): lines.extend([ - f"### {idx}. Module `{record.get('module', '')}` / Type `{record.get('attribute_type', '')}`", + f"### {idx}. Module `{html.escape(str(record.get('module', '')))}` / Type `{html.escape(str(record.get('attribute_type', '')))}`", "", - f"- Status: `{record.get('status', 'unknown')}`", - f"- Query reason: `{record.get('reason', 'n/a')}`", - f"- Queried at (UTC): `{record.get('queried_at', 'n/a')}`", - f"- Cache: `{record.get('cache', 'n/a')}`", + f"- Status: `{html.escape(str(record.get('status', 'unknown')))}`", + f"- Query reason: `{html.escape(str(record.get('reason', 'n/a')))}`", + f"- Queried at (UTC): `{html.escape(str(record.get('queried_at', 'n/a')))}`", + f"- Cache: `{html.escape(str(record.get('cache', 'n/a')))}`", "", "#### Query Parameters", "",