Skip to content

v2.4.3 — untrusted-input hardening + upstream provider/pricing ports#4

Merged
soumyadebroy3 merged 11 commits into
mainfrom
dev
May 30, 2026
Merged

v2.4.3 — untrusted-input hardening + upstream provider/pricing ports#4
soumyadebroy3 merged 11 commits into
mainfrom
dev

Conversation

@soumyadebroy3

Copy link
Copy Markdown
Owner

Releases v2.4.3. All verified locally: tsc --noEmit clean, 782 tests pass (from a 731 baseline).

Hardening (full-codebase scan)

A single malformed/hostile session file can no longer abort analysis for every provider:

  • parser.ts isolates each session source; optimize.ts isolates per-file.
  • Provider parsers (Copilot/Kiro/Qwen/Gemini/OpenClaw) guard unchecked fields, non-array chat/parts/messages/content, __proto__ tool names, and non-numeric token counts.
  • day-aggregator invalid-timestamp buckets, export-html unbounded calendar loop, plugins.ts allowlist traversal/symlink, fs-utils mid-stream-read signalling, menubar-installer EXDEV, and mcp-sonar workdir containment + token-out-of-argv all fixed.
  • New regression tests: provider hostile-input, export-html XSS defense, plus day-aggregator / menubar / fs-utils / codex.

Upstream ports (beyond the fork's ~#355 baseline)

  • Providers: Warp + Forge (#350/#401) + Warp pricing aliases (#378).
  • OpenCode zero-usage recovery on newer schemas (#394).
  • Copilot MCP tool-name normalization (#374).
  • Codex forked-session dedup — stops cost inflation (#372); message truncation + size-guarded Gemini reads (#362, CLI parts).
  • DeepSeek v4 pricing + snapshot-fallback merge (#367).
  • Gemini 3.5 Flash alias/display sync (#377/#379/#382 — additive slivers only).

Housekeeping

  • npm dependency floors moved to latest stable (commander 15 verified, ink 7.0.4, vitest/coverage 4.1.7, vite 8.0.14); all manifests already used dynamic caret ranges.
  • Version bumped to 2.4.3 (root + windows); CHANGELOG updated.

Deliberately not included

The entangled upstream remainder (#398 Cowork grouping, #373 tooling-breakdown UI, #379 typed-ToolCall refactor, #382 statusline module, #377 Antigravity-2 provider rework) depends on session-cache.ts + the #375 worktree logic this fork omits, a cross-cutting type refactor, or the diverged macOS Swift app / Antigravity runtime — none cleanly portable here.

…d desktop tooling

A graph-informed full-codebase scan surfaced a class of untrusted-input
crashes plus several correctness/security gaps. All fixes verified:
tsc --noEmit clean, 742 tests pass (11 new).

Critical
- gnome/indicator.js: resolve unrendered Git merge-conflict markers that
  broke the whole extension (syntax error); keep the union of providers.

High
- parser.ts: wrap each session source in try/catch so one malformed or
  hostile file can't abort analysis for every provider (root cause).
- optimize.ts: guard content[] element deref + per-file isolation.
- providers copilot/kiro/qwen/gemini: guard unchecked event.data and
  non-array chat|parts|messages|content against schema-drifted input.
- mcp-sonar: confine sonar_scan workdir to SONAR_SCAN_ROOT (no arbitrary
  host-path mounts into the root container); pass SONAR_TOKEN via spawn
  env instead of argv.

Medium
- Token coercion against corruption (parser, optimize, openclaw; menubar-json
  finite-clamp so the desktop JSON contract never serializes null).
- __proto__ tool-name guards: kimi/qwen/pi/mistral-vibe/kiro/openclaw.
- day-aggregator: invalid timestamps no longer create NaN day buckets.
- plugins: resolve()+realpathSync() so the $HOME allowlist resists ".."
  traversal and home-rooted symlinks.
- export-html: cap the calendar-fill loop (no hang on out-of-range dates).
- codex: treat a cumulative-counter reset as a fresh window instead of
  emitting negative token totals.
- fs-utils: re-throw on mid-stream read failure so a truncated read is not
  cached as complete; parser/droid isolate the bad file.
- menubar-installer: back-up -> swap -> remove with an EXDEV copy fallback
  so a failed reinstall can't leave the user with no app.

Tests
- New: export-html XSS defense; provider hostile-input resilience.
- Updated: codex reset; fs-utils re-throw; day-aggregator NaN; menubar
  finite-clamp.
Add MCP server configs and integration for the code-review-graph tool across Gemini, Qoder, and Kiro clients. Includes mcp.json files pointing to the local pipx venv, Gemini and Qoder settings with SessionStart/PostTool hooks, two low-noise hook scripts (crg-session-start.sh, crg-update.sh), and .bak copies. Adds knowledge-graph guidance and skill manifests (.github instruction, QODER.md, and multiple .gemini/skills/* SKILL.md) to encourage using graph tools for exploration, review, refactoring, and debugging. Also adds an empty graph.db placeholder.
…401, #378)

Adds two AI-coding-tool session providers the fork was missing, both
lazy-loaded (open SQLite on disk):
- Warp (upstream #350): reads warp.sqlite under Group Containers, parses
  exchanges/blocks, attributes tokens by primary-agent category.
- Forge (upstream #401): reads forge's SQLite session store.
- Warp Claude-variant pricing aliases (upstream #378): map the suffixed
  model ids Warp emits (claude-4-6-sonnet-high, claude-4-7-opus-xhigh, ...)
  to canonical LiteLLM pricing ids so cost is non-zero.

Registered in the LAZY_PROVIDERS array (one line each). Imports resolve to
existing fork helpers (bash-utils, models, sqlite, types) — no new deps.
Upstream provider + test files ported verbatim. tsc clean, 756 tests pass.

(cherry picked from commit e9f10e1f50a6550161ec970e026d5a48ef5545f5)
… #394)

OpenCode sessions were yielding zero usage when the DB schema changed.
Ports upstream PR #394:
- accept role "model" as equivalent to "assistant"
- fall back to `usage.{input,output,cache_*}_tokens` when `tokens.*` absent
- recognize tool-call / tool_call part types and treat reasoning/file/
  tool-result parts as activity
- session-level token fallback (tryQuerySessionTokens) when per-message
  parsing yields nothing, with a CODEBURN_VERBOSE diagnostic
+ 4 ported tests. tsc clean, full suite green.

(cherry picked from commit 93eb84576f9f5acd7c4b07ddf93ac677ddc26423)
… #374)

Copilot records MCP tools as `<server>-<tool>`; they were counted as core
tools instead of MCP. Adds normalizeToolName/normalizeCopilotMcpTool (matching
the OpenCode MCP normalization already in the fork) and routes the legacy,
transcript, and toolDisplayName paths through it. (Upstream's session-cache
invalidation half is N/A — the fork has no session-cache.ts.)

(cherry picked from commit 9b4d721094d4623bb24cae77a9df68a9c8b1f563)
… (upstream #372)

A forked Codex session replays the parent's entire event history with
timestamps clustered at fork-creation time, double-counting tokens/cost.
Ports the codex portion of upstream PR #372:
- read `forked_from_id` from session_meta; compute a 5s fork cutoff
- skip token_count events replayed within that cutoff
- key dedup by `forkedFromId || sessionId` (dropping the timestamp) so a
  fork dedups against its parent
Adapted to the fork's CodexParserState structure. + 1 regression test.
(Upstream's parser.ts hunks target the session-cache the fork lacks; the
antigravity bits are handled under the #377 port.)

(cherry picked from commit 3fc9fda483eed519730d0b5a9adf7830c1008dfd)
…eam #362)

Ports the CLI-applicable robustness fixes from upstream PR #362:
- codex: truncate the captured user message to 500 chars (parity with
  other providers; bounds memory on huge prompts).
- gemini: read sessions via readSessionFile (shared size cap + UTF-8
  hardening) instead of raw readFile, closing the oversize-file bypass.
(The PR's Swift hunks — payload decode fragility, NaN bar widths, ForEach
collisions — and its per-provider main.ts rewrite target code the fork has
diverged from; not applicable.)

(cherry picked from commit 31d980d1a2c335219d17db11b4321340b50d6d21)
…m #367)

Ports upstream PR #367:
- mergeSnapshotFallbacks(): backfill any model the runtime LiteLLM cache is
  missing from the bundled snapshot, so models we ship pricing for never read
  as $0 when the cache is stale/incomplete; wired into both loadPricing paths.
- CODEBURN_CACHE_DIR override for the pricing cache dir.
- DeepSeek v4 Pro/Flash: manual bundler entries + snapshot entries + display
  names (models.ts SHORT_NAMES and claude.ts), priced from DeepSeek's official
  rates (LiteLLM PR #27056 unmerged).
+ 6 unit tests (pricing values, prefix resolution, cost math, stale-cache
  fallback). The PR's CLI integration test is omitted (couples to the exact
  --format json schema and spawns a 30s subprocess); the unit tests cover the
  same cost math directly.

(cherry picked from commit a4eb2c29b6c417d1cf58f778d3794e4cf541ff9c)
… #377/#379/#382)

Cleanly-isolatable, additive slivers only (the entangled Antigravity-2
provider rework, statusline hook, and subagent-breakdown UI are NOT ported):
- models.ts BUILTIN_ALIASES: gemini-3.5-flash {high,medium,low} and the
  "Gemini 3.5 Flash (High/Medium/Low)" label forms resolve to gemini-3.5-flash.
- models.ts SHORT_NAMES + gemini.ts + antigravity.ts modelDisplayNames:
  display these variants as "Gemini 3.5 Flash".
Display is correct immediately; cost resolves once LiteLLM indexes
gemini-3.5-flash (the bundled snapshot doesn't ship it yet, so no offline
cost assertion). + 4 resolution/display tests.
All manifests already use dynamic (caret) ranges; this lifts the floors that
were behind the latest published stable so a fresh install lands on current:
- root: commander ^14.0.3 -> ^15.0.0 (major; verified — tsc clean, full suite
  green, `cli.ts --help/--version` work), ink ^7.0.3 -> ^7.0.4,
  vitest + @vitest/coverage-v8 ^4.1.6 -> ^4.1.7
- windows: vite ^8.0.13 -> ^8.0.14
package-lock.json regenerated. Everything else (chalk, react, typescript,
tauri-*, @types/*, esbuild, tsup, tsx) was already on latest stable.
Cargo deps use default-caret semantics and are current; mac SPM has no
external package deps.
…ng ports

Bumps the package version to 2.4.3 (root + windows) and adds the CHANGELOG
entry. Covers the robustness hardening, Warp/Forge providers, OpenCode/
Copilot/Codex fixes, DeepSeek v4 pricing + snapshot fallback, Gemini 3.5
Flash sync, and the dependency-floor refresh.
@soumyadebroy3 soumyadebroy3 merged commit 6b07855 into main May 30, 2026
12 of 13 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