Skip to content

[PR-B/Phase 3] Continue-on-error triage: unmask SonarCloud, tighten audits #160

Open

Description

@BillyOutlast

Problem

Four continue-on-error: true statements mask real failures from security/quality gates. PR #155 confirmed: SonarCloud scanner exited 3 (auth error in .github/workflows/ci.yml:220), masked as success. External SonarCloud Code Analysis check FAILED quality gate at 13% coverage on new code — not blocking because not a required check.

Locations:

  1. .github/workflows/ci.yml:97 — pnpm audit
  2. .github/workflows/ci.yml:220 — SonarCloud scan
  3. .github/workflows/osv-scanner.yml:31 — OSV scan-scheduled
  4. .github/actions/rust-ci/action.yml:129 — cargo audit

Fix Per Location

3a. SonarQube Scan (ci.yml:220) — REMOVE continue-on-error

This is the highest-priority fix. The scanner crashed with exit code 3; continue-on-error: true swallowed the failure. With branch protection now in place (Phase 1), this step MUST be allowed to fail the build.

# ci.yml line 218-222
- name: SonarQube Scan
  uses: SonarSource/sonarqube-scan-action@...
  # DELETE: continue-on-error: true
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

3b. pnpm audit (ci.yml:97) — KEEP continue-on-error, add new-vuln detection

Removing continue-on-error would fail CI on every known transitive advisory. Solution: keep the step non-blocking, but add a separate blocking step that fails only on NEW critical advisories not in the allow list.

- name: Audit dependencies (informational)
  continue-on-error: true
  run: pnpm audit --audit-level=critical --ignore GHSA-mp2f-45pm-3cg9

- name: Check for new critical advisories
  if: always()
  run: |
    pnpm audit --audit-level=critical --json > /tmp/audit.json 2>/dev/null || true
    node -e "
      const a = require('/tmp/audit.json');
      const ignored = ['GHSA-mp2f-45pm-3cg9'];
      const critical = (a.advisories ? Object.values(a.advisories) : [])
        .filter(v => v.severity === 'critical' && !ignored.includes(v.github_advisory_id));
      critical.forEach(v => console.log(v.github_advisory_id, v.module_name, v.title));
      process.exit(critical.length > 0 ? 1 : 0);
    "

3c. OSV scanner scan-scheduled (osv-scanner.yml:31) — KEEP, document why

OSV scanner exits 1 on any CVE in the dependency tree, including transitive. Legitimate to keep non-blocking. Add a comment explaining the rationale and verify SARIF upload still works.

# NOTE: OSV scanner exits 1 on ANY CVE including transitive. We keep
# continue-on-error: true because blocking on transitive vulns creates
# constant noise. SARIF results are still uploaded for review.
- name: Run OSV-Scanner
  continue-on-error: true
  uses: ...

3d. Cargo audit (rust-ci/action.yml:129) — KEEP, add new-vuln detection

Same pattern as pnpm audit: keep continue-on-error, add a post-step that parses cargo audit --json and fails only on NEW advisories not in security/risk-register.yaml.

Verification Gates

# Create a branch with a deliberately vulnerable dependency
git checkout -b remediation/test-vuln
# Add known-critical transitive dep to server/package.json
git commit -am "test: introduce known vuln"
git push origin remediation/test-vuln
gh pr create --base develop --head remediation/test-vuln --title "test: vuln detection" --draft

# Expected: ci.yml workflow FAILED on the new-vuln check
gh run list --workflow ci.yml --branch remediation/test-vuln | grep -i fail

Risk

MEDIUM. Removing continue-on-error from SonarQube could cause flaky failures on transient network errors. Mitigation: scanner retries internally; runner-level retry available.

Rollback

Revert the SonarQube step change; keep old pnpm/cargo audit logic.

Effort

~90 min (3 distinct audit logic changes — can be split across 3 commits)

Provenance

Adversarial 4-member hyperplan, 3 rounds. Phase 3 of umbrella.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions