Skip to content

fix(ci): reconcile vulnerability findings with Linear#1505

Merged
msukkari merged 1 commit into
mainfrom
msukkari/vulnerability-linear-reconciliation
Jul 24, 2026
Merged

fix(ci): reconcile vulnerability findings with Linear#1505
msukkari merged 1 commit into
mainfrom
msukkari/vulnerability-linear-reconciliation

Conversation

@msukkari

@msukkari msukkari commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Make vulnerability-to-Linear reconciliation exact, fail-closed, and bidirectional.

  • Create a Linear issue only when a current repository finding has no exact existing issue.
  • Leave an existing active issue unchanged.
  • Reopen completed or canceled issues when the same finding is still present.
  • Preserve issues explicitly marked Duplicate rather than reopening or recreating them.
  • Close active pipeline-managed issues when their finding is no longer present.
  • Reconcile clean scans as well as scans with findings.
  • Abort before any Linear mutation when Dependabot, CodeQL, or Trivy collection fails.

Matching and safety

Issues use the canonical title format [repository] finding-id: title and are queried within the Sourcebot team. Matching is exact, including repository and finding ID, so prefix collisions and CodeQL IDs containing colons do not produce false matches. Auto-close is limited to active, pipeline-managed issues from the current repository. Dry-run mode suppresses create, reopen, and close mutations.

Tests

Adds a focused regression suite covering:

  • new finding creation
  • existing active issue
  • completed/canceled issue reopening
  • duplicate marker preservation
  • repository isolation
  • finding-ID prefix collisions
  • CodeQL IDs containing colons
  • stale issue closure
  • clean snapshots that close all remaining managed issues
  • dry-run behavior

Also adds the focused suite to the pull-request test workflow.

Related: SOU-1587


Note

Medium Risk
Workflow now mutates Linear issue state and fails hard on API gaps; incorrect snapshots could close or duplicate issues, though guards and tests reduce that risk.

Overview
Makes vulnerability triage keep Linear in sync with the current scanner snapshot: create/reopen/skip on the way in, and auto-close pipeline-managed issues when their finding ID is no longer present—including on clean scans.

Fail-closed reconciliation: Dependabot/CodeQL fetch failures and missing tokens now exit the job instead of writing empty alert files, so incomplete data cannot mass-close issues. The Linear triage job runs when check-alerts succeeds and scan succeeded or was skipped (not after a failed scan).

Matching: Linear lookup uses team-scoped startsWith on [repo] finding-id: titles, with shared jq scripts for exact finding-ID parsing (including CodeQL IDs with colons), open-vs-closed preference, and duplicate markers. A new step paginates open managed issues and moves resolved ones to a completed workflow state (skipped in dry-run).

Adds a shell regression suite for match/classify behavior and wires it into the PR Test workflow; CHANGELOG notes the behavior change.

Reviewed by Cursor Bugbot for commit 950c111. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Security findings are now synchronized with their corresponding Linear issues.
    • Resolved findings automatically close their associated issues.
    • Existing issues are matched more accurately, including reopening previously resolved issues when findings return.
  • Bug Fixes

    • Prevented reconciliation when vulnerability scan data is incomplete or unavailable.
    • Improved handling of duplicate and similarly named findings.
  • Tests

    • Added comprehensive automated coverage for vulnerability triage and reconciliation scenarios.
  • Documentation

    • Updated the unreleased changelog with the synchronization improvements.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 606dad3e-9fc1-4d58-9349-9f5fd8282e35

📥 Commits

Reviewing files that changed from the base of the PR and between 61c9302 and 950c111.

📒 Files selected for processing (6)
  • .github/scripts/classify-vulnerability-issues.jq
  • .github/scripts/match-vulnerability-issue.jq
  • .github/scripts/test-vulnerability-triage.sh
  • .github/workflows/test.yml
  • .github/workflows/vulnerability-triage.yml
  • CHANGELOG.md

Walkthrough

Vulnerability triage now requires complete scanner data, deterministically matches findings to Linear issues, and closes managed issues absent from the current findings. New jq filters and shell tests cover matching, deduplication, reopening, and classification behavior.

Changes

Vulnerability triage reconciliation

Layer / File(s) Summary
Deterministic issue matching
.github/scripts/match-vulnerability-issue.jq, .github/scripts/classify-vulnerability-issues.jq, .github/scripts/test-vulnerability-triage.sh
Finding identifiers are extracted from managed titles, matching issues are selected by state, and current findings classify issues as ignored, kept, or closed with shell-based assertions.
Complete scanner snapshot gating
.github/workflows/vulnerability-triage.yml
Dependabot and CodeQL fetch failures now fail the workflow, and Linear triage requires successful scanner prerequisites.
Linear reconciliation and closure
.github/workflows/vulnerability-triage.yml, .github/workflows/test.yml, CHANGELOG.md
Linear metadata and searches are validated and scoped; resolved issues are paginated, classified, and moved to the completed state. The workflow test job and changelog reflect the triage reconciliation behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Scanner as Dependabot and CodeQL
  participant Workflow as Vulnerability triage
  participant Linear as Linear API
  participant jq as jq filters
  Scanner->>Workflow: Submit alert snapshot
  Workflow->>Linear: Search managed issues
  Linear-->>Workflow: Return issue candidates and states
  Workflow->>jq: Match and classify findings
  jq-->>Workflow: Return issue selections and close actions
  Workflow->>Linear: Complete resolved issues
Loading

Possibly related PRs

Suggested reviewers: brendan-kellam

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch msukkari/vulnerability-linear-reconciliation

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.

@msukkari
msukkari marked this pull request as ready for review July 24, 2026 17:18
@msukkari
msukkari merged commit 9491a13 into main Jul 24, 2026
12 of 13 checks passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 950c111. Configure here.

always() &&
!cancelled() &&
needs.check-alerts.result == 'success' &&
(needs.scan.result == 'success' || needs.scan.result == 'skipped')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Skipped Trivy closes issues

High Severity

Linear reconciliation runs when the Trivy job is skipped, builds findings without container scan data, and the auto-close step treats missing Trivy CVEs as resolved. Open Linear issues for container-only findings can be completed even though no Trivy snapshot was collected.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 950c111. Configure here.

echo "::error::Failed to create $FAILED_COUNT Linear issue(s)"
exit 1
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.

Create failure blocks issue closure

Medium Severity

The Create Linear issues step exits with failure when any create or reopen fails, so the new Close resolved Linear issues step never runs. Resolved findings can stay open in Linear because inbound sync aborted before outbound reconciliation.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 950c111. Configure here.

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