From 7c9c43f1158ee3775dad26d40ae3e71b18d496c5 Mon Sep 17 00:00:00 2001 From: Prajwol Gyawali Date: Sun, 7 Jun 2026 09:50:55 +0545 Subject: [PATCH 1/4] ci: pre-build SP1 core runner binary via override env The clippy job runs `--all-features`, which pulls `sp1-core-executor-runner` into the lint graph. Its build.rs runs a nested `cargo build` and embeds the result via `include_bytes!(env!("SP1_CORE_RUNNER_BINARY"))`. Since clippy runs build scripts, that native build executes even for a lint, and it breaks on a `Swatinem/rust-cache` hit: the helper binary lives under the registry source dir (not preserved by the cache), while the build-script output recording its path is cached, so cargo skips the rebuild and `include_bytes!` can't read it. The crate's build.rs honors a `SP1_CORE_RUNNER_OVERRIDE_BINARY` env var (source-only; not in its README/docs): when set it skips the nested build and points the runtime at an external binary instead. A `prebuild-sp1-runner` composite action pre-builds the helper into `$RUNNER_TEMP` and returns its path as an output; lint.yml and prover.yml set it as the override env only on the steps that compile the crate. Returning a path rather than writing `$GITHUB_ENV` keeps the override scoped to those steps instead of the whole job. This is cache-stable and keeps the heavy build out of the lint, unlike the previous `cargo clean` workaround it replaces in prover.yml. The helper version is read from Cargo.lock, not the `sp1-sdk` requirement, which is a caret that floats up to a later patch in the lock. --- .../actions/prebuild-sp1-runner/action.yml | 37 +++++++++++++++++++ .github/workflows/lint.yml | 9 +++++ .github/workflows/prover.yml | 19 ++++------ 3 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 .github/actions/prebuild-sp1-runner/action.yml diff --git a/.github/actions/prebuild-sp1-runner/action.yml b/.github/actions/prebuild-sp1-runner/action.yml new file mode 100644 index 00000000..71d0253a --- /dev/null +++ b/.github/actions/prebuild-sp1-runner/action.yml @@ -0,0 +1,37 @@ +name: Pre-build SP1 core runner binary +description: >- + Pre-build the sp1-core-executor-runner helper binary so the crate's build.rs + skips its nested cargo build. Returns the binary path as an output; set it as + SP1_CORE_RUNNER_OVERRIDE_BINARY on the steps that compile the crate. Requires + the repo checked out and a Rust toolchain on PATH. + +# `sp1-core-executor-runner`'s build.rs runs a nested `cargo build` and embeds +# the helper binary via `include_bytes!(env!("SP1_CORE_RUNNER_BINARY"))`. The +# binary lands under the registry source dir, which `Swatinem/rust-cache` does +# not preserve, while the build-script output that records its path is cached — +# so on a cache hit cargo skips the rebuild and `include_bytes!` fails with +# "couldn't read ...". The crate's build.rs honors `SP1_CORE_RUNNER_OVERRIDE_BINARY` +# (source-only, not in its docs): when set it skips the nested build and points +# at an external binary instead. Pin to the version resolved in Cargo.lock, not +# the `sp1-sdk` requirement (a caret that floats up to a later patch), so the +# prebuilt helper matches the linked runner crate. +# +# The path is returned as an output rather than written to $GITHUB_ENV so it is +# scoped to the steps that opt in (via env:), instead of every step in the job. +outputs: + override-binary: + description: >- + Absolute path to the prebuilt helper. Set it as + SP1_CORE_RUNNER_OVERRIDE_BINARY on steps that build sp1-core-executor-runner. + value: ${{ steps.prebuild.outputs.override-binary }} +runs: + using: composite + steps: + - id: prebuild + name: Pre-build SP1 core runner binary + shell: bash + run: | + VER="$(awk -F'"' '/^name = "sp1-core-executor-runner-binary"$/{f=1;next} f&&/^version = /{print $2;exit}' Cargo.lock)" + test -n "$VER" || { echo "could not determine sp1-core-executor-runner-binary version from Cargo.lock"; exit 1; } + cargo install sp1-core-executor-runner-binary --version "$VER" --root "$RUNNER_TEMP/sp1-core-runner" --force + echo "override-binary=$RUNNER_TEMP/sp1-core-runner/bin/sp1-core-executor-runner-binary" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5baf5252..c05d5018 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -37,10 +37,19 @@ jobs: - name: Install protoc uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + # `--all-features` pulls in `sp1-core-executor-runner`, whose build.rs + # embeds a nested-built helper that breaks clippy on a cache hit; the + # action pre-builds it and returns the path to use as the override (see the + # action for why). + - name: Pre-build SP1 core runner binary + id: sp1-runner + uses: ./.github/actions/prebuild-sp1-runner + - name: Run clippy run: cargo clippy --examples --tests --benches --all-features --all-targets --locked env: RUSTFLAGS: -D warnings + SP1_CORE_RUNNER_OVERRIDE_BINARY: ${{ steps.sp1-runner.outputs.override-binary }} fmt: name: Check code formatting diff --git a/.github/workflows/prover.yml b/.github/workflows/prover.yml index 1d540606..4760d282 100644 --- a/.github/workflows/prover.yml +++ b/.github/workflows/prover.yml @@ -52,17 +52,12 @@ jobs: - name: Install protoc uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 - # `sp1-core-executor-runner`'s build.rs builds a helper binary and embeds - # it via `include_bytes!(env!("SP1_CORE_RUNNER_BINARY"))`. When pulled from - # crates.io, the binary is written *inside* the registry source dir - # (`~/.cargo/registry/src/.../sp1-core-executor-runner-X.Y.Z/target/`), - # which `Swatinem/rust-cache` does not preserve — but it does cache the - # build-script output that records the path. On a cache hit cargo skips - # rerunning the build script, then `include_bytes!` fails with "couldn't - # read ..." because the binary is gone. Clean these crates so build.rs - # always re-runs and re-creates the binary. - - name: Clean SP1 core executor runner crates - run: cargo clean -p sp1-core-executor-runner -p sp1-core-executor-runner-binary + # `sp1-core-executor-runner`'s build.rs embeds a nested-built helper that + # breaks on a cache hit; the action pre-builds it and returns the path to + # use as the override so build.rs skips the nested build (see the action). + - name: Pre-build SP1 core runner binary + id: sp1-runner + uses: ./.github/actions/prebuild-sp1-runner - name: Run prover-perf and post PR comment if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false @@ -70,6 +65,7 @@ jobs: ZKVM_MOCK: "1" ZKVM_PROFILING: "1" SKIP_VKEY_BUILD: "1" + SP1_CORE_RUNNER_OVERRIDE_BINARY: ${{ steps.sp1-runner.outputs.override-binary }} run: | cargo run --release -p strata-asm-prover-perf -- \ --post-to-gh \ @@ -85,5 +81,6 @@ jobs: ZKVM_MOCK: "1" ZKVM_PROFILING: "1" SKIP_VKEY_BUILD: "1" + SP1_CORE_RUNNER_OVERRIDE_BINARY: ${{ steps.sp1-runner.outputs.override-binary }} run: | cargo run --release -p strata-asm-prover-perf -- --programs asm-stf From e013da1d5906b05721bd6e4f2088e17dc187087e Mon Sep 17 00:00:00 2001 From: Prajwol Gyawali Date: Sun, 7 Jun 2026 10:26:06 +0545 Subject: [PATCH 2/4] ci: extract shared setup-rust and setup-sp1 composite actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every workflow repeated the same Rust setup (toolchain install + Swatinem cache + protoc) with only small variations, and prover/release duplicated the SP1 toolchain install + version check verbatim. That spread the pinned action SHAs and the rust-toolchain.toml parse across nine jobs, so a bump had to be made in many places. Factor the setup into two local composite actions: - `setup-rust` (inputs: channel, components, cache, protoc) — installs the toolchain and, by default, restores the cache and installs protoc. `channel: rust-toolchain.toml` reads the pinned channel from that file. - `setup-sp1` — sp1up install + PATH + `cargo prove --version`. Behavior is preserved per job via inputs: components (clippy/rustfmt/ llvm-tools-preview), cache disabled for the fmt and release jobs, protoc disabled for the fmt and security jobs, and the rust-toolchain.toml channel for prover/release. Every input combination release.yml uses is also exercised by a PR-triggered job, so the tag-only release workflow is covered indirectly. setup-sp1 carries a `zizmor: ignore[github-env]` for its $GITHUB_PATH append: persisting $HOME/.sp1/bin onto PATH for later steps requires $GITHUB_PATH and the value is fixed and trusted. zizmor flags env-file writes in composite actions (context-agnostic) even though the same write was unflagged inline in the workflows. --- .github/actions/setup-rust/action.yml | 45 +++++++++++++++++++++++++++ .github/actions/setup-sp1/action.yml | 20 ++++++++++++ .github/workflows/docs.yml | 14 ++------- .github/workflows/functional.yml | 16 +++------- .github/workflows/lint.yml | 24 ++++++-------- .github/workflows/prover.yml | 25 +++------------ .github/workflows/release.yml | 23 +++++--------- .github/workflows/security.yml | 12 +++---- .github/workflows/unit.yml | 30 ++++-------------- 9 files changed, 102 insertions(+), 107 deletions(-) create mode 100644 .github/actions/setup-rust/action.yml create mode 100644 .github/actions/setup-sp1/action.yml diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml new file mode 100644 index 00000000..c632254e --- /dev/null +++ b/.github/actions/setup-rust/action.yml @@ -0,0 +1,45 @@ +name: Set up Rust +description: >- + Install a Rust toolchain (optionally with components) and, by default, restore + the Swatinem cache and install protoc. Requires the repo to be checked out. +inputs: + channel: + description: >- + Toolchain to install and default to. Use the literal "rust-toolchain.toml" + to read the pinned channel from that file instead. + default: nightly + components: + description: 'Space-separated rustup components to add (e.g. "clippy rustfmt").' + default: "" + cache: + description: 'Whether to restore the Swatinem/rust-cache ("true"/"false").' + default: "true" + protoc: + description: 'Whether to install protoc ("true"/"false").' + default: "true" +runs: + using: composite + steps: + - name: Install Rust toolchain + shell: bash + env: + CHANNEL: ${{ inputs.channel }} + COMPONENTS: ${{ inputs.components }} + run: | + if [ "$CHANNEL" = "rust-toolchain.toml" ]; then + CHANNEL="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml)" + fi + args=() + for c in $COMPONENTS; do args+=(--component "$c"); done + rustup toolchain install "$CHANNEL" --profile minimal "${args[@]}" + rustup default "$CHANNEL" + + - name: Rust cache + if: inputs.cache == 'true' + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 + with: + cache-on-failure: true + + - name: Install protoc + if: inputs.protoc == 'true' + uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 diff --git a/.github/actions/setup-sp1/action.yml b/.github/actions/setup-sp1/action.yml new file mode 100644 index 00000000..7c1c6fd7 --- /dev/null +++ b/.github/actions/setup-sp1/action.yml @@ -0,0 +1,20 @@ +name: Set up SP1 toolchain +description: >- + Install the SP1 toolchain via sp1up, add it to PATH, and verify cargo prove is + available. Requires a Rust toolchain to already be on PATH. +runs: + using: composite + steps: + - name: Install SP1 toolchain + shell: bash + # The only env-file write appends a fixed, trusted dir ($HOME/.sp1/bin) to + # PATH; persisting PATH across steps requires $GITHUB_PATH and there is no + # user input, so the github-env finding is a false positive. + run: | # zizmor: ignore[github-env] + curl -fsSL --proto '=https' --tlsv1.2 https://sp1.succinct.xyz | bash + ~/.sp1/bin/sp1up + echo "$HOME/.sp1/bin" >> "$GITHUB_PATH" + + - name: Check SP1 toolchain + shell: bash + run: cargo prove --version diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e68b0435..11e58989 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,18 +24,8 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal - rustup default nightly - - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - with: - cache-on-failure: true - - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + - name: Set up Rust + uses: ./.github/actions/setup-rust - name: Check docs leaving the dependencies out env: diff --git a/.github/workflows/functional.yml b/.github/workflows/functional.yml index 1e6f5127..6ef846c7 100644 --- a/.github/workflows/functional.yml +++ b/.github/workflows/functional.yml @@ -75,24 +75,16 @@ jobs: bitcoind --version rm -rf SHA256SUMS "bitcoin-$BITCOIND_VERSION" "bitcoin-$BITCOIND_VERSION-$BITCOIND_ARCH.tar.gz" - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal --component llvm-tools-preview - rustup default nightly + - name: Set up Rust + uses: ./.github/actions/setup-rust + with: + components: llvm-tools-preview - name: Install cargo-llvm-cov uses: taiki-e/install-action@b550161ef8a7bc4f2a671c0b03a18ac9ccedea1e # v2.79.1 with: tool: cargo-llvm-cov - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - with: - cache-on-failure: true - - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 - - name: Install uv uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c05d5018..48befddd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,18 +24,10 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal --component clippy - rustup default nightly - - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 + - name: Set up Rust + uses: ./.github/actions/setup-rust with: - cache-on-failure: true - - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + components: clippy # `--all-features` pulls in `sp1-core-executor-runner`, whose build.rs # embeds a nested-built helper that breaks clippy on a cache hit; the @@ -63,10 +55,12 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal --component rustfmt - rustup default nightly + - name: Set up Rust + uses: ./.github/actions/setup-rust + with: + components: rustfmt + cache: "false" + protoc: "false" - name: Check Rust formatting run: cargo fmt --all --check diff --git a/.github/workflows/prover.yml b/.github/workflows/prover.yml index 4760d282..f8d4c6c8 100644 --- a/.github/workflows/prover.yml +++ b/.github/workflows/prover.yml @@ -29,28 +29,13 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - RUST_TOOLCHAIN="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml)" - rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal - rustup default "$RUST_TOOLCHAIN" - - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 + - name: Set up Rust + uses: ./.github/actions/setup-rust with: - cache-on-failure: true - - - name: Install SP1 Toolchain - run: | - curl -fsSL --proto '=https' --tlsv1.2 https://sp1.succinct.xyz | bash - ~/.sp1/bin/sp1up - echo "$HOME/.sp1/bin" >> "$GITHUB_PATH" - - - name: Check SP1 toolchain - run: cargo prove --version + channel: rust-toolchain.toml - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + - name: Set up SP1 toolchain + uses: ./.github/actions/setup-sp1 # `sp1-core-executor-runner`'s build.rs embeds a nested-built helper that # breaks on a cache hit; the action pre-builds it and returns the path to diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34de2945..35a96caa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,23 +27,14 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - RUST_TOOLCHAIN="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml)" - rustup toolchain install "$RUST_TOOLCHAIN" --profile minimal - rustup default "$RUST_TOOLCHAIN" - - - name: Install SP1 toolchain - run: | - curl -fsSL --proto '=https' --tlsv1.2 https://sp1.succinct.xyz | bash - ~/.sp1/bin/sp1up - echo "$HOME/.sp1/bin" >> "$GITHUB_PATH" - - - name: Check SP1 toolchain - run: cargo prove --version + - name: Set up Rust + uses: ./.github/actions/setup-rust + with: + channel: rust-toolchain.toml + cache: "false" - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + - name: Set up SP1 toolchain + uses: ./.github/actions/setup-sp1 - name: Build guest ELFs and vk JSONs # Override the repo-wide SKIP_VKEY_BUILD=1 default (.cargo/config.toml) so diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index e6417d51..e577404f 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -24,15 +24,11 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal --component clippy - rustup default nightly - - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 + - name: Set up Rust + uses: ./.github/actions/setup-rust with: - cache-on-failure: true + components: clippy + protoc: "false" - name: Install latest cargo-audit from source run: cargo install cargo-audit --force --locked diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 12ee80b4..2f07c702 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -31,10 +31,10 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal --component llvm-tools-preview - rustup default nightly + - name: Set up Rust + uses: ./.github/actions/setup-rust + with: + components: llvm-tools-preview - name: Install latest cargo-nextest release uses: taiki-e/install-action@b550161ef8a7bc4f2a671c0b03a18ac9ccedea1e # v2.79.1 @@ -59,14 +59,6 @@ jobs: bitcoind --version rm -rf SHA256SUMS "bitcoin-$BITCOIND_VERSION" "bitcoin-$BITCOIND_VERSION-$BITCOIND_ARCH.tar.gz" - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - with: - cache-on-failure: true - - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 - - name: Run tests with coverage run: | cargo llvm-cov --locked --workspace nextest --all-features --lcov --output-path lcov.unit.info @@ -94,18 +86,8 @@ jobs: with: persist-credentials: false - - name: Install Rust toolchain - run: | - rustup toolchain install nightly --profile minimal - rustup default nightly - - - name: Rust cache - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - with: - cache-on-failure: true - - - name: Install protoc - uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + - name: Set up Rust + uses: ./.github/actions/setup-rust - name: Run doctests run: cargo test --doc --all-features From debfbc11f8d9e3672b8b2ed289f3a395defad1ff Mon Sep 17 00:00:00 2001 From: vladb-ai Date: Thu, 2 Jul 2026 14:31:19 +0000 Subject: [PATCH 3/4] chore: trigger AI security review From 845cdbbd4bbccc2d734b09ec310a8b05f4bd5f20 Mon Sep 17 00:00:00 2001 From: vladb-ai Date: Thu, 2 Jul 2026 14:54:53 +0000 Subject: [PATCH 4/4] ci: add AI security review workflow to PR branch --- .github/workflows/claude-security-review.yml | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/claude-security-review.yml diff --git a/.github/workflows/claude-security-review.yml b/.github/workflows/claude-security-review.yml new file mode 100644 index 00000000..b8677dfa --- /dev/null +++ b/.github/workflows/claude-security-review.yml @@ -0,0 +1,47 @@ +name: AI Security Review + +permissions: + contents: read + pull-requests: write # Needed for leaving PR review comments + id-token: write # Needed by claude-code-action's OIDC flow + +on: + pull_request: + +jobs: + security: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + fetch-depth: 0 + + - uses: anthropics/claude-code-action@v1 + with: + # Subscription / account auth (Claude Pro/Max) instead of an API key. + # Generate with `claude setup-token` and add as a repo secret. + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + # Use the built-in Actions token for PR ops so no Claude GitHub App install is required. + github_token: ${{ github.token }} + use_sticky_comment: true + prompt: | + Perform a security review of pull request #${{ github.event.pull_request.number }} in ${{ github.repository }}. + Run `gh pr diff ${{ github.event.pull_request.number }}` to get the changes, and read the surrounding code for context. + + Report only real, exploitable vulnerabilities introduced or exposed by this diff: + - Injection (SQL / command / template), unsafe deserialization, path traversal, SSRF + - Broken authn/authz, missing access checks, insecure direct object references + - Cryptographic misuse, weak randomness, secret / credential exposure + - Memory safety, integer overflow/underflow, unchecked arithmetic, panics on untrusted input (watch Rust `unsafe`) + - Input-validation gaps, unsafe error handling, resource exhaustion / DoS + + For each finding report: `file:line`, severity (Critical/High/Medium/Low), a concrete exploit scenario, and a concrete fix. + Favor precision over recall — do not report style issues or speculative concerns. If there are no security issues, say so briefly. + + When done, post your review as exactly ONE pull-request comment by running: + `gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body ""` + Start the comment with the heading "## 🔒 AI Security Review". + claude_args: | + --max-turns 40 + --allowedTools "Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api:*),Bash(gh pr comment:*),Bash(cat:*),Bash(ls:*),Bash(grep:*),Bash(rg:*),Bash(find:*),Bash(head:*),Bash(tail:*),Bash(sed:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Read,Grep,Glob"