Skip to content
Merged
Show file tree
Hide file tree
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
41 changes: 41 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write # creates the GitHub release and uploads assets
id-token: write # required for cosign keyless signing via GitHub OIDC
outputs:
hashes: ${{ steps.checksums.outputs.hashes }} # base64 SHA256SUMS, consumed by the provenance job below
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7

Expand All @@ -98,12 +101,50 @@ jobs:
sha256sum * > SHA256SUMS
cd -

- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: Sign binaries with cosign (keyless)
# OIDC-based keyless signing: the certificate is issued by Fulcio and
# bound to this workflow's identity (no long-lived key to manage or
# leak), and the signing event is recorded in the Rekor transparency
# log. The .cosign.bundle carries cert + signature + Rekor entry, so
# verifiers only need one extra download. See README "Verifying
# release binaries" for consumer-side verification.
run: |
cd dist
for file in *.tar.gz *.zip; do
[ -e "$file" ] || continue
echo "Signing $file..."
cosign sign-blob --yes --bundle "${file}.cosign.bundle" "$file"
done
cd -

- name: Compute hashes for SLSA provenance
id: checksums
run: |
cd dist
echo "hashes=$(base64 -w0 < SHA256SUMS)" >> "$GITHUB_OUTPUT"
cd -

- name: Create release
uses: softprops/action-gh-release@7c4723f7a335432393329f8f1c564994ce50185d # v3
with:
files: dist/*
generate_release_notes: true

provenance:
name: SLSA provenance
needs: release
permissions:
actions: read # generator reads the workflow run for provenance
id-token: write # OIDC keyless signing (same trust model as cosign)
contents: write # attach the attestation to the release
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
curl -fsSL https://raw.githubusercontent.com/slsa-framework/slsa-github-generator/main/README.md |
  grep -n -A4 'MUST be referenced by tag'

Repository: getappz/agentflare

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## release workflow context\n'
sed -n '120,160p' .github/workflows/release.yml

printf '\n## repo references to slsa-github-generator\n'
rg -n "slsa-github-generator|zizmor: ignore\\[unpinned-uses\\]|slsa-verifier" -S .

Repository: getappz/agentflare

Length of output: 1788


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## README around SLSA verification\n'
sed -n '180,210p' README.md

printf '\n## exact workflow pin in release.yml\n'
grep -n "slsa-framework/slsa-github-generator" -n .github/workflows/release.yml

Repository: getappz/agentflare

Length of output: 1795


🌐 Web query:

slsa-github-generator reusable workflow reference by tag slsa-verifier trusted builder commit SHA release.yml

💡 Result:

When using slsa-github-generator, you must reference reusable workflows by a specific semantic version tag (e.g., @vX.Y.Z) rather than by commit SHA or shorter tags (like @vX or @vX.Y) [1][2][3]. This requirement is intentional and necessary for slsa-verifier to successfully verify the reference of the trusted builder or generator [1][4]. While this approach deviates from general GitHub Actions best practices—which typically recommend pinning by commit SHA—it is a mandatory constraint due to current technical limitations in GitHub Actions [1][4][5]. Regarding verification, slsa-verifier works by verifying the cryptographic signatures on the generated provenance to confirm it was created by the expected builder [6][7]. It also validates properties such as the builder ID and the source code repository [6][7]. When you need to verify a specific commit SHA, you should use the --print-provenance flag with slsa-verifier to inspect the commit SHA of the config source or materials, rather than specifying the commit SHA directly as an input to the verification flags [6][7]. Summary of Key Practices: - Always reference slsa-github-generator reusable workflows using the full semantic version tag (@vX.Y.Z) [1][8]. - Do not use commit SHAs or short tags for these specific reusable workflow references [2][4][3]. - Use slsa-verifier to check the generated provenance against your expected builder identity and source [6][9]. - For commit SHA validation, inspect the output of slsa-verifier --print-provenance [6][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import urllib.request, re
url='https://raw.githubusercontent.com/slsa-framework/slsa-github-generator/main/README.md'
text=urllib.request.urlopen(url, timeout=20).read().decode()
for pat in ['MUST be referenced by tag', 'slsa-verifier', 'trusted builder', 'reusable workflow']:
    print(f'## {pat}')
    for m in re.finditer(pat, text, re.I):
        start=max(0,m.start()-180); end=min(len(text), m.end()+260)
        print(text[start:end].replace('\n',' '))
        print('---')
        break
PY

Repository: getappz/agentflare

Length of output: 2750


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## README around SLSA verification section\n'
sed -n '186,205p' README.md

printf '\n## upstream generator README mentions of tag/SHA guidance\n'
python3 - <<'PY'
import urllib.request, re
url='https://raw.githubusercontent.com/slsa-framework/slsa-github-generator/main/README.md'
text=urllib.request.urlopen(url, timeout=20).read().decode()
for needle in ['tag', 'commit', 'reusable workflow', 'generator_generic_slsa3.yml', 'unpinned']:
    print(f'\n## {needle}')
    for line in text.splitlines():
        if needle.lower() in line.lower():
            print(line)
PY

Repository: getappz/agentflare

Length of output: 3720


🌐 Web query:

site:github.com/slsa-framework/slsa-github-generator README reusable workflow tag commit SHA slsa-verifier verify-artifact

💡 Result:

When using slsa-verifier to verify artifacts generated by slsa-github-generator reusable workflows, you must reference the reusable workflow using a semantic version tag (e.g., @vX.Y.Z) rather than a commit SHA or a shorter tag (e.g., @vX or @vX.Y) [1][2][3]. This requirement is intentional and necessary for slsa-verifier to successfully perform verification [4][5]. Specifically, slsa-verifier needs to confirm the identity of the trusted builder or generator used to create the provenance [1][6]. Because GitHub Actions does not provide information about the associated branch or tag when a workflow is called by its commit SHA, slsa-verifier cannot distinguish between commits on a trusted branch (like main) and commits from untrusted sources (such as forks or PRs) [7]. Consequently, referencing by tag is currently the only supported method to ensure the provenance is verifiable [1][4]. While referencing third-party actions by digest is generally considered a best practice in GitHub Actions for security hardening, this specific requirement for slsa-github-generator workflows is a known limitation due to how GitHub Actions handles metadata for reusable workflows [4][5]. The technical community tracks this issue (e.g., issue #12 in the slsa-verifier repository) as a point of ongoing development [1][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import urllib.request, re
url='https://raw.githubusercontent.com/slsa-framework/slsa-github-generator/main/README.md'
text=urllib.request.urlopen(url, timeout=20).read().decode()
patterns = [
    r'reusable workflow',
    r'generator_generic_slsa3\.yml',
    r'release tag',
    r'commit SHA',
    r'full .*tag',
    r'`@v2`\.1\.0',
    r'`@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a`',
]
for pat in patterns:
    print(f'\n## {pat}')
    for m in re.finditer(pat, text, re.I):
        start=max(0,m.start()-220); end=min(len(text), m.end()+320)
        print(text[start:end].replace('\n',' '))
        print('---')
        break
PY

Repository: getappz/agentflare

Length of output: 2750


🌐 Web query:

"slsa-github-generator" reusable workflow tag commit SHA slsa-verifier README "full release tag"

💡 Result:

When using slsa-github-generator, you must reference the reusable workflow by a full version tag (e.g., @v2.1.0) rather than a commit SHA or a short tag (e.g., @v2) [1][2]. This is a security requirement that allows slsa-verifier to cryptographically verify that the provenance was generated by a trusted, specific version of the generator workflow [3][2]. Referencing by commit SHA is not supported for these reusable workflows because it prevents the verifier from distinguishing between trusted commits and untrusted commits (such as those from pull requests or forks) [3]. Regarding verification with slsa-verifier: 1. Tag Verification: You should not specify a tag in the --source-uri flag [4][5][6]. Instead, if you need to perform source versioning validation, use the --source-tag flag to verify the specific release tag [4][5][6]. 2. Commit SHA Verification: The slsa-verifier does not have a direct flag for commit SHA validation in the same way it does for tags [5][6]. To verify a specific commit SHA, you should use the --print-provenance flag to output the provenance details and then inspect the commit SHA of the config source or materials within that output [4][5][6]. In summary, the generator requires explicit tagging to ensure trust, and the verifier expects you to use specialized flags (--source-tag) for tags or manual inspection (--print-provenance) for commit SHAs [4][2][6].

Citations:


Use the v2.1.0 tag here
slsa-github-generator reusable workflows need a full release tag so slsa-verifier can validate provenance; the SHA pin breaks that. Switch to @v2.1.0 and add a targeted zizmor: ignore[unpinned-uses].

Suggested change
-    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
+    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 # zizmor: ignore[unpinned-uses]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 # zizmor: ignore[unpinned-uses]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 143, Update the reusable workflow
reference in the release workflow from the commit SHA to the full v2.1.0 tag,
and add a targeted zizmor ignore for unpinned uses on that reference. Preserve
the existing generator_generic_slsa3.yml workflow.

with:
base64-subjects: ${{ needs.release.outputs.hashes }}
upload-assets: true

update-homebrew:
name: Update Homebrew
needs: release
Expand Down
69 changes: 67 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,9 @@ cd agentflare
.\install.ps1
```

**Windows, Scoop** (prebuilt binary — unsigned, like most small Rust CLIs;
Defender/SmartScreen false-positives are possible, report an issue if hit):
**Windows, Scoop** (prebuilt binary — not Authenticode-signed, so
Defender/SmartScreen false-positives are possible; verify with cosign/SLSA
instead, see "Verifying release binaries" below; report an issue if hit):
```powershell
scoop bucket add agentflare https://github.com/getappz/agentflare
scoop install agentflare
Expand All @@ -149,6 +150,70 @@ cargo install --git https://github.com/getappz/agentflare
curl -fsSL https://raw.githubusercontent.com/getappz/agentflare/master/install.sh | sh -s -- --uninstall
```

---

## Verifying release binaries

The install methods above verify SHA-256 checksums by default — enough to
catch a corrupted download, not a substituted one. For higher-assurance
environments, verify the cryptographic signature and build provenance before
running the binary.

### cosign (signing identity)

Every release binary is signed in CI using
[cosign](https://docs.sigstore.dev/cosign/overview/) keyless signing via the
GitHub OIDC token — the certificate is issued by Fulcio and bound to this
repo's `release.yml` workflow, so verifiers pin to the workflow identity
instead of a long-lived key.

```bash
VERSION=v0.x.x
FILE=agentflare-x86_64-unknown-linux-gnu.tar.gz
curl -fL -o "$FILE" "https://github.com/getappz/agentflare/releases/download/${VERSION}/${FILE}"
curl -fL -o "${FILE}.cosign.bundle" "https://github.com/getappz/agentflare/releases/download/${VERSION}/${FILE}.cosign.bundle"

cosign verify-blob \
--bundle "${FILE}.cosign.bundle" \
--certificate-identity-regexp '^https://github\.com/getappz/agentflare/\.github/workflows/release\.yml@refs/tags/v.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"$FILE"
```

### SLSA L3 provenance (build process)

cosign proves *this repo's CI signed it*; SLSA provenance proves *how it was
built* — which commit, workflow, and inputs. Releases include a
`<tag>.intoto.jsonl` attestation generated by the
[SLSA GitHub generator](https://github.com/slsa-framework/slsa-github-generator).
Verify with [`slsa-verifier`](https://github.com/slsa-framework/slsa-verifier):

```bash
curl -fL -o "${VERSION}.intoto.jsonl" "https://github.com/getappz/agentflare/releases/download/${VERSION}/${VERSION}.intoto.jsonl"

slsa-verifier verify-artifact \
--provenance-path "${VERSION}.intoto.jsonl" \
--source-uri github.com/getappz/agentflare \
--source-tag "${VERSION}" \
"$FILE"
```

Both print a `Verified`/`PASSED` line and exit 0 on success — do not run the
binary on failure. `--certificate-identity-regexp`/`--certificate-oidc-issuer`
and `--source-uri`/`--source-tag` are the load-bearing flags in each command;
loosening any of them defeats the point.

| Attack | SHA-256 checksums | cosign keyless | SLSA L3 provenance |
|---|---|---|---|
| Corrupted download | ✅ caught | ✅ caught | ✅ caught |
| Substituted binary at release | ❌ SHA256SUMS would also be swapped | ✅ certificate identity ≠ this repo's workflow | ✅ provenance source-uri ≠ this repo |
| Stolen release-pipeline secret | ❌ | ✅ no long-lived secret to steal | ✅ provenance binds to specific workflow run |
| Tampered build process | ❌ | ❌ — cosign signs the artifact, not the build | ✅ provenance records the exact workflow, commit, and inputs |

SHA-256 stays the default in the installers above because it needs no extra
client-side tooling; cosign and SLSA are opt-in for environments that need
the higher tier.

## Set up an agent

One command per tool, run once. Running it is the consent — installs happen
Expand Down