release(v0.27.0): ClusterFuzzLite scaffolding + from_yaml OSError fix#119
Conversation
Wires ClusterFuzzLite into CI under AddressSanitizer and UndefinedBehaviorSanitizer for the three parsers that ingest attacker-controlled bytes: the OVERT envelope CBOR decoder, the audit-record from_dict deserialiser, and the policy YAML/JSON loader. PR-triggered (300s, code-change mode), nightly batch (3600s), and push-to-main build sanity all land as separate workflows so a broken Dockerfile surfaces immediately rather than at next PR. Bundled fix: from_yaml previously leaked OSError(ENAMETOOLONG) past its PolicyError contract on single-line YAML strings longer than the OS path limit. Path(source).is_file() raised before any handler ran. The is_file probe is now wrapped so any stat failure is interpreted as "not a path" and the input falls through to YAML parsing. Found by the local smoke run of fuzz_policy_loader.py before any atheris fuzzing ran. Regression test pinned in test_policy.py. Full pytest suite: 771 passed, 12 skipped.
npm Trusted Publishing has been 404'ing on every release tag since v0.23.0. The TP form on the package access page kept clearing on save (or never persisting in the first place), so the OIDC token had nothing to match against on npm side. Every release after v0.23 has required the manual `npm login --auth-type=web` + `npm publish --no-provenance` fallback to get the TypeScript client out the door. This swaps the publish-npm job back to NODE_AUTH_TOKEN with the NPM_TOKEN repo secret, drops --provenance from the publish command, and removes the now-unused id-token: write permission. The secret has been rotated to a token with "Allow bypass 2FA when publishing" enabled. Tradeoff accepted: lose npm-side provenance attestation on the @vaara/client artefact. SLSA build provenance via actions/attest-build-provenance still attests the wheel, sdist, and GitHub Release artefacts. The TypeScript client is a thin HTTP wrapper, not security-critical surface.
This reverts commit ed5c338.
📝 WalkthroughWalkthroughThis PR establishes continuous fuzzing for Vaara's parser attack surfaces using ClusterFuzzLite. It introduces a containerized build environment, three Atheris fuzz targets for OVERT envelope verification, audit record deserialization, and policy YAML/JSON loading, plus GitHub Actions workflows for PR-triggered, continuous, and nightly batch fuzzing runs. A bug fix in policy YAML handling prevents oversized single-line inputs from bypassing the error contract through OSError exceptions. ChangesContinuous Fuzzing Coverage
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| steps: | ||
| - name: Build fuzzers (${{ matrix.sanitizer }}) | ||
| id: build | ||
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 |
| sanitizer: ${{ matrix.sanitizer }} | ||
| - name: Run fuzzers (${{ matrix.sanitizer }}) | ||
| id: run | ||
| uses: google/clusterfuzzlite/actions/run_fuzzers@v1 |
| steps: | ||
| - name: Build fuzzers (${{ matrix.sanitizer }}) | ||
| id: build | ||
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 |
| id: build | ||
| # v1 tag — ClusterFuzzLite ships its action set under this moving ref; | ||
| # see https://google.github.io/clusterfuzzlite/build-integration/#step-3-create-the-github-actions-workflows | ||
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 |
| sanitizer: ${{ matrix.sanitizer }} | ||
| - name: Run fuzzers (${{ matrix.sanitizer }}) | ||
| id: run | ||
| uses: google/clusterfuzzlite/actions/run_fuzzers@v1 |
| from vaara.policy.schema import PolicyError | ||
|
|
||
| try: | ||
| import yaml as _yaml # noqa: F401 |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with 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.
Inline comments:
In @.github/workflows/cflite_batch.yml:
- Line 20: Update the ClusterFuzzLite GitHub Actions usages that currently use
mutable tags to the immutable commit SHA: replace
`google/clusterfuzzlite/actions/build_fuzzers@v1` and
`google/clusterfuzzlite/actions/run_fuzzers@v1` with
`google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1`
and
`google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1`
respectively so the workflow in `.github/workflows/cflite_batch.yml` pins to the
dereferenced immutable commit.
In @.github/workflows/cflite_cifuzz.yml:
- Line 26: Replace the mutable action ref "uses:
google/clusterfuzzlite/actions/build_fuzzers@v1" with the immutable commit SHA
to prevent silent upstream changes; update that line to use the provided commit
id "884713a6c30a92e5e8544c39945cd7cb630abcd1" (i.e., "uses:
google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1").
In @.github/workflows/cflite_pr.yml:
- Line 30: The workflow currently uses mutable tags for the ClusterFuzzLite
actions (uses: google/clusterfuzzlite/actions/build_fuzzers@v1 and uses:
google/clusterfuzzlite/actions/run_fuzzers@v1); replace those mutable tags with
the corresponding immutable commit SHAs for each action (e.g.,
google/clusterfuzzlite/actions/build_fuzzers@<commit-sha> and
google/clusterfuzzlite/actions/run_fuzzers@<commit-sha>) so the workflow is
pinned to a specific, reproducible revision; update both usages and verify the
SHAs come from the upstream repo’s tags/commits to ensure they match the
intended versions.
In `@fuzz/fuzz_overt_envelope.py`:
- Around line 76-79: The verifier currently only catches (EnvelopeError,
TypeError, ValueError) in the fuzz harness; update the exception handling around
verify_base_envelope(envelope, _DUMMY_PUBKEY) to also catch KeyError,
OverflowError, and MemoryError so the harness treats those as expected/benign
(i.e., return on those exceptions as well), keeping the existing behavior for
EnvelopeError, TypeError, and ValueError.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 530ff1ae-ae65-49ea-b5dc-37b53345827d
📒 Files selected for processing (14)
.clusterfuzzlite/Dockerfile.clusterfuzzlite/build.sh.github/workflows/cflite_batch.yml.github/workflows/cflite_cifuzz.yml.github/workflows/cflite_pr.ymlCHANGELOG.mdSECURITY.mdclients/ts/package.jsonfuzz/fuzz_audit_from_dict.pyfuzz/fuzz_overt_envelope.pyfuzz/fuzz_policy_loader.pypyproject.tomlsrc/vaara/policy/loader.pytests/test_policy.py
| steps: | ||
| - name: Build fuzzers (${{ matrix.sanitizer }}) | ||
| id: build | ||
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Resolve the v1 tag to immutable commit SHA for pinning.
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Confirm the exact uses statements in the workflow
sed -n '1,120p' .github/workflows/cflite_batch.yml | nl -ba | sed -n '1,120p'
# Find all clusterfuzzlite action usages in the repo
rg -n "google/clusterfuzzlite/actions/" .github/workflows || trueRepository: vaaraio/vaara
Length of output: 100
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- cflite_batch.yml (first 140 lines) ----"
sed -n '1,140p' .github/workflows/cflite_batch.yml | cat -n | sed -n '1,140p'
echo "---- clusterfuzzlite action usages in .github/workflows ----"
rg -n "google/clusterfuzzlite/actions/" .github/workflows || true
echo "---- exact uses lines for build_fuzzers/run_fuzzers (if present) ----"
rg -n "google/clusterfuzzlite/actions/(build_fuzzers|run_fuzzers)`@v1`" .github/workflows || trueRepository: vaaraio/vaara
Length of output: 2215
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# dereferenced commit to pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'
# pin: 884713a6c30a92e5e8544c39945cd7cb630abcd1Repository: vaaraio/vaara
Length of output: 168
Pin ClusterFuzzLite batch workflow actions to immutable commit SHAs.
.github/workflows/cflite_batch.yml uses mutable @v1 tags:
google/clusterfuzzlite/actions/build_fuzzers@v1(line 20)google/clusterfuzzlite/actions/run_fuzzers@v1(line 26)
Pin both to the dereferenced immutable v1 commit 884713a6c30a92e5e8544c39945cd7cb630abcd1.
Suggested change
- uses: google/clusterfuzzlite/actions/build_fuzzers@v1
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
- uses: google/clusterfuzzlite/actions/run_fuzzers@v1
+ uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1📝 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.
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 | |
| uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 |
🧰 Tools
🪛 GitHub Check: CodeQL
[warning] 20-20: Unpinned tag for a non-immutable Action in workflow
Unpinned 3rd party Action 'ClusterFuzzLite batch fuzzing' step Uses Step: build uses 'google/clusterfuzzlite/actions/build_fuzzers' with ref 'v1', not a pinned commit hash
🪛 zizmor (1.25.2)
[error] 20-20: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(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/cflite_batch.yml at line 20, Update the ClusterFuzzLite
GitHub Actions usages that currently use mutable tags to the immutable commit
SHA: replace `google/clusterfuzzlite/actions/build_fuzzers@v1` and
`google/clusterfuzzlite/actions/run_fuzzers@v1` with
`google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1`
and
`google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1`
respectively so the workflow in `.github/workflows/cflite_batch.yml` pins to the
dereferenced immutable commit.
| steps: | ||
| - name: Build fuzzers (${{ matrix.sanitizer }}) | ||
| id: build | ||
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Resolve the current commit behind v1 before pinning.
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'Repository: vaaraio/vaara
Length of output: 168
Review comment
File: .github/workflows/cflite_cifuzz.yml
Lines: 26-26
Comment
Pin the ClusterFuzzLite action to an immutable commit SHA.
Using @v1 leaves this workflow on a mutable ref; pinning avoids silent upstream changes. The v1 tag resolves to commit 884713a6c30a92e5e8544c39945cd7cb630abcd1.
Suggested change
- uses: google/clusterfuzzlite/actions/build_fuzzers@v1
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1📝 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.
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 | |
| uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 |
🧰 Tools
🪛 GitHub Check: CodeQL
[warning] 26-26: Unpinned tag for a non-immutable Action in workflow
Unpinned 3rd party Action 'ClusterFuzzLite continuous build' step Uses Step: build uses 'google/clusterfuzzlite/actions/build_fuzzers' with ref 'v1', not a pinned commit hash
🪛 zizmor (1.25.2)
[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(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/cflite_cifuzz.yml at line 26, Replace the mutable action
ref "uses: google/clusterfuzzlite/actions/build_fuzzers@v1" with the immutable
commit SHA to prevent silent upstream changes; update that line to use the
provided commit id "884713a6c30a92e5e8544c39945cd7cb630abcd1" (i.e., "uses:
google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1").
| id: build | ||
| # v1 tag — ClusterFuzzLite ships its action set under this moving ref; | ||
| # see https://google.github.io/clusterfuzzlite/build-integration/#step-3-create-the-github-actions-workflows | ||
| uses: google/clusterfuzzlite/actions/build_fuzzers@v1 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Resolve commits for action refs before pinning.
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1' 'refs/tags/v1^{}'Repository: vaaraio/vaara
Length of output: 168
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant portion of the workflow with line numbers
nl -ba .github/workflows/cflite_pr.yml | sed -n '1,120p'Repository: vaaraio/vaara
Length of output: 100
🏁 Script executed:
#!/bin/bash
set -euo pipefail
cat -n .github/workflows/cflite_pr.yml | sed -n '1,120p'Repository: vaaraio/vaara
Length of output: 1590
🏁 Script executed:
git ls-remote https://github.com/google/clusterfuzzlite.git 'refs/tags/v1^{}'Repository: vaaraio/vaara
Length of output: 114
Pin ClusterFuzzLite actions to immutable SHAs.
.github/workflows/cflite_pr.yml uses the mutable @v1 tag for both google/clusterfuzzlite/actions/build_fuzzers and google/clusterfuzzlite/actions/run_fuzzers.
Suggested change
- uses: google/clusterfuzzlite/actions/build_fuzzers@v1
+ uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1
- uses: google/clusterfuzzlite/actions/run_fuzzers@v1
+ uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1🧰 Tools
🪛 GitHub Check: CodeQL
[warning] 30-30: Unpinned tag for a non-immutable Action in workflow
Unpinned 3rd party Action 'ClusterFuzzLite PR fuzzing' step Uses Step: build uses 'google/clusterfuzzlite/actions/build_fuzzers' with ref 'v1', not a pinned commit hash
🪛 zizmor (1.25.2)
[error] 30-30: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(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/cflite_pr.yml at line 30, The workflow currently uses
mutable tags for the ClusterFuzzLite actions (uses:
google/clusterfuzzlite/actions/build_fuzzers@v1 and uses:
google/clusterfuzzlite/actions/run_fuzzers@v1); replace those mutable tags with
the corresponding immutable commit SHAs for each action (e.g.,
google/clusterfuzzlite/actions/build_fuzzers@<commit-sha> and
google/clusterfuzzlite/actions/run_fuzzers@<commit-sha>) so the workflow is
pinned to a specific, reproducible revision; update both usages and verify the
SHAs come from the upstream repo’s tags/commits to ensure they match the
intended versions.
| try: | ||
| verify_base_envelope(envelope, _DUMMY_PUBKEY) | ||
| except (EnvelopeError, TypeError, ValueError): | ||
| return |
There was a problem hiding this comment.
Align verifier exception handling with the stated contract.
Lines 78-79 catch fewer exception types than the contract described in Lines 7-10. If verify_base_envelope raises KeyError, OverflowError, or MemoryError, this harness reports a finding even though those are documented as expected.
Proposed fix
- except (EnvelopeError, TypeError, ValueError):
+ except (
+ EnvelopeError,
+ TypeError,
+ ValueError,
+ KeyError,
+ OverflowError,
+ MemoryError,
+ ):
return🤖 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 `@fuzz/fuzz_overt_envelope.py` around lines 76 - 79, The verifier currently
only catches (EnvelopeError, TypeError, ValueError) in the fuzz harness; update
the exception handling around verify_base_envelope(envelope, _DUMMY_PUBKEY) to
also catch KeyError, OverflowError, and MemoryError so the harness treats those
as expected/benign (i.e., return on those exceptions as well), keeping the
existing behavior for EnvelopeError, TypeError, and ValueError.
Summary
AuditRecord.from_dict, policy YAML/JSON loader.vaara.policy.loader.from_yamlleakedOSError(ENAMETOOLONG)past itsPolicyErrorcontract on single-line YAML strings longer than the OS path limit. Found by the local smoke run offuzz_policy_loader.pybefore any atheris fuzzing ran. Regression test pinned intests/test_policy.py.Test plan
Summary by CodeRabbit
Bug Fixes
PolicyErrorfor oversized single-line strings instead of leaking system errors.Chores