Skip to content

Chore/scorecard improvements#444

Merged
ginccc merged 10 commits into
mainfrom
chore/scorecard-improvements
Apr 23, 2026
Merged

Chore/scorecard improvements#444
ginccc merged 10 commits into
mainfrom
chore/scorecard-improvements

Conversation

@ginccc

@ginccc ginccc commented Apr 23, 2026

Copy link
Copy Markdown
Member

This pull request introduces several major improvements to the project's security and release processes, focusing on compliance with OpenSSF Scorecard requirements. The most significant changes are the addition of continuous fuzzing with ClusterFuzzLite, automated SLSA supply-chain provenance attestation, and automated signed GitHub Releases. These enhancements strengthen the project's supply chain integrity, vulnerability detection, and release transparency.

Security and Supply Chain Improvements

  • Added ClusterFuzzLite configuration (.clusterfuzzlite/) with a custom Dockerfile, project.yaml, and a build.sh script that builds and packages Jazzer-based fuzz targets for PathNavigator and MatchingUtilities. This enables JVM fuzzing as part of CI. [1] [2] [3]
  • Introduced .github/workflows/clusterfuzzlite.yml to run fuzzing in two modes: on pull requests (code-change fuzzing, 5 minutes) and weekly (batch fuzzing, 30 minutes), increasing the likelihood of catching regressions and rare bugs.

Release Process and Provenance

  • Updated the main CI workflow (.github/workflows/ci.yml) to:
    • Grant the required permissions for creating GitHub Releases and SLSA provenance attestations.
    • Capture the Docker image digest after pushing and output it for subsequent steps. [1] [2]
    • Generate and push SLSA build provenance attestations using actions/attest-build-provenance.
    • Automatically create a signed GitHub Release on tag pushes, including Docker pull and verification instructions.

Documentation

  • Updated docs/changelog.md to document all the above changes, including action version pinning, rationale, and code review findings.

Summary by CodeRabbit

  • New Features

    • Enable continuous JVM fuzzing on PRs and weekly schedules via ClusterFuzzLite with automated fuzzer build and execution.
  • Chores

    • Generate SLSA provenance attestations for pushed images; automated GitHub Release creation with image digest and verification instructions.
    • Expanded CI permissions and ensured fuzzing config is included in Docker build context.
  • Documentation

    • Added changelog entry describing CI and supply-chain improvements.
  • Tests

    • Improved integration test reliability by adding a retry helper for async endpoints.

ginccc added 2 commits April 23, 2026 10:22
…nd GitHub Releases

- Add .clusterfuzzlite/ config (project.yaml, Dockerfile, build.sh)
  with standalone Jazzer fuzz targets for PathNavigator and MatchingUtilities
- Add clusterfuzzlite.yml workflow: PR code-change fuzzing (5min) + weekly batch (30min)
- Add SLSA provenance attestation via actions/attest-build-provenance@v4.1.0
- Add automatic GitHub Release creation on tag pushes via softprops/action-gh-release@v3.0.0
- Capture Docker image digest for provenance subject binding
- All actions pinned to latest SHA commits

Scorecard checks targeted: Fuzzing, Signed-Releases
@ginccc ginccc requested a review from rolandpickl April 23, 2026 09:09
@ginccc ginccc self-assigned this Apr 23, 2026
@github-actions

github-actions Bot commented Apr 23, 2026

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/google/clusterfuzzlite/actions/build_fuzzers 52ecc61cb587ee99c26825a112a21abf19c7448c UnknownUnknown
actions/google/clusterfuzzlite/actions/run_fuzzers 52ecc61cb587ee99c26825a112a21abf19c7448c UnknownUnknown

Scanned Files

  • .github/workflows/clusterfuzzlite.yml

@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@ginccc has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 24 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 20 minutes and 24 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ffe9d068-10a8-4e60-86ed-e3a51d6bcadc

📥 Commits

Reviewing files that changed from the base of the PR and between 306ba07 and 7d455cf.

📒 Files selected for processing (3)
  • .clusterfuzzlite/build.sh
  • .github/workflows/clusterfuzzlite.yml
  • src/test/java/ai/labs/eddi/integration/BaseIntegrationIT.java
📝 Walkthrough

Walkthrough

Adds JVM ClusterFuzzLite fuzzing: new Dockerfile and build script that generate two Jazzer fuzz targets, ClusterFuzzLite project config and workflow, CI changes to publish image digests and produce SLSA attestations/releases, multiple new utility classes used by fuzzers, test stability helpers, docs update, and .dockerignore adjustments to include fuzz sources.

Changes

Cohort / File(s) Summary
ClusterFuzzLite Docker & config
​.clusterfuzzlite/Dockerfile, ​.clusterfuzzlite/project.yaml
New Dockerfile based on OSS‑Fuzz JVM builder and a minimal project.yaml declaring jvm runtime.
ClusterFuzzLite build & generated fuzzers
​.clusterfuzzlite/build.sh
New build script that stages selected utility classes, rewrites Java 22 unnamed-catch syntax, compiles utilities with --release 17/21, generates two Jazzer fuzz entry classes (PathNavigatorFuzzer, MatchingUtilitiesFuzzer), and emits per-target wrapper scripts invoking jazzer_driver.
Fuzzing utilities
​.clusterfuzzlite/PathNavigator.java, ​.clusterfuzzlite/MatchingUtilities.java, ​.clusterfuzzlite/RuntimeUtilities.java
Added utility classes: PathNavigator (get/set nested values with simple expression support), MatchingUtilities (value-path matching logic), and RuntimeUtilities (argument checks and resource loading).
Workflows / CI
.github/workflows/ci.yml, .github/workflows/clusterfuzzlite.yml
ci.yml expanded permissions, captures pushed image digest, conditionally creates SLSA attestations and GitHub Releases; new clusterfuzzlite.yml runs ClusterFuzzLite build+run on PR code-change and weekly batch schedules with SARIF upload.
Tests
src/test/java/.../BaseIntegrationIT.java, src/test/java/.../ConversationServiceComponentIT.java
Added retryUntilOk helper and updated two integration tests to use retries and declare throws Exception for improved async stability.
Build context
.dockerignore
Un-ignores .clusterfuzzlite/** so fuzz config/scripts are included in Docker build context.
Documentation
docs/changelog.md
Adds changelog entry documenting fuzzing integration, attestations, release automation, and related fixes.

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer (push/tag)
  participant GH as GitHub Actions
  participant Docker as Container Registry
  participant Att as Attestation Service (actions/attest-build-provenance)
  participant CF as ClusterFuzzLite runner / Jazzer

  Dev->>GH: push or tag
  GH->>GH: build Docker image (ci job)
  GH->>Docker: push image (record digest)
  GH->>Att: create SLSA attestation using digest
  GH->>GitHub: create Release on tag (include digest & cosign cmds)
  GH->>CF: build fuzzers (ClusterFuzzLite build action)
  GH->>CF: run fuzzers (ClusterFuzzLite run action) -> SARIF upload
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • rolandpickl

Poem

🐰 I hopped through code and left a trace,

fuzz seeds scattered in every place,
Jazzer hums while paths are chased,
attestations wrapped and safely placed,
builds and releases — a neat, secure race.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Chore/scorecard improvements' is vague and does not clearly convey the main changes. While it references the branch name and general area, it lacks specificity about the primary improvements (fuzzing, SLSA provenance, releases). Consider a more descriptive title such as 'Add ClusterFuzzLite fuzzing and SLSA provenance to improve OpenSSF Scorecard compliance' to better communicate the key changes to reviewers scanning the history.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/scorecard-improvements

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 6

🧹 Nitpick comments (2)
docs/changelog.md (1)

16-56: Add Files, Design decisions, and Next steps blocks for consistency.

This entry is strong, but adding those three blocks would match the established changelog template and make future audits easier.

Based on learnings: "Update docs/changelog.md after completing work with date, title, repo/branch, files changed, design decisions, and next steps".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/changelog.md` around lines 16 - 56, Add three standard changelog
sections to this entry: a "Files" block listing the new/changed files from the
diff (e.g., .clusterfuzzlite/project.yaml, .clusterfuzzlite/Dockerfile,
.clusterfuzzlite/build.sh, .github/workflows/clusterfuzzlite.yml, CI/action pin
list), a "Design decisions" block summarizing key choices (use of jazzer_driver
and $this_dir-relative paths, try/catch in fuzz targets, pushing SLSA
attestations to Docker Hub, signed GitHub release strategy), and a "Next steps"
block with follow-ups (monitor fuzzing results, rotate pinned-action SHAs if
needed, verify attestation consumption, document container-only distribution).
Ensure headings match the changelog style ("Files", "Design decisions", "Next
steps") and place them under the existing entry for the 2026-04-23 OpenSSF
Scorecard item.
.clusterfuzzlite/build.sh (1)

10-111: Quote variable expansions (Shellcheck SC2086).

Shellcheck flags unquoted $SRC, $OUT, and ${fuzzer} on lines 10, 23, 24, 27, 28, 35, 70, 105, 106, 107, 111, and 122. These are generally safe in the ClusterFuzzLite sandbox but quoting is cheap insurance against paths containing spaces or globs, and keeps CI lint clean.

✂️ Example of the pattern
-cd $SRC/project
+cd "$SRC/project"
...
-cp -r target/classes $OUT/classes
-cp -r target/test-classes $OUT/test-classes
+cp -r target/classes "$OUT/classes"
+cp -r target/test-classes "$OUT/test-classes"
...
-cat > $SRC/PathNavigatorFuzzer.java << 'EOF'
+cat > "$SRC/PathNavigatorFuzzer.java" << 'EOF'
...
-javac -cp "${BUILD_CP}" \
-    -d $OUT \
-    $SRC/PathNavigatorFuzzer.java \
-    $SRC/MatchingUtilitiesFuzzer.java
+javac -cp "${BUILD_CP}" \
+    -d "$OUT" \
+    "$SRC/PathNavigatorFuzzer.java" \
+    "$SRC/MatchingUtilitiesFuzzer.java"
...
-    cat > $OUT/${fuzzer} << WRAPPER
+    cat > "$OUT/${fuzzer}" << WRAPPER
 ...
-    chmod +x $OUT/${fuzzer}
+    chmod +x "$OUT/${fuzzer}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.clusterfuzzlite/build.sh around lines 10 - 111, The shell script uses
unquoted path/glob variables causing Shellcheck SC2086; update all uses of SRC,
OUT, BUILD_CP, RUNTIME_CP and the loop variable fuzzer to use
quoted/brace-expanded forms (e.g. "$SRC", "$OUT", "${BUILD_CP}", "$RUNTIME_CP",
"${fuzzer}") and also quote them in compound contexts (javac -cp "$BUILD_CP", cp
-r "$SRC"/..., cat > "$OUT/${fuzzer}", cp target/deps/*.jar "$OUT/deps/" etc.)
so expansions are safe with spaces/globs while preserving the existing behavior
of PathNavigatorFuzzer/MatchingUtilitiesFuzzer generation and wrapper creation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.clusterfuzzlite/build.sh:
- Around line 58-65: Remove the broad catch(Exception) in fuzzerTestOneInput so
runtime bugs from PathNavigator.getValue are not swallowed; either delete the
try/catch entirely or restrict it to documented checked exceptions only, and
apply the same change to MatchingUtilitiesFuzzer.fuzzerTestOneInput where
MatchingUtilities.executeValuePath is invoked; make sure only specific noisy
exceptions (if any) are caught rather than catching Exception or Throwable so
Jazzer can surface NPEs, IndexOutOfBoundsException, ClassCastException, etc.
- Around line 26-28: The copy command silently ignores failure; change the cp
invocation (target/deps/*.jar to $OUT/deps/) so it fails loudly: remove the
"2>/dev/null || true" suppression and instead check that target/deps contains at
least one .jar (e.g., test -n "$(ls target/deps/*.jar 2>/dev/null)") and if none
exist emit a clear error via echo to stderr and exit non‑zero; update the block
around the mkdir -p $OUT/deps and cp to perform this presence check before
attempting cp so missing dependency JARs cause an immediate, descriptive
failure.
- Around line 111-121: The generated wrapper sets LD_LIBRARY_PATH as a plain
shell variable so it is not visible to the jazzer_driver process; change the
wrapper so LD_LIBRARY_PATH is exported (or apply it inline to the jazzer_driver
invocation) so the jazzer_driver sees the updated library path — update the
LD_LIBRARY_PATH assignment line inside the wrapper and either add an export for
LD_LIBRARY_PATH or prefix the jazzer_driver command with the LD_LIBRARY_PATH
assignment to ensure the variable is in the driver’s environment.

In @.github/workflows/ci.yml:
- Around line 388-391: The CI permissions are too broad for the Docker build
job; change the Docker job's permissions to use contents: read (keeping
id-token: write and attestations: write) and extract the release creation step
into a new tag-only job named e.g. release that runs on tags (if:
startsWith(github.ref, 'refs/tags/')), has needs: docker, and sets permissions:
contents: write so only that job can create GitHub Releases; move the existing
Create GitHub Release step into that new release job and ensure all other steps
remain under the reduced-permission docker job.
- Around line 546-552: The "Create GitHub Release" step currently sets
make_latest: true unconditionally; change the softprops/action-gh-release inputs
to set prerelease and make_latest based on the existing is-stable output (use
something like prerelease: ${{ !steps.<id>.outputs.is-stable }} and make_latest:
${{ steps.<id>.outputs.is-stable }}), so only stable semantic-version tags
become latest and tags with suffixes (RC, -beta, etc.) are flagged as
prerelease; update the step that uses softprops/action-gh-release (the Create
GitHub Release step) to reference the workflow step that produced is-stable for
these conditional inputs.

In @.github/workflows/clusterfuzzlite.yml:
- Around line 31-42: The pr-fuzzing and batch-fuzzing jobs call the
google/clusterfuzzlite/actions/build_fuzzers action without checking out the
repository and the jobs need explicit read access to repo contents; add a step
that runs actions/checkout@v3 (or `@v4`) before the Build Fuzzers step in each job
and set job-level permissions to include contents: read in addition to
security-events: write so build_fuzzers can access .clusterfuzzlite/*,
Dockerfile, build.sh and source files.

---

Nitpick comments:
In @.clusterfuzzlite/build.sh:
- Around line 10-111: The shell script uses unquoted path/glob variables causing
Shellcheck SC2086; update all uses of SRC, OUT, BUILD_CP, RUNTIME_CP and the
loop variable fuzzer to use quoted/brace-expanded forms (e.g. "$SRC", "$OUT",
"${BUILD_CP}", "$RUNTIME_CP", "${fuzzer}") and also quote them in compound
contexts (javac -cp "$BUILD_CP", cp -r "$SRC"/..., cat > "$OUT/${fuzzer}", cp
target/deps/*.jar "$OUT/deps/" etc.) so expansions are safe with spaces/globs
while preserving the existing behavior of
PathNavigatorFuzzer/MatchingUtilitiesFuzzer generation and wrapper creation.

In `@docs/changelog.md`:
- Around line 16-56: Add three standard changelog sections to this entry: a
"Files" block listing the new/changed files from the diff (e.g.,
.clusterfuzzlite/project.yaml, .clusterfuzzlite/Dockerfile,
.clusterfuzzlite/build.sh, .github/workflows/clusterfuzzlite.yml, CI/action pin
list), a "Design decisions" block summarizing key choices (use of jazzer_driver
and $this_dir-relative paths, try/catch in fuzz targets, pushing SLSA
attestations to Docker Hub, signed GitHub release strategy), and a "Next steps"
block with follow-ups (monitor fuzzing results, rotate pinned-action SHAs if
needed, verify attestation consumption, document container-only distribution).
Ensure headings match the changelog style ("Files", "Design decisions", "Next
steps") and place them under the existing entry for the 2026-04-23 OpenSSF
Scorecard item.
🪄 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

Run ID: 94b6ff06-2e53-483c-891a-53865c7056ff

📥 Commits

Reviewing files that changed from the base of the PR and between acdffb7 and 4603993.

📒 Files selected for processing (6)
  • .clusterfuzzlite/Dockerfile
  • .clusterfuzzlite/build.sh
  • .clusterfuzzlite/project.yaml
  • .github/workflows/ci.yml
  • .github/workflows/clusterfuzzlite.yml
  • docs/changelog.md

Comment thread .clusterfuzzlite/build.sh Outdated
Comment thread .clusterfuzzlite/build.sh
Comment thread .clusterfuzzlite/build.sh Outdated
Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/clusterfuzzlite.yml
Three root causes identified and fixed:

1. .dockerignore blocked build context: The repo .dockerignore starts with *
   (exclude-all). Added minimal allowlist entries for .clusterfuzzlite/ and
   src/main/java/.../utils/ so the CFL Dockerfile can access build.sh and
   the utility source files.

2. JDK version mismatch: Project requires Java 25 (maven.compiler.release=25)
   but base-builder-jvm ships Java 21. Eliminated Maven entirely — build.sh
   now compiles only the 3 needed source files directly with javac.

3. Java 22+ syntax incompatibility: Source files use unnamed variables
   (catch Exception _) which is a Java 22 feature. build.sh now copies
   sources to a staging dir and patches them with perl before compiling
   with -source/-target 21.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

♻️ Duplicate comments (2)
.clusterfuzzlite/build.sh (2)

61-68: ⚠️ Potential issue | 🟠 Major

Let Jazzer observe runtime exceptions from the APIs under test.

Both fuzz targets still swallow Exception, which hides the NPEs, bounds errors, and type errors fuzzing should surface. Remove the catch blocks or narrow them to explicitly expected exceptions only.

🐛 Proposed fix
     public static void fuzzerTestOneInput(FuzzedDataProvider data) {
         String path = data.consumeString(500);
-        try {
-            PathNavigator.getValue(path, SEED_DATA);
-        } catch (Exception ignored) {
-            // Expected — fuzzer explores error paths
-        }
+        PathNavigator.getValue(path, SEED_DATA);
     }
     public static void fuzzerTestOneInput(FuzzedDataProvider data) {
         String valuePath = data.consumeString(300);
         String equals = data.consumeBoolean() ? data.consumeString(100) : null;
         String contains = data.consumeBoolean() ? data.consumeString(100) : null;
-        try {
-            MatchingUtilities.executeValuePath(DATA, valuePath, equals, contains);
-        } catch (Exception ignored) {
-            // Expected — fuzzer explores error paths
-        }
+        MatchingUtilities.executeValuePath(DATA, valuePath, equals, contains);
     }

Also applies to: 92-100

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.clusterfuzzlite/build.sh around lines 61 - 68, The fuzzer target
fuzzerTestOneInput currently swallows all Exceptions around the call to
PathNavigator.getValue(path, SEED_DATA), hiding NPEs and other runtime errors;
remove the broad catch (or replace it with only specific expected exceptions) so
Jazzer can observe runtime exceptions, and apply the same change to the other
identical target around lines 92-100; specifically update the try/catch in
fuzzerTestOneInput to not catch Exception (or catch only the concrete expected
exception types) so runtime errors from PathNavigator.getValue surface to the
fuzzer.

119-128: ⚠️ Potential issue | 🟠 Major

Make the generated wrapper discoverable and pass LD_LIBRARY_PATH to Jazzer.

The wrapper still sets LD_LIBRARY_PATH as an unexported shell variable, so jazzer_driver may not receive it. Also add the CFL JVM wrapper detection marker used by the documented example. Source: ClusterFuzzLite JVM integration docs.

🛠️ Proposed fix
 #!/bin/bash
+# LLVMFuzzerTestOneInput for fuzzer detection.
 this_dir=\$(dirname "\$0")
-LD_LIBRARY_PATH="\${JVM_LD_LIBRARY_PATH:-}":\$this_dir
-\$this_dir/jazzer_driver \\
+LD_LIBRARY_PATH="\${JVM_LD_LIBRARY_PATH:-}:\$this_dir" \\
+"\$this_dir/jazzer_driver" \\
     --agent_path=\$this_dir/jazzer_agent_deploy.jar \\
     --cp=${RUNTIME_CP} \\
     --target_class=${fuzzer} \\
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.clusterfuzzlite/build.sh around lines 119 - 128, The generated wrapper
currently sets LD_LIBRARY_PATH as a shell variable
(LD_LIBRARY_PATH="...":$this_dir) so jazzer_driver won't see it and it lacks the
CFL JVM wrapper detection marker; update the template written in build.sh so the
wrapper exports LD_LIBRARY_PATH (e.g., export
LD_LIBRARY_PATH="${JVM_LD_LIBRARY_PATH:-}":$this_dir) before calling
jazzer_driver and add the ClusterFuzzLite JVM wrapper detection marker (e.g.,
export CFL_JVM_WRAPPER=1) near the top of the wrapper; modify the heredoc that
creates the ${fuzzer} wrapper (the block that writes the bash stub invoking
jazzer_driver) to include these two exports.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.clusterfuzzlite/build.sh:
- Around line 106-110: The javac invocation compiling PathNavigatorFuzzer.java
and MatchingUtilitiesFuzzer.java omits the Jazzer API jar, causing missing
FuzzedDataProvider symbols; update the javac classpath used in the build script
(the javac command that compiles PathNavigatorFuzzer.java and
MatchingUtilitiesFuzzer.java) to include $JAZZER_API_PATH in addition to
$OUT/classes so the Jazzer API is available at compile time.

---

Duplicate comments:
In @.clusterfuzzlite/build.sh:
- Around line 61-68: The fuzzer target fuzzerTestOneInput currently swallows all
Exceptions around the call to PathNavigator.getValue(path, SEED_DATA), hiding
NPEs and other runtime errors; remove the broad catch (or replace it with only
specific expected exceptions) so Jazzer can observe runtime exceptions, and
apply the same change to the other identical target around lines 92-100;
specifically update the try/catch in fuzzerTestOneInput to not catch Exception
(or catch only the concrete expected exception types) so runtime errors from
PathNavigator.getValue surface to the fuzzer.
- Around line 119-128: The generated wrapper currently sets LD_LIBRARY_PATH as a
shell variable (LD_LIBRARY_PATH="...":$this_dir) so jazzer_driver won't see it
and it lacks the CFL JVM wrapper detection marker; update the template written
in build.sh so the wrapper exports LD_LIBRARY_PATH (e.g., export
LD_LIBRARY_PATH="${JVM_LD_LIBRARY_PATH:-}":$this_dir) before calling
jazzer_driver and add the ClusterFuzzLite JVM wrapper detection marker (e.g.,
export CFL_JVM_WRAPPER=1) near the top of the wrapper; modify the heredoc that
creates the ${fuzzer} wrapper (the block that writes the bash stub invoking
jazzer_driver) to include these two exports.
🪄 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

Run ID: 6e53ecc0-7c2c-418f-a0af-a80ab7280b3f

📥 Commits

Reviewing files that changed from the base of the PR and between 4603993 and b74bac2.

📒 Files selected for processing (3)
  • .clusterfuzzlite/Dockerfile
  • .clusterfuzzlite/build.sh
  • .dockerignore
✅ Files skipped from review due to trivial changes (2)
  • .dockerignore
  • .clusterfuzzlite/Dockerfile

Comment thread .clusterfuzzlite/build.sh Outdated
ClusterFuzzLite:
- Vendor utility .java files into .clusterfuzzlite/ to avoid Docker
  context issues (parent directory un-ignore is fragile in .dockerignore)
- Remove src/ exceptions from .dockerignore — zero production impact
- Auto-detect JDK version (17 or 21) instead of hardcoding --release
- Use --release instead of deprecated -source/-target pair
- Add  to fuzz target compilation classpath (was missing)
- Narrow perl regex to only catch blocks: \bcatch\s*\(\s*(\w+)\s+_\s*\)
  to prevent false positives on lambda/method unnamed parameters

Integration tests:
- Verify sendUserInput response (assert 200 + steps) before undo/redo
- Extract retryUntilOk() helper into BaseIntegrationIT for reuse
- Undo/redo use retry loop with 200ms backoff for Postgres visibility lag
- redoAfterUndo now asserts undo success before attempting redo
Comment thread src/test/java/ai/labs/eddi/integration/BaseIntegrationIT.java Fixed
ginccc added 3 commits April 23, 2026 14:06
The base-builder-jvm image defaults to US-ASCII locale. The vendored
PathNavigator.java contains em-dash characters in comments which cause
'unmappable character' errors. Adding -encoding UTF-8 resolves this.
…export LD_LIBRARY_PATH

- Add keep-unaffected-fuzz-targets: true to PR build step so vendored-
  copy PRs don't get all targets stripped (fixes 'No fuzz targets found')
- Narrow catch blocks: only catch IllegalArgumentException and
  StackOverflowError — let Jazzer detect NPE, IOOB, ClassCastException
- Export LD_LIBRARY_PATH in wrapper scripts so jazzer_driver inherits it
The build succeeds (all javac compilations pass) but the post-build
validation fails with 'No fuzz targets found'. Adding ls/file/grep
diagnostics to understand what  looks like after compilation.
Temporarily disabling bad-build-check to let the run step proceed.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/test/java/ai/labs/eddi/integration/BaseIntegrationIT.java (1)

271-281: ⚠️ Potential issue | 🟡 Minor

Assert the last response instead of issuing an extra retry.

Line 281 re-executes the supplied call after the 10 retry attempts, which makes this helper perform an 11th request and can re-run mutating POSTs such as undo/redo. Keep the last response and use description in the failure message instead.

Proposed fix
     protected void retryUntilOk(java.util.function.Supplier<Response> call, String description)
             throws InterruptedException {
+        Response lastResponse = null;
         for (int i = 0; i < 10; i++) {
-            Response response = call.get();
-            if (response.statusCode() == 200) {
+            lastResponse = call.get();
+            if (lastResponse.statusCode() == 200) {
                 return;
             }
             Thread.sleep(200);
         }
         // Final attempt — will fail with assertion if still not OK
-        call.get().then().assertThat().statusCode(200);
+        org.junit.jupiter.api.Assertions.fail(String.format(
+                "%s did not return HTTP 200 after retries. Last status=%d, body=%s",
+                description, lastResponse.statusCode(), lastResponse.getBody().asString()));
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/ai/labs/eddi/integration/BaseIntegrationIT.java` around lines
271 - 281, The helper method retryUntilOk is making an extra 11th request by
calling call.get() after the retry loop; change it to retain the last Response
(from the final loop iteration) and assert on its statusCode instead of
re-invoking call.get(), using the provided description in the failure/assertion
message; update references in retryUntilOk so the Response variable is declared
outside the loop, assigned inside each iteration, and used after the loop to
fail with a clear message including description when statusCode() != 200.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.clusterfuzzlite/MatchingUtilities.java:
- Around line 19-33: The matching logic in MatchingUtilities (variables/methods:
value, equals, contains, isNullOrEmpty, success; PathNavigator.getValue)
mishandles non-String/non-List contains checks, uses exact-equality for
List.contains, and lets a Boolean result override an explicit equals mismatch;
fix by: 1) when equals is non-empty only consider success true if
equals.equals(value.toString()) and otherwise set success=false and skip other
branches (do not fall through to the Boolean branch); 2) for contains, treat
non-String/non-List values by calling value.toString().contains(contains); 3)
for List<?> l, iterate elements and treat an element as a match if element !=
null && element.toString().contains(contains) (rather than
l.contains(contains)); update the branches in the method so equals has priority,
contains uses stringified-substring semantics for all element types, and Boolean
handling only runs when both equals and contains are empty.

In @.clusterfuzzlite/PathNavigator.java:
- Around line 107-121: The setValue write path performs unchecked casts and
mutating operations that can throw
UnsupportedOperationException/ClassCastException/ArrayStoreException (notably
when updating l via ((List<Object>) l).set(...) and updating current via
((Map<String,Object>) current).put(...)). Modify setValue to perform the
mutations inside guarded try/catch blocks: when you detect a List<?> l from
parentMap.get(key), parse the index and then call set inside a try that catches
UnsupportedOperationException, ClassCastException, ArrayStoreException (and
NumberFormatException for parsing) and silently ignores failures (preserving the
class's "invalid paths silently ignored" behavior); similarly, when current is a
Map<?,?> use a safe put wrapped in a try that catches
UnsupportedOperationException and ClassCastException and ignores them instead of
letting them propagate. Use the existing symbols parentMap, l, index, key and
current to locate the spots to wrap.

---

Duplicate comments:
In `@src/test/java/ai/labs/eddi/integration/BaseIntegrationIT.java`:
- Around line 271-281: The helper method retryUntilOk is making an extra 11th
request by calling call.get() after the retry loop; change it to retain the last
Response (from the final loop iteration) and assert on its statusCode instead of
re-invoking call.get(), using the provided description in the failure/assertion
message; update references in retryUntilOk so the Response variable is declared
outside the loop, assigned inside each iteration, and used after the loop to
fail with a clear message including description when statusCode() != 200.
🪄 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

Run ID: 31ebd70f-dcda-4368-9fbe-c2c848b58282

📥 Commits

Reviewing files that changed from the base of the PR and between b74bac2 and 306ba07.

📒 Files selected for processing (9)
  • .clusterfuzzlite/Dockerfile
  • .clusterfuzzlite/MatchingUtilities.java
  • .clusterfuzzlite/PathNavigator.java
  • .clusterfuzzlite/RuntimeUtilities.java
  • .clusterfuzzlite/build.sh
  • .dockerignore
  • .github/workflows/clusterfuzzlite.yml
  • src/test/java/ai/labs/eddi/integration/BaseIntegrationIT.java
  • src/test/java/ai/labs/eddi/integration/ConversationServiceComponentIT.java
✅ Files skipped from review due to trivial changes (3)
  • .dockerignore
  • .clusterfuzzlite/RuntimeUtilities.java
  • .github/workflows/clusterfuzzlite.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .clusterfuzzlite/Dockerfile

Comment thread .clusterfuzzlite/MatchingUtilities.java
Comment thread .clusterfuzzlite/PathNavigator.java
ginccc added 3 commits April 23, 2026 15:42
Root cause: both run_fuzzers steps defaulted to language: c++ which
looks for ELF binaries with LLVMFuzzerTestOneInput. JVM fuzz targets
are shell wrapper scripts — only detected when language: jvm is set.

Also re-enabled bad-build-check and removed debug diagnostics.
The bad-build-check scans wrapper scripts for the string
'LLVMFuzzerTestOneInput' to detect valid fuzz targets. Without it,
JVM shell wrappers are invisible to the checker.

Adapted from google/oss-fuzz/projects/json-sanitizer/build.sh:
- Added '# LLVMFuzzerTestOneInput for fuzzer detection.' comment
- Use LD_LIBRARY_PATH as command prefix (not separate export)
- Add memory settings based on -runs flag
- Re-enabled bad-build-check (was incorrectly disabled)
The description parameter was unused — now passed to Hamcrest's
describedAs matcher so test failures show which operation was
being retried. Also replaced FQN with proper import.
Comment thread .clusterfuzzlite/MatchingUtilities.java
@ginccc ginccc merged commit 543e81b into main Apr 23, 2026
24 checks passed
@ginccc ginccc deleted the chore/scorecard-improvements branch April 23, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants