Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions .claude/skills/gh-aw-guide/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: >-

# gh-aw (GitHub Agentic Workflows) Guide

This skill provides the complete reference for building, securing, and maintaining GitHub Agentic Workflows in this repository. It covers the gh-aw platform's architecture, security model, and all available features.
This skill provides a complete reference for building, securing, and maintaining GitHub Agentic Workflows. It covers the gh-aw platform's architecture, security model, and all available features.

## Quick Start

Expand Down Expand Up @@ -85,7 +85,7 @@ gh aw upgrade # Upgrade gh-aw CLI extension

**Note:** gh-aw is actively developed. If a capability feels like something a framework would provide natively, check the reference docs — it probably exists even if it's not in this table yet.

For full architecture, security, fork handling, safe outputs, and troubleshooting details, read `references/architecture.md` in this skill directory.
For full architecture, security, fork handling, safe outputs, and troubleshooting details, see the [official gh-aw docs](https://gh.io/gh-aw).

## Common Patterns

Expand Down Expand Up @@ -196,15 +196,26 @@ Manual triggers (`workflow_dispatch`, `issue_comment`) should bypass the gate. N

### Fork PR Checkout (workflow_dispatch)

For `workflow_dispatch` workflows that need to evaluate a PR branch: use the shared `Checkout-GhAwPr.ps1` script. It (1) verifies the PR author has write access and rejects fork PRs, (2) checks out the PR branch, and (3) restores `.github/skills/`, `.github/instructions/`, and `.github/copilot-instructions.md` from the base branch SHA — defense-in-depth even though the platform also does this restore automatically.
For `workflow_dispatch` workflows that need to evaluate a PR branch, implement a checkout step that: (1) verifies the PR author has write access and rejects fork PRs, (2) checks out the PR branch, and (3) restores `.github/` and agent infrastructure from the base branch SHA — defense-in-depth even though the platform also does this restore automatically.

```yaml
steps:
- name: Checkout PR and restore agent infrastructure
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ inputs.pr_number }}
run: pwsh .github/scripts/Checkout-GhAwPr.ps1
run: |
# Verify PR author has write access, reject forks
AUTHOR=$(gh pr view "$PR_NUMBER" --json author --jq '.author.login')
PERM=$(gh api "repos/$GITHUB_REPOSITORY/collaborators/$AUTHOR/permission" --jq '.permission')
if [[ "$PERM" != "admin" && "$PERM" != "write" && "$PERM" != "maintain" ]]; then
echo "::error::PR author $AUTHOR has $PERM access — requires write+"
exit 1
fi
Comment on lines +208 to +214
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MODERATE — Comment claims "reject forks" but no fork check exists

The comment on line 208 says # Verify PR author has write access, reject forks, and the prose description lists "rejects fork PRs" as goal (1). However, the code only checks collaborator permission level — there is no isCrossRepository check. A maintainer with write access who opens a PR from their personal fork passes the permission guard despite the stated intent to reject forks.

Since this is a documentation template that practitioners will copy, the misleading comment is concerning — consumers will believe the fork case is handled when it isn't.

Suggested fix — add an explicit fork guard:

IS_FORK=$(gh pr view "$PR_NUMBER" --json isCrossRepository --jq '.isCrossRepository')
if [[ "$IS_FORK" == "true" ]]; then
  echo "::error::Fork PRs are not supported for workflow_dispatch"
  exit 1
fi

Flagged by: 3/3 reviewers (after consensus)

gh pr checkout "$PR_NUMBER"
# Restore trusted .github/ from base branch
BASE_SHA=$(gh pr view "$PR_NUMBER" --json baseRefOid --jq '.baseRefOid')
git checkout "$BASE_SHA" -- .github/ .agents/ 2>/dev/null || true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MODERATE — blanket || true silently swallows .github/ restore failures

The whole point of this defense-in-depth step is to restore trusted .github/ from the base branch. Combining both paths in one git checkout with 2>/dev/null || true means that if .github/ fails to restore (bad SHA, transient git error, path missing), the step silently succeeds and the agent proceeds with potentially tampered agent infrastructure.

Failing scenario: A transient error or corrupted local clone causes git checkout "$BASE_SHA" -- .github/ .agents/ to fail. The || true swallows the exit code, and the workflow continues with the PR branch's .github/ intact — exactly the attack vector this step is designed to prevent.

Suggested fix: Split the restore so .github/ is mandatory and .agents/ is optional:

git checkout "$BASE_SHA" -- .github/
git checkout "$BASE_SHA" -- .agents/ 2>/dev/null || true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CRITICAL — Restore failure is silently swallowed (fail-open)

|| true discards the exit code and 2>/dev/null hides the error message. If git checkout fails (invalid SHA, ref not found, git state issue), the workflow continues with the PR branch's potentially untrusted .github/ content intact. Since this snippet is documentation that practitioners will copy into real workflows, a fail-open example is actively dangerous — consumers get a false sense of security.

Failing scenario: BASE_SHA resolves to a ref that's been force-pushed away or garbage-collected. The restore silently fails and the agent runs against untrusted .github/ infrastructure from the PR branch.

Suggested fix — make .github/ restore mandatory, .agents/ optional:

git checkout "$BASE_SHA" -- .github/ \
  || { echo "::error::Failed to restore trusted .github/ from base branch"; exit 1; }
git checkout "$BASE_SHA" -- .agents/ 2>/dev/null || true

Flagged by: 3/3 reviewers

Comment on lines +216 to +218
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MODERATE — .claude/ directory not included in trusted-path restore

The restore command covers .github/ and .agents/ but not .claude/, where this repository (and others following the same pattern) stores agent skills. A PR author could embed adversarial instructions in .claude/skills/ files that survive the checkout-and-restore sequence. While this gap also existed in the old Checkout-GhAwPr.ps1 (which restored specific .github/ subpaths, not .claude/), the new snippet is an opportunity to close it — especially since this is a template others will copy.

Suggested fix — add .claude/ to the restore:

git checkout "$BASE_SHA" -- .github/ .agents/ .claude/ 2>/dev/null || true

(Combined with the fail-open fix above, make .github/ mandatory and others optional.)

Flagged by: 2/3 reviewers

```

For `pull_request` + fork support (not `workflow_dispatch`): add `forks: ["*"]` to the trigger frontmatter. The platform automatically preserves `.github/` and `.agents/` as a base-branch artifact in the activation job, then restores them after `checkout_pr_branch.cjs` — fork PRs cannot overwrite agent infrastructure (gh-aw#23769, resolved).
Expand Down Expand Up @@ -291,16 +302,7 @@ safe-outputs:
# protected-files: blocked (default) | allowed (disables protection)
```

**5. Fork PR checkout for `workflow_dispatch`** — the platform's `checkout_pr_branch.cjs` is skipped for `workflow_dispatch`, so you **must** use `.github/scripts/Checkout-GhAwPr.ps1` to check out the PR branch, verify write access, reject fork PRs, and restore trusted `.github/` from the base branch. Without it, the agent evaluates the workflow branch instead of the PR:

```yaml
steps:
- name: Checkout PR and restore agent infrastructure
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ inputs.pr_number }}
run: pwsh .github/scripts/Checkout-GhAwPr.ps1
```
**5. Fork PR checkout for `workflow_dispatch`** — the platform's `checkout_pr_branch.cjs` is skipped for `workflow_dispatch`, so you must implement a checkout step that verifies write access, rejects fork PRs, and restores trusted `.github/` from the base branch. See the [Fork PR Checkout](#fork-pr-checkout-workflow_dispatch) pattern above for a complete example.

**6. XPIA hardening (v0.70.0+)** — Cross-prompt injection (XPIA) sanitization paths have been hardened. `disable-xpia-prompt` is now **rejected at compile time in strict mode** — do not use it. If a workflow previously relied on it, remove the flag; the runtime handles XPIA protection by default.

Expand Down Expand Up @@ -434,10 +436,11 @@ Supported runtimes: `node`, `python`, `go`, `uv`, `bun`, `deno`, `ruby`, `java`,

## When to Read the Full Reference

Read `.claude/skills/gh-aw-guide/references/architecture.md` when you need:
## Further Reading
Comment on lines 437 to +439
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 MINOR — orphan heading left behind

## When to Read the Full Reference is now an empty section with no content, immediately followed by ## Further Reading. It looks like the old heading should have been removed or replaced, not left as an empty orphan.

Suggest removing line 437 (and its trailing blank line) so only ## Further Reading remains.


See the [official gh-aw documentation](https://gh.io/gh-aw) for:
- **Execution model** details (step ordering, credential availability, pre-agent-steps/post-steps)
- **Security boundaries** (defense layers, integrity filtering, protected files, rules for authors)
- **Security boundaries** (defense layers, integrity filtering, protected files)
- **Fork PR handling** (platform restore, threat model, trigger-by-trigger behavior)
- **Safe outputs** (complete list of 30+ types, key options for each)
- **Troubleshooting** specific errors
- **Upstream issue history** (all 5 tracked issues and their resolutions)
Loading