Commit Graph

3 Commits

Author SHA1 Message Date
ruv 4327ec9ffa fix(smoke): #2089 — accept E2BIG as valid rejection in github-safe injection smoke
The >256KB rejection case fails on Linux CI because Linux's
MAX_ARG_STRLEN (128 KiB per argv element on most kernels) trips
before the helper's own size cap fires. spawnSync returns
status=null with error.code='E2BIG' instead of status=1.

Local macOS development passes because Mach's per-arg limit is
~1 MiB so the helper's cap is what fires. The smoke now accepts
either path — the assertion is "rejected before gh is invoked,"
and E2BIG satisfies that even more strongly (the body cannot
reach exec at all).

Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com>
2026-05-21 14:23:31 -04:00
ruv 7d2fc001ec feat(security): #2089 ADR-127 Phase 2 — github-safe maxBuffer + agent frontmatter tools: + swarm-pr/issue injection fix
github-safe.js (both copies — dogfood + init-template)
  Adds GITHUB_SAFE_VERSION='1.0.0' constant for smoke assertions.
  Adds explicit 256KB body cap (MAX_BODY_BYTES): rejects oversized bodies
  with exit 1 before any temp-file write, matching the GitHub API body
  field limit documented in ADR-127.  Adds strict error handling: all
  execSync calls wrapped in try/catch, cleanup in finally.  Adds
  GITHUB_SAFE_DRY_RUN=1 env-var for smoke tests to skip gh exec.

github-setup.sh (both copies)
  Prepends set -euo pipefail.  Replaces bare `gh auth status &>/dev/null`
  with a check that parses "Logged in" and "repo" scope from the output.
  Adds security rationale comment explaining why each flag is needed.

Agent frontmatter WebFetch removal (dogfood copies only — init-template
commands don't have frontmatter; the relevant change there is the injection
fix below):
  release-manager.md  — removes WebFetch (keeps Write for CHANGELOG)
  release-swarm.md    — removes WebFetch (keeps Write for CHANGELOG)
  repo-architect.md   — removes WebFetch

All 13 agents already have explicit tools: lines; only the 3 above had
WebFetch.  No agent in scope now has WebFetch in its tools: list.

swarm-pr.md + swarm-issue.md (BOTH dogfood .claude/agents/github/ AND
init-template v3/@claude-flow/cli/.claude/commands/github/):
  Replaces unquoted ${{ github.event.comment.body }} interpolated into
  --comment "..." with mktemp + printf + grep + --comment-file pattern.
  Replaces unquoted ${{ github.event.label.name }} == "swarm-ready" with
  mktemp + printf + grep -qx pattern.  Closes prompt-injection path where
  a PR comment with shell metacharacters could execute attacker-controlled
  shell in a pull_request-triggered workflow.

smoke-github-safe-injection.mjs updated:
  Upgrades the >256KB test case from "note" (Phase 1 red) to "ok" (Phase 2
  green) now that the 256KB cap is enforced.

Acceptance checks:
  node scripts/smoke-github-safe-injection.mjs  → all 5 cases pass
  node scripts/smoke-github-actions-pins.mjs    → ok (no regressions)
  grep -r 'github.event.comment.body.*--comment' .claude/agents/ v3/@claude-flow/cli/.claude/
  → exit 1 (no matches)

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-21 14:06:59 -04:00
ruv 90df1d6e8a feat(ci): #2089 ADR-127 Phase 1 — github-safe injection smoke + uses: pin smoke + supply-chain allowed-deps actions block
Creates two new CI smoke scripts and wires them into v3-ci.yml.

smoke-github-safe-injection.mjs
  Generalizes the smoke-pre-bash-hook.mjs pattern (#2017) to the GitHub
  helper surface.  Drives adversarial PR/issue bodies (backticks, $(),
  semicolons, empty) through github-safe.js via a fake-gh shim and
  asserts the body lands verbatim in a temp file with --body-file, not
  inline as --body.  The >256KB cap case is documented as a red→green
  transition for Phase 2 (no cap yet enforced).  Runs against both
  .claude/helpers/github-safe.js (dogfood) and the init-template copy.

smoke-github-actions-pins.mjs
  Static scan of .claude/agents/github/*.md, .claude/skills/github-*/
  SKILL.md, and v3/@claude-flow/cli/.claude/commands/github/*.md.  Every
  uses: ref must be SHA-pinned (40-hex) OR present in the new
  .github/supply-chain/allowed-deps.json "actions" block.  Exits 0 now
  that allowed-deps.json covers the full set of refs in-use.  Phase 3
  upgrades @v3→@v4 across all files; this smoke is the regression gate
  that prevents them drifting back.

.github/supply-chain/allowed-deps.json
  Adds "actions" key with allowed[], minimumVersion, and an explanatory
  comment per ADR-127 §Phase 1.  Lists all GitHub Actions currently
  referenced in scope: checkout, setup-node, pnpm/action-setup, cache,
  upload-artifact, ruvnet/swarm-action, aws-actions/configure-aws-credentials.

.github/workflows/v3-ci.yml
  Adds path-filter entries under both push and pull_request triggers
  covering the 6 ADR-127-specified paths:
    .claude/agents/github/**
    .claude/skills/github-*/**
    v3/@claude-flow/cli/.claude/commands/github/**
    .claude/helpers/github-safe.js
    v3/@claude-flow/cli/.claude/helpers/github-safe.js
    scripts/smoke-github-*.mjs
    .github/supply-chain/allowed-deps.json
  Adds two independent smoke jobs: github-safe-injection-smoke and
  github-actions-pins-smoke, following the ruvllm-wasm-auto-init-smoke
  pattern.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-21 14:03:29 -04:00