45 lines
1.2 KiB
Python
45 lines
1.2 KiB
Python
"""Input hardening: validate resource IDs and workspace names.
|
|
|
|
Agents hallucinate bad IDs. Catch them early with clear errors.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from honcho_cli.output import print_error
|
|
|
|
UNSAFE_CHARS = re.compile(r'[?#%\x00-\x1f\x7f/\\]')
|
|
|
|
|
|
def validate_resource_id(value: str, resource_type: str = "resource") -> str:
|
|
"""Validate a resource ID. Returns the value if valid, raises SystemExit on invalid."""
|
|
if not value:
|
|
_fail(
|
|
"EMPTY_ID",
|
|
f"Empty {resource_type} ID provided",
|
|
{resource_type: ""},
|
|
)
|
|
|
|
if UNSAFE_CHARS.search(value):
|
|
_fail(
|
|
"INVALID_ID",
|
|
f"Invalid {resource_type} ID: contains unsafe characters (?, #, %, control chars, path separators)",
|
|
{resource_type: value},
|
|
)
|
|
|
|
if ".." in value:
|
|
_fail(
|
|
"INVALID_ID",
|
|
f"Invalid {resource_type} ID: contains path traversal",
|
|
{resource_type: value},
|
|
)
|
|
|
|
return value
|
|
|
|
|
|
def _fail(code: str, message: str, details: dict) -> None:
|
|
"""Print structured error and exit."""
|
|
print_error(code, message, details)
|
|
raise SystemExit(1)
|