Skip to content

CLI review fixes: wiki-lint path traversal, launcher leak, search/agent-config parity#415

Merged
tobocop2 merged 10 commits into
feat/local-model-apifrom
fix/feat-cli-commands-review
Jun 22, 2026
Merged

CLI review fixes: wiki-lint path traversal, launcher leak, search/agent-config parity#415
tobocop2 merged 10 commits into
feat/local-model-apifrom
fix/feat-cli-commands-review

Conversation

@tobocop2

Copy link
Copy Markdown
Owner

Problem

Review of the CLI command layer found a security blocking bug plus several entry-point parity gaps:

  • lilbee wiki lint <wiki_source> joined the user-supplied source onto the wiki root with no containment check, so a traversal source (../../../../etc/passwd) read an arbitrary file and echoed its lines back as "unmarked claim" issues.
  • run_launcher ran prepare() and the warm wait outside the cleanup finally, leaking the spawned lilbee serve process when prepare raised (e.g. declining opencode setup).
  • CLI search skipped the cfg.max_distance relevance cutoff that REST and MCP both apply, returning lower-relevance chunks than the API for the same query.
  • model list --task validated differently from --source: it leaked the internal ModelTask enum name and, in --json mode, emitted Typer usage text instead of the JSON error envelope.
  • agent-config emitted a config omitting a remote-configured chat model that launch opencode and /v1/models both include.
  • The opencode MCP skill install wasn't atomic: a partial copy left a half-written dir that was then skipped forever.

Solution

  • Validate the resolved wiki path within the wiki root before reading (mirrors browse.find_page and the drafts path).
  • Wrap the post-spawn launcher work in the finally so the serve process is always stopped.
  • Apply the max_distance filter in CLI search; select the display score with explicit None checks so a real 0.0 survives.
  • Add _parse_task_or_bad_param mirroring the source parser (JSON envelope + friendly message).
  • Include a remote-configured chat model in agent-config.
  • Install the skill into a temp dir then os.replace, cleaning up staging on failure.

Tested: the traversal is rejected without disclosure, the launcher cleanup, the max_distance filter, the --task envelope, and the atomic skill install.

tobocop2 added 10 commits June 21, 2026 18:46
lint_wiki_page joined the user-supplied wiki_source onto wiki_root with no
containment check, so 'wiki lint ../../../../etc/passwd' read an arbitrary file
and echoed its lines back as unmarked-claim issues. Validate the resolved path
within wiki_root before reading, mirroring browse.find_page and the drafts path.
…, agent-config remote model

- run_launcher wraps prepare()/warm under the spawned-server finally so a raise
  (e.g. declining opencode setup) no longer leaks the lilbee serve process.
- CLI search applies the cfg.max_distance relevance cutoff that REST and MCP use,
  and renders a legitimate 0.0 score instead of dropping it via a truthy or-chain.
- model list --task gets the same JSON error envelope + friendly message as
  --source, no longer leaking the internal ModelTask enum name.
- agent-config includes a remote-configured chat model (matching launch and
  /v1/models) instead of only native registry refs.
A partial copy left a half-written skill dir that exists() then skipped forever,
so opencode ran with an empty skill and no recovery. Build in a temp dir and
os.replace into place, cleaning up staging on failure.
… import

- memory remove exits non-zero on not-found, matching model remove / remove.
- wiki status uses theme.SUCCESS/theme.ERROR instead of literal green/red.
- model.py imports sys at module top instead of lazily.
…robe dedup + log handle

- search/ask reject empty/whitespace queries via a shared helper (matching REST);
  search caps --top-k at 100 like the REST route.
- json-mode add suppresses eager worker start like the interactive path.
- spawn_server closes its log file handle after Popen dups the fd; the three
  /api/health probes share one _probe_health helper and a _HEALTH_PATH constant.
…nup, warm budget, opencode pins

- SyncStatus.pending mutated via an atomic adjust_pending under a lock (was a
  non-atomic cross-thread counter despite the thread-safe docstring).
- auto_sync reuses _format_sync_summary instead of rebuilding the summary string.
- self-check cleans up its downloaded GGUF and per-leg work dirs (temp leak);
  download dir is also removed on failure. Extracted a shared _self_check_leg.
- render_warm reports not-ready (not None) after a mid-stream drop so the caller
  doesn't double-spend the warm budget.
- agent-config opencode pins default_ref + chat_ctx like launch opencode.
@tobocop2 tobocop2 merged commit 9457f36 into feat/local-model-api Jun 22, 2026
8 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant