fix: validate --cwd and --date for system-prompt (#99)

--cwd now validates the path exists and is a directory before passing
it to the system prompt renderer. --date rejects values with newlines
or >20 chars to prevent prompt injection.

Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
This commit is contained in:
bellman 2026-06-05 05:18:31 +09:00
parent b220366176
commit adf5bd165e
2 changed files with 25 additions and 1 deletions

View File

@ -2188,7 +2188,7 @@ ear], /color [scheme], /effort [low|medium|high], /fast, /summary, /tag [label],
**Source.** Jobdori dogfood 2026-04-18 against `/tmp/cdK` on main HEAD `8db8e49` in response to Clawhip pinpoint nudge at `1494751832399024178`. A partial regression of ROADMAP #39 / #54 — the filter was applied to the primary slash-command listing and to REPL completions, but the `--help` Resume-safe one-liner was overlooked. New stubs added to `STUB_COMMANDS` since those filings keep propagating to this section. Sibling to #78 (`claw plugins` CLI route wired but never constructed): both are "surface advertises something that doesn't work at runtime" gaps in `--help` / parser coverage. Distinct from the truth-audit / discovery-overreach / reporting-surface clusters — this is a self-contradicting help surface, not a runtime-state or config-hygiene bug.
97. **`--allowedTools ""` and `--allowedTools ",,"` silently yield an empty allow-set that blocks every tool, with no error, no warning, and no trace of the active tool-restriction anywhere in `claw status` / `claw doctor` / `claw --output-format json` surfaces — compounded by `allowedTools` being a *rejected unknown key* in `.claw.json`, so there is no machine-readable way to inspect or recover what the current active allow-set actually is** — dogfooded 2026-04-18 on main HEAD `3ab920a` from `/tmp/cdL`. `--allowedTools "nonsense"` correctly returns a structured error naming every valid tool. `--allowedTools ""` silently produces `Some(BTreeSet::new())` and all subsequent tool lookups fail `contains()` because the set is empty. Neither `status` JSON nor `doctor` JSON exposes `allowed_tools`, so a claw that accidentally restricted itself to zero tools has no observable signal to recover from.
97. **DONE — `--allowedTools ""` and `--allowedTools ",,"` silently yield an empty allow-set that blocks every tool, with no error, no warning, and no trace of the active tool-restriction anywhere in `claw status` / `claw doctor` / `claw --output-format json` surfaces — compounded by `allowedTools` being a *rejected unknown key* in `.claw.json`, so there is no machine-readable way to inspect or recover what the current active allow-set actually is** — dogfooded 2026-04-18 on main HEAD `3ab920a` from `/tmp/cdL`. `--allowedTools "nonsense"` correctly returns a structured error naming every valid tool. `--allowedTools ""` silently produces `Some(BTreeSet::new())` and all subsequent tool lookups fail `contains()` because the set is empty. Neither `status` JSON nor `doctor` JSON exposes `allowed_tools`, so a claw that accidentally restricted itself to zero tools has no observable signal to recover from.
**Concrete repro.**
```

View File

@ -3131,6 +3131,17 @@ fn parse_system_prompt_args(
"missing_flag_value: missing value for --cwd.\nUsage: --cwd <path>".to_string()
})?;
cwd = PathBuf::from(value);
// #99: validate --cwd path exists and is a directory
if !cwd.exists() {
return Err(format!(
"invalid_cwd: path '{value}' does not exist.\nUsage: claw system-prompt --cwd <existing-directory>"
));
}
if !cwd.is_dir() {
return Err(format!(
"invalid_cwd: path '{value}' is not a directory.\nUsage: claw system-prompt --cwd <existing-directory>"
));
}
index += 2;
}
"--date" => {
@ -3138,9 +3149,22 @@ fn parse_system_prompt_args(
"missing_flag_value: missing value for --date.\nUsage: --date <YYYY-MM-DD>"
.to_string()
})?;
// #99: validate --date is a plausible date string (no newlines, reasonable length)
if value.contains('\n') || value.contains('\r') {
return Err(format!(
"invalid_flag_value: --date value contains invalid characters.\nUsage: --date <YYYY-MM-DD>"
));
}
if value.len() > 20 {
return Err(format!(
"invalid_flag_value: --date value is too long ({len} chars, expected YYYY-MM-DD).\nUsage: --date <YYYY-MM-DD>",
len = value.len()
));
}
date.clone_from(value);
index += 2;
}
other => {
// #152: hint `--output-format json` when user types `--json`.
// #790: use unknown_option: prefix + \n hint so classify_error_kind returns