diff options
| author | Yuriy Andamasov <yuriy@vyos.io> | 2026-05-11 01:11:41 +0300 |
|---|---|---|
| committer | Yuriy Andamasov <yuriy@vyos.io> | 2026-05-11 01:11:41 +0300 |
| commit | 025319ead33f2d12c2bfb151a081ebed94f70730 (patch) | |
| tree | 1b2ea24ed04d05612aaf6c56d97b6507a210e94a | |
| parent | 14e76661a77fb16b57b65df3d04b4d816765d407 (diff) | |
| download | vyos-documentation-025319ead33f2d12c2bfb151a081ebed94f70730.tar.gz vyos-documentation-025319ead33f2d12c2bfb151a081ebed94f70730.zip | |
ci(ai-validation): address 4 CR findings — SHA pins, NUL guard, DB pin, drop id-token
Addresses the four CodeRabbit `Major / Quick win` findings raised
on this PR (after flip to ready):
1. SHA-pin all action invocations (was movable tags `@v6`, `@v4`, `@v1`
on 4 actions). pull_request_target workflows have repo write access
and access to secrets; GitHub security guidance recommends full
commit SHAs as the only immutable release form. Other steps already
were SHA-pinned, so this just resolves the inconsistency:
* actions/checkout@v6 -> @de0fac2e # v6.0.2 (x4)
* actions/upload-artifact@v4 -> @ea165f8d # v4.6.2
* actions/download-artifact@v4 -> @d3f86a10 # v4.3.0
* anthropics/claude-code-action@v1 -> @476e359e # v1.0.119
2. Reject paths containing control characters (NUL/CR/newline/etc) in
changed-md.z and changed-rst.z before `tr '\0' '\n'` converts them
to newline-delimited manifests. A fork PR could in principle commit
`docs/foo<LF>bar.md` and split it into two logical lines, masking
the real file from line-based consumers. The filesystem and
porcelain git typically reject these but the path could survive in
the tree object; fail-fast in the workflow.
3. Pin reference-DB download to `tag: ${{ env.REVIEWER_REF }}` (was
`latest: true`). REVIEWER_REF already fixes the reviewer code to
`reviewer-v1.0.1` on every use; the DB download was the one place
that resolved from the latest release tag, breaking reproducibility
and creating a silent compat-window where a future v1.x.x release
with a DB-schema change could be picked up while pinned reviewer
code still expects the old schema.
4. Drop `id-token: write` from the validate job's permissions. No step
in the workflow uses OIDC; the permission was a copy-paste leftover.
Least-privilege.
Files: same change copied byte-identically to all three workflow PRs
once they land (this PR for circinus, paired PR for sagitta, follow-up
on rolling since #1957 already merged).
| -rw-r--r-- | .github/workflows/ai-validation.yml | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/.github/workflows/ai-validation.yml b/.github/workflows/ai-validation.yml index 44952092..36f5cb6c 100644 --- a/.github/workflows/ai-validation.yml +++ b/.github/workflows/ai-validation.yml @@ -51,7 +51,7 @@ jobs: contents: read steps: - name: Checkout PR merge ref (NO credentials) - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: refs/pull/${{ github.event.number }}/merge persist-credentials: false @@ -69,6 +69,21 @@ jobs: # in changed-md.txt (which drives the bundling step). git diff "$BASE...HEAD" --name-only --diff-filter=ACMRT -z -- 'docs/**/*.md' > changed-md.z git diff "$BASE...HEAD" --name-only --diff-filter=ACMRT -z -- 'docs/**/*.rst' > changed-rst.z + # Reject paths containing control chars (newlines, CR, NUL inside the + # name, escape sequences etc) before generating the newline-delimited + # *.txt manifests. Without this guard, `tr '\0' '\n'` on a path like + # `docs/foo\nbar.md` would split it into two logical lines — + # downstream consumers reading line-by-line would miss validation + # coverage on the real file (or worse, attempt to act on a synthetic + # path). Filesystems and porcelain git typically reject these but a + # fork PR can still commit such a tree entry; fail fast. + for z in changed-md.z changed-rst.z; do + if LC_ALL=C tr -d '\0\n\r' < "$z" \ + | LC_ALL=C grep -Pq '[\x00-\x1F\x7F]'; then + echo "::error::Refusing to bundle: path in $z contains a control character. Reject the offending file name in the PR." + exit 1 + fi + done tr '\0' '\n' < changed-md.z > changed-md.txt tr '\0' '\n' < changed-rst.z > changed-rst.txt git diff "$BASE...HEAD" -- 'docs/**/*.md' > diff-md.patch @@ -123,7 +138,7 @@ jobs: done < changed-md.z - name: Upload PR input artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: pr-input path: | @@ -138,7 +153,6 @@ jobs: permissions: contents: read pull-requests: write - id-token: write steps: # Pass secrets via env: rather than inlining ${{ secrets.X }} into the # shell script. GitHub Actions template-expands ${{ ... }} BEFORE bash @@ -182,7 +196,7 @@ jobs: - name: Download PR input if: steps.secrets-check.outputs.skip != 'true' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: pr-input @@ -198,7 +212,7 @@ jobs: - name: Sparse-checkout branches.json from reviewer if: steps.secrets-check.outputs.skip != 'true' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: VyOS-Networks/vyos-docs-opus-reviewer ref: ${{ env.REVIEWER_REF }} @@ -229,7 +243,7 @@ jobs: - name: Checkout vyos-1x at mapped branch if: steps.secrets-check.outputs.skip != 'true' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: vyos-networks/vyos-1x ref: ${{ steps.branch.outputs.vyos1x }} @@ -248,7 +262,11 @@ jobs: uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13 with: repository: VyOS-Networks/vyos-docs-opus-reviewer - latest: true + # Pin the DB to the same release tag as REVIEWER_REF so a future + # reviewer-v1.x.x release with a schema change can't be silently + # picked up while the pinned reviewer code still expects the + # old schema. Reproducibility > recency for this artifact. + tag: ${{ env.REVIEWER_REF }} fileName: reference-db-${{ steps.branch.outputs.vyos1x }}.tar.gz out-file-path: .reference-db token: ${{ steps.app.outputs.token }} @@ -293,7 +311,7 @@ jobs: # reviewer-src/.git/config where the Pass 2 LLM step could read it. - name: Checkout reviewer package source (pinned to REVIEWER_REF) if: steps.secrets-check.outputs.skip != 'true' - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: VyOS-Networks/vyos-docs-opus-reviewer ref: ${{ env.REVIEWER_REF }} @@ -322,7 +340,7 @@ jobs: - name: Pass 2 — Claude review if: steps.secrets-check.outputs.skip != 'true' - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@476e359e6203e73dad705c8b322e333fabbd7416 # v1.0.119 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} # claude-code-action@v1 removed the top-level `model` input; CLI |
