Skip to content

refactor: extract cora-review to standalone workflow + harden action v2#107

Merged
ajianaz merged 4 commits into
developfrom
chore/cora-review-v2
Jun 1, 2026
Merged

refactor: extract cora-review to standalone workflow + harden action v2#107
ajianaz merged 4 commits into
developfrom
chore/cora-review-v2

Conversation

@ajianaz
Copy link
Copy Markdown
Collaborator

@ajianaz ajianaz commented Jun 1, 2026

Changes

Extract cora-review from ci.yml into standalone cora-review.yml workflow and upgrade action to v2.

Action v2 improvements

  • SHA-pin all third-party actions (Infisical, codeql, github-script)
  • Add checksum verification on binary download
  • Env var indirection for shell args (prevent injection)
  • Fallback version bumped to v0.1.7

Workflow changes

  • New standalone cora-review.yml with concurrency control + timeout
  • Remove cora-review job from ci.yml (no longer needs rust-toolchain/cache)
  • Checkout v5.0.0 with persist-credentials: false

Summary by CodeRabbit

  • Chores
    • Refactored code review workflow to run on dedicated triggers instead of in main CI pipeline
    • Enhanced security verification with SHA-256 checksum validation
    • Improved error handling and logging for review diagnostics
    • Better detection logic to distinguish between failed reviews and reviews with no issues found

CTO Hermes added 2 commits June 1, 2026 16:25
…ection

- Capture cora stderr to log file instead of suppressing (2>/dev/null)
- Forward stderr as GitHub ::warning:: annotation
- Detect empty SARIF output (<10 bytes) and warn instead of false 'No issues'
- Bump fallback version v0.1.6 → v0.1.7
Action v2 improvements:
- SHA-pin all third-party actions (Infisical, codeql, github-script)
- Add checksum verification on binary download
- Env var indirection for shell args (prevent injection)
- Concurrency control + timeout in standalone workflow
- Fallback version bumped to v0.1.7

Workflow:
- Extract from ci.yml to standalone cora-review.yml
- Remove unnecessary rust-toolchain/cache from review job
- Add timeout-minutes: 10
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Warning

Review limit reached

@ajianaz, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 50 minutes and 17 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 628dd011-9873-4e6a-b96f-72d6fa1252d5

📥 Commits

Reviewing files that changed from the base of the PR and between ecf9458 and 50a09a3.

📒 Files selected for processing (1)
  • .github/actions/cora-review/action.yml
📝 Walkthrough

Walkthrough

The PR reorganizes cora-review execution from the main CI pipeline to a standalone workflow, hardens external action dependencies via commit pinning, adds SHA-256 verification to cora-cli installation, refactors version resolution using environment variables, improves diagnostics by capturing stderr and using file-size heuristics for output interpretation, and updates the fallback cora-cli version.

Changes

Cora Review Automation: Hardening, Installation Verification, and Workflow Isolation

Layer / File(s) Summary
Workflow Reorganization
.github/workflows/ci.yml, .github/workflows/cora-review.yml
Removes the cora-review job from the main CI workflow and introduces a new dedicated GitHub Actions workflow that triggers on develop pull requests with independent concurrency control, scoped permissions, and isolated job execution.
External Action Pinning and Dependency Hardening
.github/actions/cora-review/action.yml
Pins Infisical/secrets-action, upload-sarif, and github-script from floating version tags to specific commit SHAs for supply-chain security and reproducibility.
cora-cli Version Resolution and Installation Verification
.github/actions/cora-review/action.yml
Refactors version resolution to read from INPUT_VERSION environment variable, updates the fallback "latest" version from v0.1.6 to v0.1.7, and replaces direct tarball extraction with a download-plus-SHA-256-verify flow before binary placement.
Review Execution and Output Diagnostics
.github/actions/cora-review/action.yml
Updates cora review invocation to pass base branch and severity via environment variables, captures stderr to cora-stderr.log with completion and warning logging, refines empty-output handling by checking on-disk SARIF file size to distinguish "could not complete" from "no issues found," and removes an inline code comment.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ajianaz/cora-cli#53: Both PRs modify .github/actions/cora-review/action.yml to refactor how cora-cli version is resolved at runtime (PR #53 adds "latest" via GitHub API, while this PR refactors version handling via environment variables and updates the default fallback).
  • ajianaz/cora-cli#46: Builds directly on the composite-action extraction introduced in PR #46 by further hardening action dependencies, improving cora-cli installation reliability, and refining output diagnostics in the existing ./.github/actions/cora-review/ structure.

Poem

🐰 A rabbit hops through CI's bustling lane,
Now cora-cli verifies with checksums' chain,
Workflows split clean, dependencies pinned tight,
Diagnostics shine bright—no stderr left to blight!
Security hardened, our review stays in sight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: extracting cora-review to a standalone workflow and hardening the action with security improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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/cora-review-v2

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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

🔍 Cora AI Code Review

Blocked — critical issues found.

🔴 Error (1)

  • .github/actions/cora-review/action.yml:121 — The || true after the cora review command means that if cora crashes or fails entirely, the workflow continues as if it succeeded. Combined with the empty SARIF check, a crash would produce a misleading "Review could not complete" comment rather than failing the job. This hides real failures from developers.

Review powered by cora-cli · BYOK · MIT

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/actions/cora-review/action.yml (1)

58-70: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix retry/fallback logic for resolving cora-cli “latest”

File: .github/actions/cora-review/action.yml
Lines: 58-70

The retry/fallback path can exit on the first failed lookup: shell: bash steps are run with -e, and if curl -sfL fails the subsequent python3 (parsing empty/invalid JSON) exits non-zero, causing the step to terminate before the loop can reach Attempt $i failed... and the v0.1.7 fallback.

Suggested fix
         if [ "$INPUT_VERSION" = "latest" ]; then
+          VERSION=""
           for i in 1 2 3; do
-            VERSION=$(curl -sfL --connect-timeout 10 \
-              https://api.github.com/repos/ajianaz/cora-cli/releases/latest \
-              | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tag_name', ''))" 2>/dev/null)
-            if [ -n "$VERSION" ]; then
-              break
+            if VERSION=$(
+              curl -sfL --connect-timeout 10 \
+                https://api.github.com/repos/ajianaz/cora-cli/releases/latest \
+                | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tag_name', ''))" 2>/dev/null
+            ); then
+              if [ -n "$VERSION" ]; then
+                break
+              fi
             fi
             echo "Attempt $i failed, retrying..."
             sleep 5
           done
🤖 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/actions/cora-review/action.yml around lines 58 - 70, The loop that
resolves INPUT_VERSION="latest" can abort early because the pipeline `curl ... |
python3 -c ...` can exit non-zero under `-e`; change the resolution step so
failures don't kill the step — e.g., capture curl output to a temp variable or
file then run the json parse with `|| true` (or run the pipeline in a subshell
with `set +e`) and assign VERSION only if parse succeeds; ensure the loop still
hits the echo "Attempt $i failed, retrying..." and the fallback to v0.1.7 when
VERSION remains empty. Reference the existing INPUT_VERSION check and the
VERSION assignment inside the retry for where to apply this change.
🧹 Nitpick comments (1)
.github/workflows/cora-review.yml (1)

3-6: 💤 Low value

Consider gating on non-draft PRs.

ready_for_review is included, but opened and synchronize still fire on draft PRs, so reviews will run while a PR is still a draft. If that's not intended, add a draft guard at the job level:

♻️ Optional: skip drafts
 jobs:
   cora-review:
     name: Cora Review
     runs-on: ubuntu-latest
     timeout-minutes: 10
+    if: github.event.pull_request.draft == false
     steps:
🤖 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/cora-review.yml around lines 3 - 6, The workflow currently
triggers on pull_request types [opened, synchronize, ready_for_review,
reopened], which means it will run for draft PRs when opened/synchronized;
update the pull_request gating so drafts are skipped by adding a job-level guard
that checks the PR draft flag (use the GitHub context: add an if condition like
"if: github.event.pull_request.draft == false" on the top-level job(s) that run
the review), or alternately adjust the trigger types to only include non-draft
transitions; reference the existing on: pull_request and types: [opened,
synchronize, ready_for_review, reopened] entries and add the if:
github.event.pull_request.draft == false guard to desired jobs.
🤖 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/actions/cora-review/action.yml:
- Around line 162-172: The current logic only checks fileSize and sets body to a
clean pass when cora-results.sarif > 10 bytes; instead, read and attempt to
parse the SARIF content (fs.readFileSync('cora-results.sarif','utf8') and
JSON.parse) and if JSON.parse throws or the parsed object lacks expected SARIF
structure (e.g., no "runs" array or malformed "runs[*].results") then set body
to the failure message (same as when fileSize < 10); update the branch that
currently uses fileSize and the body variable so parse errors or missing fields
produce the "Review could not complete" message rather than "No issues found."
- Around line 132-134: The workflow currently emits raw cora-stderr.log via the
command echo "::warning::Cora stderr: $(cat cora-stderr.log)", which can be
interpreted as additional workflow commands; replace that emission with a safe
approach: either upload cora-stderr.log as an artifact or sanitize/escape the
file contents before sending them to the workflow-command annotation.
Specifically, update the block that checks cora-stderr.log (the if that contains
echo "::warning::Cora stderr: $(cat cora-stderr.log)") to avoid injecting raw
file contents into a workflow command—escape percent/newline/carriage-return and
any literal "::" sequences when constructing the ::warning:: annotation or
switch to artifact upload so the raw stderr is not parsed by the runner.
- Around line 93-108: The current download step can silently produce HTML error
pages because curl is run with -sL; change the download logic to make HTTP
errors fail and verify the files are real: use curl with fail+show-error (e.g.,
-fSLo) when fetching the tarball and checksums, check curl's exit status after
each download, and ensure /tmp/cora.tar.gz and /tmp/cora-checksums.txt exist and
are non-empty before proceeding; if the checksums download failed (empty or curl
non-zero) treat it as an error instead of emitting a warning, and continue to
compute EXPECTED/ACTUAL only when the checksum file is valid (use CORA_VERSION,
ASSET, /tmp/cora.tar.gz and /tmp/cora-checksums.txt to locate the relevant
checks).

---

Outside diff comments:
In @.github/actions/cora-review/action.yml:
- Around line 58-70: The loop that resolves INPUT_VERSION="latest" can abort
early because the pipeline `curl ... | python3 -c ...` can exit non-zero under
`-e`; change the resolution step so failures don't kill the step — e.g., capture
curl output to a temp variable or file then run the json parse with `|| true`
(or run the pipeline in a subshell with `set +e`) and assign VERSION only if
parse succeeds; ensure the loop still hits the echo "Attempt $i failed,
retrying..." and the fallback to v0.1.7 when VERSION remains empty. Reference
the existing INPUT_VERSION check and the VERSION assignment inside the retry for
where to apply this change.

---

Nitpick comments:
In @.github/workflows/cora-review.yml:
- Around line 3-6: The workflow currently triggers on pull_request types
[opened, synchronize, ready_for_review, reopened], which means it will run for
draft PRs when opened/synchronized; update the pull_request gating so drafts are
skipped by adding a job-level guard that checks the PR draft flag (use the
GitHub context: add an if condition like "if: github.event.pull_request.draft ==
false" on the top-level job(s) that run the review), or alternately adjust the
trigger types to only include non-draft transitions; reference the existing on:
pull_request and types: [opened, synchronize, ready_for_review, reopened]
entries and add the if: github.event.pull_request.draft == false guard to
desired jobs.
🪄 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: 2556fd50-7056-4ca7-9b39-d5d6880b7970

📥 Commits

Reviewing files that changed from the base of the PR and between b0686c4 and ecf9458.

📒 Files selected for processing (3)
  • .github/actions/cora-review/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/cora-review.yml
💤 Files with no reviewable changes (1)
  • .github/workflows/ci.yml

Comment on lines +93 to +108
curl -sL "https://github.com/ajianaz/cora-cli/releases/download/${CORA_VERSION}/${ASSET}-${CORA_VERSION}.tar.gz" \
-o /tmp/cora.tar.gz
curl -sL "https://github.com/ajianaz/cora-cli/releases/download/${CORA_VERSION}/checksums-sha256.txt" \
-o /tmp/cora-checksums.txt || true
if [ -f /tmp/cora-checksums.txt ]; then
EXPECTED=$(grep "${ASSET}-${CORA_VERSION}.tar.gz" /tmp/cora-checksums.txt | awk '{print $1}')
ACTUAL=$(sha256sum /tmp/cora.tar.gz | awk '{print $1}')
if [ -n "$EXPECTED" ] && [ "$EXPECTED" != "$ACTUAL" ]; then
echo "::error::Checksum verification failed for ${ASSET}-${CORA_VERSION}.tar.gz"
echo "Expected: $EXPECTED"
echo "Actual: $ACTUAL"
exit 1
fi
rm -f /tmp/cora-checksums.txt
else
echo "::warning::No checksums file found, skipping verification"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
ls -la .github/actions/cora-review || true
sed -n '1,200p' .github/actions/cora-review/action.yml

Repository: ajianaz/cora-cli

Length of output: 8098


🏁 Script executed:

rg -n "curl -sL|checksums-sha256\.txt|tar xzf /tmp/cora\.tar\.gz" -S .github/actions/cora-review/action.yml

Repository: ajianaz/cora-cli

Length of output: 361


🏁 Script executed:

rg -n "curl -sL|checksums-sha256\.txt|tar xzf /tmp/cora\.tar\.gz" .github/actions/cora-review/action.yml

Repository: ajianaz/cora-cli

Length of output: 361


🏁 Script executed:

rg -n "curl -sL|checksums-sha256\.txt|tar xzf /tmp/cora\.tar\.gz" .github/actions/cora-review/action.yml

Repository: ajianaz/cora-cli

Length of output: 361


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "curl -sL|checksums-sha256\.txt|tar xzf /tmp/cora\.tar\.gz" .github/actions/cora-review/action.yml

Repository: ajianaz/cora-cli

Length of output: 361


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "curl -sL|checksums-sha256\.txt|tar xzf /tmp/cora\.tar\.gz" .github/actions/cora-review/action.yml

Repository: ajianaz/cora-cli

Length of output: 361


Fail cora asset downloads on HTTP errors (current curl -sL can silently write error pages).

.github/actions/cora-review/action.yml uses curl -sL to download both the tarball and checksums-sha256.txt. If GitHub returns 404/500, curl can still create /tmp/cora.tar.gz and /tmp/cora-checksums.txt; because verification only errors when EXPECTED is non-empty, a bogus/empty EXPECTED can skip checksum validation and the workflow may fail later during tar.

Suggested fix
-        curl -sL "https://github.com/ajianaz/cora-cli/releases/download/${CORA_VERSION}/${ASSET}-${CORA_VERSION}.tar.gz" \
+        curl -sfL --retry 3 --retry-delay 5 "https://github.com/ajianaz/cora-cli/releases/download/${CORA_VERSION}/${ASSET}-${CORA_VERSION}.tar.gz" \
           -o /tmp/cora.tar.gz
-        curl -sL "https://github.com/ajianaz/cora-cli/releases/download/${CORA_VERSION}/checksums-sha256.txt" \
-          -o /tmp/cora-checksums.txt || true
-        if [ -f /tmp/cora-checksums.txt ]; then
+        if curl -sfL --retry 3 --retry-delay 5 "https://github.com/ajianaz/cora-cli/releases/download/${CORA_VERSION}/checksums-sha256.txt" \
+          -o /tmp/cora-checksums.txt; then
           EXPECTED=$(grep "${ASSET}-${CORA_VERSION}.tar.gz" /tmp/cora-checksums.txt | awk '{print $1}')
+          if [ -z "$EXPECTED" ]; then
+            echo "::error::Missing checksum entry for ${ASSET}-${CORA_VERSION}.tar.gz"
+            exit 1
+          fi
           ACTUAL=$(sha256sum /tmp/cora.tar.gz | awk '{print $1}')
           if [ -n "$EXPECTED" ] && [ "$EXPECTED" != "$ACTUAL" ]; then
🤖 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/actions/cora-review/action.yml around lines 93 - 108, The current
download step can silently produce HTML error pages because curl is run with
-sL; change the download logic to make HTTP errors fail and verify the files are
real: use curl with fail+show-error (e.g., -fSLo) when fetching the tarball and
checksums, check curl's exit status after each download, and ensure
/tmp/cora.tar.gz and /tmp/cora-checksums.txt exist and are non-empty before
proceeding; if the checksums download failed (empty or curl non-zero) treat it
as an error instead of emitting a warning, and continue to compute
EXPECTED/ACTUAL only when the checksum file is valid (use CORA_VERSION, ASSET,
/tmp/cora.tar.gz and /tmp/cora-checksums.txt to locate the relevant checks).

Comment on lines +132 to +134
if [ -s cora-stderr.log ]; then
echo "::warning::Cora stderr: $(cat cora-stderr.log)"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/actions/cora-review/action.yml"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
  echo "MISSING: $FILE"
  exit 1
fi

# Show line range around 120-150
nl -ba "$FILE" | sed -n '110,170p'

# Search for cora-stderr usage
echo "== rg cora-stderr.log =="
rg -n "cora-stderr\.log" -S .github/actions/cora-review/action.yml .github/actions || true

Repository: ajianaz/cora-cli

Length of output: 173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/actions/cora-review/action.yml"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
  echo "MISSING: $FILE"
  exit 1
fi

# Show line range around 120-170 (covers 132-134)
nl -ba "$FILE" | sed -n '110,170p'

echo "== rg cora-stderr.log (broader context) =="
rg -n "cora-stderr\.log" -S .github/actions || true

echo "== rg for '::warning::Cora stderr' =="
rg -n "::warning::Cora stderr" -S .github/actions || true

Repository: ajianaz/cora-cli

Length of output: 173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/actions/cora-review/action.yml"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
  echo "MISSING: $FILE"
  exit 1
fi

echo "== Lines 110-170 =="
cat -n "$FILE" | sed -n '110,170p'

echo "== rg cora-stderr.log (action dir) =="
rg -n "cora-stderr\.log" -S .github/actions || true

echo "== rg ::warning::Cora stderr =="
rg -n "::warning::Cora stderr" -S .github/actions || true

Repository: ajianaz/cora-cli

Length of output: 3255


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/actions/cora-review/action.yml"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
  echo "MISSING: $FILE"
  exit 1
fi

echo "== Lines 110-170 =="
cat -n "$FILE" | sed -n '110,170p'

echo "== rg cora-stderr.log (action dir) =="
rg -n "cora-stderr\.log" -S .github/actions || true

echo "== rg ::warning::Cora stderr =="
rg -n "::warning::Cora stderr" -S .github/actions || true

Repository: ajianaz/cora-cli

Length of output: 3255


🌐 Web query:

GitHub Actions workflow command ::stop-commands::and matching:::: syntax how it works

💡 Result:

The GitHub Actions workflow command::stop-commands:: is used to disable the processing of subsequent workflow commands, preventing the runner from interpreting them as instructions [1]. The is a unique, randomly generated token that acts as a key to both stop and resume command processing [1][2]. How it works: 1. Disabling commands: When you execute echo "::stop-commands::", the runner stops parsing any following output for workflow commands [1]. This is useful when you need to print text to the logs that happens to contain patterns that look like GitHub Actions commands (e.g., scripts with comments) and you want to ensure they are not accidentally executed by the runner [1]. 2. Resuming commands: To re-enable command processing, you must output the exact same token using the syntax:::: [1]. This tells the runner to resume parsing the workflow output for commands [1]. Best Practices: - Unique tokens: Always use a randomly generated, unique token for each workflow run (e.g., using uuidgen or a language-specific random generator) to ensure security and prevent accidental re-enabling of commands [1]. - Masking: Because the token used to stop commands is echoed to the logs, it is recommended to mask the token using::add-mask:: if you want to keep the token itself hidden from the log output [3]. Example: # Generate a unique token stopMarker=$(uuidgen) # Mask the token for security echo "::add-mask::$stopMarker" # Disable command processing echo "::stop-commands::$stopMarker" # The following will NOT be processed as commands echo "::warning:: This will not be rendered as a warning" # Resume command processing echo "::$stopMarker::" # Commands are processed normally again echo "::warning:: This will be rendered as a warning"

Citations:


Don't emit raw cora-stderr.log inside a workflow command in .github/actions/cora-review/action.yml (lines 132-134): echo "::warning::Cora stderr: $(cat cora-stderr.log)" prints untrusted stderr directly in workflow-command format, so any ::...::... content coming from cora-stderr.log can be parsed as additional workflow commands by the runner.

Suggested fix
         if [ -s cora-stderr.log ]; then
-          echo "::warning::Cora stderr: $(cat cora-stderr.log)"
+          stop_marker=$(python3 - <<'PY'
+import uuid
+print(uuid.uuid4())
+PY
+)
+          echo "::warning::Cora emitted stderr; see grouped log output below."
+          echo "::group::Cora stderr"
+          echo "::stop-commands::$stop_marker"
+          cat cora-stderr.log
+          echo "::$stop_marker::"
+          echo "::endgroup::"
         fi
📝 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
if [ -s cora-stderr.log ]; then
echo "::warning::Cora stderr: $(cat cora-stderr.log)"
fi
if [ -s cora-stderr.log ]; then
stop_marker=$(python3 - <<'PY'
import uuid
print(uuid.uuid4())
PY
)
echo "::warning::Cora emitted stderr; see grouped log output below."
echo "::group::Cora stderr"
echo "::stop-commands::$stop_marker"
cat cora-stderr.log
echo "::$stop_marker::"
echo "::endgroup::"
fi
🤖 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/actions/cora-review/action.yml around lines 132 - 134, The workflow
currently emits raw cora-stderr.log via the command echo "::warning::Cora
stderr: $(cat cora-stderr.log)", which can be interpreted as additional workflow
commands; replace that emission with a safe approach: either upload
cora-stderr.log as an artifact or sanitize/escape the file contents before
sending them to the workflow-command annotation. Specifically, update the block
that checks cora-stderr.log (the if that contains echo "::warning::Cora stderr:
$(cat cora-stderr.log)") to avoid injecting raw file contents into a workflow
command—escape percent/newline/carriage-return and any literal "::" sequences
when constructing the ::warning:: annotation or switch to artifact upload so the
raw stderr is not parsed by the runner.

Comment on lines +162 to +172
let fileSize = 0;
try {
fileSize = fs.statSync('cora-results.sarif').size;
} catch (e) {
fileSize = 0;
}
if (fileSize < 10) {
body = `## 🔍 Cora AI Code Review\n\n⚠️ **Review could not complete.** Cora produced an empty result. Check the workflow logs for errors.\n\n---\n_Review powered by [cora-cli](https://github.com/ajianaz/cora-cli) · BYOK · MIT_`;
} else {
body = `## 🔍 Cora AI Code Review\n\n✅ **No issues found.** Code looks good!\n\n---\n_Review powered by [cora-cli](https://github.com/ajianaz/cora-cli) · BYOK · MIT_`;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Malformed non-empty SARIF is reported as a clean pass.

If parsing fails but cora-results.sarif is larger than 10 bytes, this branch posts “No issues found.” A truncated or otherwise invalid SARIF file should still be treated as a failed review, otherwise scanner failures surface as a false green.

Suggested fix
-          let sarifContent;
+          let sarifContent;
+          let sarifParseFailed = false;
           try {
             sarifContent = JSON.parse(fs.readFileSync('cora-results.sarif', 'utf8'));
           } catch (e) {
             sarifContent = null;
+            sarifParseFailed = true;
           }
@@
-          if (!sarifContent || !sarifContent.runs || sarifContent.runs.length === 0) {
+          if (!sarifContent || !sarifContent.runs || sarifContent.runs.length === 0) {
             let fileSize = 0;
             try {
               fileSize = fs.statSync('cora-results.sarif').size;
             } catch (e) {
               fileSize = 0;
             }
-            if (fileSize < 10) {
+            if (sarifParseFailed || fileSize < 10) {
               body = `## 🔍 Cora AI Code Review\n\n⚠️ **Review could not complete.** Cora produced an empty result. Check the workflow logs for errors.\n\n---\n_Review powered by [cora-cli](https://github.com/ajianaz/cora-cli) · BYOK · MIT_`;
             } else {
               body = `## 🔍 Cora AI Code Review\n\n✅ **No issues found.** Code looks good!\n\n---\n_Review powered by [cora-cli](https://github.com/ajianaz/cora-cli) · BYOK · MIT_`;
             }
🤖 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/actions/cora-review/action.yml around lines 162 - 172, The current
logic only checks fileSize and sets body to a clean pass when cora-results.sarif
> 10 bytes; instead, read and attempt to parse the SARIF content
(fs.readFileSync('cora-results.sarif','utf8') and JSON.parse) and if JSON.parse
throws or the parsed object lacks expected SARIF structure (e.g., no "runs"
array or malformed "runs[*].results") then set body to the failure message (same
as when fileSize < 10); update the branch that currently uses fileSize and the
body variable so parse errors or missing fields produce the "Review could not
complete" message rather than "No issues found."

@ajianaz ajianaz merged commit 4e21db7 into develop Jun 1, 2026
8 checks passed
@ajianaz ajianaz deleted the chore/cora-review-v2 branch June 1, 2026 14:54
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.

1 participant