Skip to content

fix(security): close approval-gate spoofing + path traversal (#54) — v1.7.1#55

Merged
richard-devbot merged 1 commit into
mainfrom
fix/approval-security-54
Jun 2, 2026
Merged

fix(security): close approval-gate spoofing + path traversal (#54) — v1.7.1#55
richard-devbot merged 1 commit into
mainfrom
fix/approval-security-54

Conversation

@richard-devbot
Copy link
Copy Markdown
Owner

Closes #54. Blocks publish until merged — both findings are pre-release HIGH.

HIGH 1 — manager identity spoofing (fixed)

The dashboard accepted resolvedBy from the request body unauthenticated.

  • Approvals now require a signed RSTACK_APPROVAL_TOKEN header + same-origin request
  • Enforce Content-Type: application/json, cap body at 64KB, require an explicit approver
  • Record audit-proof actor evidence (token-verified, via, ts) — not just a name string
  • Secure default: with no token set, browser approvals are disabled; sdlc_approve still enforces the policy.json / RSTACK_MANAGER_USERS allow-list
  • Client prompts once for the token and stores it locally

HIGH 2 — approval-id path traversal (fixed)

A crafted gate id (gate:<runId>:<task>:<artifact>) could encode a runId with .. and drive an approvals.json write outside .rstack/runs.

  • isSafeRunId + artifact validation reject traversal in parseApprovalQueueId
  • safeRunApprovalsPath resolves the path and asserts containment under .rstack/runs/<run>, and requires a real manifest.json, before any write

Verification

  • 106/106 tests (5 new security regressions: traversal id, escaping runId write, ghost run, manager allow-list)
  • 7 live transport-auth checks: no-token→403, bad content-type→415, missing/invalid token→401, cross-origin→403, missing approver→400, valid→reaches resolver
  • lint clean

🤖 Generated with Claude Code

HIGH findings from the pre-release audit on the approval-gate work:

1. Manager identity spoofing — dashboard accepted any resolvedBy from the
   request body. Now: approvals require a signed RSTACK_APPROVAL_TOKEN +
   same-origin request, enforce application/json, cap body size, demand an
   explicit approver, and record audit-proof actor evidence. No token set =
   browser approvals disabled (secure default); sdlc_approve still enforces
   the manager allow-list.

2. Approval-id path traversal — a crafted gate id could encode a runId with
   .. and drive a write outside .rstack/runs. Now: isSafeRunId + artifact
   validation in parseApprovalQueueId, and safeRunApprovalsPath asserts the
   resolved path stays under .rstack/runs/<run> with a real manifest before
   any write.

5 security regression tests + 7 live transport-auth checks verify both.

Closes #54

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@richard-devbot richard-devbot merged commit f710e9f into main Jun 2, 2026
6 checks passed
@richard-devbot richard-devbot deleted the fix/approval-security-54 branch June 2, 2026 14:13
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.

Business Hub approval gates: fix manager identity spoofing and path traversal before release

2 participants