T01 · Skill Instruction Hijacking
- Location
scripts/manage_weather_subscription.py:287- Finding
Persistent Agent Prompt Injection Through Unsanitized City Input
- Content
View full analysis
str: day_phrase = DAY_MODE_LABEL.get(mode, "天气") if mode == "tomorrow": fetch_hint = "查询明天的天气" report_days = 1 elif mode == "7day": fetch_hint = f"输出未来{days}天的天气" report_days = days else: fetch_hint = "查询当天天气" report_days = 1 normalized_to = normalize_target(to) return ( f"请运行 global-weather-service 技能中的 weather_report.py,为用户 {normalized_to} 查询 {city} 的{day_phrase},并直接投递最终天气内容。" "数据源必须使用 Open-Meteo。" f"请在触发时重新查询最新数据,{fetch_hint}。" f"请使用命令 `python scripts\\weather_report.py \"{city}\" --days {report_days}` 生成天气简报。" "如果 mode 是 tomorrow,请在输出文案中明确这是明日天气,但仍只输出一份单日简报。" "输出格式必须为中文天气简报,包含标题、日期、天气、温度、生活指数、穿衣建议、紫外线和其他建议。" "不要解释过程,不要输出系统说明。" ) ``` The resulting message is persisted as an OpenClaw cron instruction: ```python message = build_agent_message(to, city, mode, days) cmd = [ openclaw_cmd, "cron", "add", "--name", name, "--session", "isolated", "--message", message, "--channel", "qqbot", "--to", normalize_target(to), "--announce", "--json", ] ``` ### Technical Analysis The user-controlled `city` value is interpolated verbatim into natural-language Agent instructions and into a quoted command displayed inside those instructions. The application does not constrain its length or character set and does not reject newlines, backticks, quotation marks, or instruction-like content. Although `subprocess.run()` receives a list of arguments and therefore does not directly introduce shell command injection at cron creation time, this does not protect the downstream Agent ...[truncated 1701 chars]- Remediation
View remediation
