Follow-up to #3773: that cleared the n+m addition alert, but CodeQL still
flagged the 2*maxD allocation (go/allocation-size-overflow) because it
doesn't propagate maxD's bound through the guarded sum. Clamp each line
count to maxDiffEdits before summing, so the sum and the 2*maxD allocation
both have constant-bounded operands. maxD stays min(n+m, maxDiffEdits).
Co-authored-by: reasonix <[email protected]>
CodeQL go/allocation-size-overflow (high) flagged `n + m` flowing into
`make([]int, 2*maxD+1)`: a pathological line count could overflow the
addition before the downstream clamp. The result was already safe (the
clamp caught a wrapped-negative maxD), but the addition itself still
tripped the query. Restructure to maxD = min(n+m, maxDiffEdits) with the
sum taken only when n and m are within the cap — no overflow at the
operation, identical bound.
Co-authored-by: reasonix <[email protected]>
* @
fix(codegraph): resolve symlinks when extracting third-party bundle
The lexical tar/zip-slip guard missed the symlink-redirect escape: an
in-bounds symlink extracted as a parent component lets a later entry be
written through it to land outside the cache dir. Resolve the real parent
with EvalSymlinks before validating, and judge a symlink target from its
resolved location. Closes the go/unsafe-unzip-symlink + go/zipslip alerts.
@
* @
fix(scripts): run gh without a shell in backfill-issue-labels
execSync built a shell command string from interpolated values; switch to
execFileSync with an argv array so label and issue arguments can never be
parsed as shell. Closes the js/command-line-injection alert.
@
* @
ci(e2e-bot): gate untrusted PR-head run behind an environment
Running PR-head code with the provider secret was guarded only by the
author_association check. Add an `e2e-bot` deployment environment (configure
required reviewers to force per-run approval) and pin the checkout to the
head commit resolved at trigger time, detached, so a mid-run force-push
cannot swap in different code. Addresses actions/untrusted-checkout-toctou.
@
* @
fix: bound integer conversions flagged by code scanning
parseHexColor parses single bytes; parse them as 8-bit unsigned and return
int so the per-channel value is provably in range, dropping the
int64->int conversions at the call sites. Clamp the Myers maxD against a
negative n+m overflow too, so make() can never see a wrapped size.
@
---------
Co-authored-by: reasonix <[email protected]>
The Myers trace stores O(D) snapshots of an O(D)-wide vector, so the edit
distance D drives O(D²) ≈ O(N²) time and memory: a full rewrite of a 3000-line
file allocated ~565 MB, ~6 GB at 10k lines — enough to OOM the synchronous
write-preview/checkpoint diff. Cap D at 2000 edits: small changes converge well
below it (so a tiny edit in a huge file still gets a real diff), while a near-
total rewrite falls back to cheap order-insensitive tallies and an omitted-diff
marker instead of a gigabyte allocation. A 6000-line rewrite now costs 63 MB.
Four reusable harness capabilities a desktop front-end needs, all additive and
independent of the agent loop / TUI (agent.go, chat_tui.go, cli.go untouched):
- diff: Myers line-diff engine (internal/diff) + a tool.Previewer optional
capability. write_file/edit_file/multi_edit can now compute the change a call
WOULD make (unified diff, +N/-M, create/modify) without touching disk, for
approval cards and changed-files panels. A consistency test asserts the
preview matches what Execute persists, so the two can't drift.
- inspect: read-only projection of providers (with key readiness), tools
(builtin vs mcp, read-only, previewable, schema), MCP servers/prompts/
resources, and slash commands into JSON-ready structs for a settings UI.
- config: programmatic, validated mutation surface (SetDefaultModel,
Upsert/RemoveProvider, SetPlannerModel, permission-rule edits, Upsert/
RemovePlugin) plus an atomic SaveTo, separate from the init wizard.
- builtin.Workspace: binds the built-in tools to a working directory so
concurrent agents (e.g. desktop tabs on different projects) get independent
path roots. A zero workDir is byte-identical to today's process-cwd behavior.