Skip to content

aegis: drop the duplicated binary name from cli.args (6 of 7 methods are dead)#90

Merged
Alexgodoroja merged 1 commit into
mainfrom
fix/aegis-cli-argv
Jul 16, 2026
Merged

aegis: drop the duplicated binary name from cli.args (6 of 7 methods are dead)#90
Alexgodoroja merged 1 commit into
mainfrom
fix/aegis-cli-argv

Conversation

@Alexgodoroja

Copy link
Copy Markdown
Collaborator

The bug

6 of the 7 methods on the published io.pilot.aegis v0.1.3 do nothing.

backend.command is ["aegis"] and every method's cli.args repeats "aegis" as argv[0], so the adapter runs aegis aegis scan <path> → unknown subcommand → usage banner. Only aegis.exec (a verbatim argv passthrough) and the scaffold's auto-added help work.

It is invisible from the outside because the call exits 0: the CLI adapter wraps the tool's non-zero exit into a successful IPC reply with the banner in the body.

$ pilotctl appstore call io.pilot.aegis aegis.scan '{"path":"/etc/hosts"}'
{ "exit": 1, "stderr": "...aegis 0.1.3 — Agent Guard and Intercept System\nUsage:..." }   # nothing scanned

Root cause

The generated adapter builds argv as base[0] + base[1:] + cli.args (client_cli.go.tmpl), and main.go.tmpl rewrites base[0] to the staged binary path. With a single-element backend.command, base[1:] is empty — so every element of cli.args lands after argv[0]. The leading "aegis" was pure duplication, never required.

aegis is the only one of ten CLI submissions that does this. tldr, duckdb, postgres, redis, mysql, sqlite, docker, otto and miren all omit the binary name — the convention is unambiguous.

The fix

Six deletions. Nothing outside .methods changes.

Verification

Against the staged binary:

before: aegis aegis scan /etc/hosts  -> exit 1, usage banner
after:  aegis scan /etc/hosts        -> exit 0, [AEGIS] scan complete: 0/1 flagged

And end-to-end through a rebuilt bundle on a stock pilot-daemon + pilotctl (isolated root, real prod trust anchor, sha256 OK): all six dead methods work, and it genuinely scans rather than merely exiting 0 — a planted prompt-injection file returns QUARANTINE … combined=1.00 [Patterns=1.00], 1/1 flagged.

go test ./internal/... green.

Version: same-version 0.1.3, deliberately

app_version tracks the upstream tool version and the wrapped binary is unchanged — this is a wrapper-only fix. Artifact URLs derive from app_version, so bumping to 0.1.4 would repoint three sha-pinned R2 URLs at objects that don't exist. UPDATING.md explicitly allows an owner's idempotent same-version re-publish. The publisher key is confirmed to be the original (ed25519:+nt58BA0gpPYuyaeG2GwfTI79j8IHP+zra5GvRQv0N0=, matching both the live catalogue pin and the local catalogue-pins), so the update gate will accept it.

Go-live requires a catalogue PR (not yet opened)

Merging this alone does not reach users — the bundle must be rebuilt, uploaded, and the catalogue's bundle_url/bundle_sha256 flipped.

⚠️ The republish must NOT overwrite the prod bundle path. The live catalogue pins ae40da40…; a rebuilt bundle is different bytes, so overwriting bundles/io.pilot.aegis/0.1.3/ would break sha verification for every aegis install in the window between upload and catalogue merge. Upload to a new path and let the catalogue PR flip URL+sha atomically. (The native artifacts under io.pilot.aegis/0.1.3/ are genuinely unchanged and are correctly reused.)

Follow-ups (deliberately not here)

  • Once this ships, aegis's next_steps graph (app-template#89) should be re-pointed: it currently routes via aegis.exec because that is the only thing that works today. Specifically the "Agent Guard and Intercept System" edge should be deleted (post-fix that banner is only the intended output of aegis.exec {"args":["--help"]}, so the edge would fire on a correct call), the missing required param recovery should point at aegis.scan, and the scan complete: 0/ edge should widen from to *.
  • Pre-existing wart on main: the manifest's exposes lists aegis.help twice — the submission declares it while the scaffold auto-adds it (the playbook says don't declare <ns>.help). Benign (auto-help wins).

6 of 7 methods are dead in the published app. backend.command is ["aegis"] and
every method's cli.args repeated "aegis" as argv[0], so the adapter ran
`aegis aegis scan <path>` -> unknown subcommand -> usage banner, exit 1. Only
aegis.exec (a verbatim argv passthrough) and the scaffold's auto-added help
worked.

The adapter builds argv as base[0] + base[1:] + cli.args, and with a
single-element command base[1:] is empty, so every cli.args element lands after
argv[0]. The leading "aegis" was pure duplication. aegis is the only one of ten
CLI submissions that does this; tldr, duckdb, postgres, redis, mysql, sqlite,
docker, otto and miren all omit it.

Verified against the staged binary:
  before: `aegis aegis scan /etc/hosts` -> exit 1, usage banner
  after:  `aegis scan /etc/hosts`       -> exit 0, [AEGIS] scan complete: 0/1 flagged

and end-to-end through a rebuilt bundle on a stock daemon: all six methods work,
and a planted injection file returns QUARANTINE combined=1.00 -- it genuinely
scans rather than merely exiting 0.

Same-version 0.1.3: the wrapped binary is unchanged and artifact URLs derive
from app_version, so a bump would repoint sha-pinned URLs at objects that do
not exist. UPDATING.md allows an owner's idempotent same-version re-publish.
@Alexgodoroja

Copy link
Copy Markdown
Collaborator Author

Go-live half is open: pilot-protocol/pilotprotocol#397 — rebuilt + re-signed bundles for the fix in this PR.

Built from this PR's tree at 3364651, signed with the app's original publisher key ed25519:+nt58BA0gpPYuyae… (matches the catalogue's publisher pin, so the ownership gate passes). Bundles went to a new R2 prefix 0.1.3/rev2/ rather than over 0.1.3/, so existing installs keep verifying against the currently-pinned sha until the cutover flips url+sha atomically.

Rehearsed the real client path end-to-end against prod R2 before opening: sha256 OK, then aegis.scan returns [AEGIS] scan complete: 0/1 flagged (exit 0) instead of the usage banner, and flags a planted injection with QUARANTINE … 1/1 flagged.

Suggested merge order: this PR first (submission of record), then #397.

@Alexgodoroja
Alexgodoroja merged commit e0b4b09 into main Jul 16, 2026
7 checks passed
Alexgodoroja pushed a commit that referenced this pull request Jul 16, 2026
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