Skip to content

fix(approvals): tamper detection + multi-workflow tests + doc fixes (v0.3.2)#8

Merged
amittell merged 1 commit intomainfrom
fix/approval-tamper-check-and-multi-workflow-tests
Apr 22, 2026
Merged

fix(approvals): tamper detection + multi-workflow tests + doc fixes (v0.3.2)#8
amittell merged 1 commit intomainfrom
fix/approval-tamper-check-and-multi-workflow-tests

Conversation

@amittell
Copy link
Copy Markdown
Owner

Summary

Patch release bundling two real fixes and two doc clarifications surfaced during the 0.3.x audit. No schema or CLI surface changes.

Fix 1 — Approval tamper detection

verifyApprovalSignature previously rebuilt the canonical payload from the current grant and spread it into the attestation object, but the ssh provider only verifies signature against signed_payload — the rebuilt value was never used. Post-sign edits to approver, reason, expires_at, or task_hash in approvals.ndjson would go undetected (the ssh signature still matches the original signed payload).

Now the rebuilt payload is compared to signature.signed_payload. Any divergence returns verified: false with reason grant fields do not match signed payload (possible tampering). Flagged by the 0.3.0 implementation audit as a confidence-below-threshold observation; converting the dead code path into an actual defensive check.

Fix 2 — Multi-workflow disambiguation tests

grantApproval correctly requires --workflow on multi-workflow manifests and scopes grants per workflow, but no test exercised those paths. Added a test that:

  • Throws without --workflow on a multi-workflow manifest
  • Throws on an unknown workflow id
  • Grants distinct approvals for same-task-id in different workflows (different task hashes)
  • Confirms findValidApproval is correctly scoped per workflow

Doc 1 — contract.max_cost_usd

Clarified: enforced by runtimes that track cost-attributed operations (openclaw-scheduler for LLM tasks reporting token usage); declarative-only for shell-target agentcli exec (no cost signal to enforce against). Prevents users from expecting exec to cap shell-command spend.

Doc 2 — Sandbox on non-macOS

Added recommendation to docs/guide-identity.md that production-grade isolation on Linux / Windows should run agentcli exec inside a container until native OS sandbox adapters ship. Manifest declaration remains valid metadata; the OS-level boundary comes from the container namespace.

Test plan

  • npm run lint clean
  • npm test665/665 (was 663 + 2 new tests)
  • Tamper test: ssh-signed grant + mutations to approver/reason/expires_at each fail verification (skipped cleanly if no local ssh key)
  • Multi-workflow test: disambiguation + per-workflow hash scoping
  • CI lint-test passes

Files

  • src/approvals.js — tamper check in verifyApprovalSignature, explanatory comment
  • test/approvals.test.js — tamper test + multi-workflow test
  • docs/field-reference.mdmax_cost_usd clarification
  • docs/guide-identity.md — sandbox/container recommendation
  • CHANGELOG.md — new 0.3.2 section
  • package.json — 0.3.1 → 0.3.2

…v0.3.2)

verifyApprovalSignature previously built a canonical payload from the
current grant and spread it into the attestation object, but the ssh
provider only checks signature-against-stored-signed_payload and never
used the rebuilt value. Post-sign edits to approver, reason, expires_at,
or task_hash in approvals.ndjson would go undetected.

Now the rebuilt payload is compared to signature.signed_payload and any
divergence returns verified: false with reason "grant fields do not
match signed payload (possible tampering)".

Tests:
- ssh-signed grant + mutations to approver/reason/expires_at each fail
  verification (skipped cleanly if no local ssh key available)
- multi-workflow manifest: throws without --workflow, throws on unknown
  workflow id, scopes grants per workflow with distinct task hashes

Docs:
- contract.max_cost_usd: clarified as runtime-enforced (scheduler for
  cost-attributed tasks), declarative-only for shell exec
- sandbox/network on non-macOS: recommend containerized execution as
  the production-grade isolation path until native Linux/Windows
  sandbox adapters ship

665/665 tests pass. No schema changes, no CLI surface changes, no
behavioral change for unsigned grants.
@amittell amittell merged commit ef90065 into main Apr 22, 2026
1 check passed
@amittell amittell deleted the fix/approval-tamper-check-and-multi-workflow-tests branch April 22, 2026 01:20
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