Files
git.stella-ops.org/docs-archived/product/advisories/09-Jan-2026 - GitHub Code Scanning Integration (Revised).md
2026-01-09 18:27:46 +02:00

21 KiB

GitHub Code Scanning Integration via SARIF

Status: Revised Original: 09-Jan-2026 (Lighting Up GitHub with SARIF) Revision: 09-Jan-2026 Author: Product/Engineering Epic: Platform Integrations


Executive Summary

This advisory defines the complete integration between StellaOps Scanner and GitHub Code Scanning via SARIF 2.1.0. The integration enables StellaOps findings to appear natively in GitHub's Security tab with zero custom UI, leveraging GitHub's existing annotation, filtering, and alerting infrastructure.

Current State

Component Status Notes
SARIF 2.1.0 Models Implemented Full schema in Scanner.SmartDiff
SmartDiff SARIF Export Implemented Binary diff findings, production-ready
Findings SARIF Export Not Implemented Main vulnerability findings
GitHub App Connector Implemented Auth + health checks working
GitHub Code Scanning Upload Not Implemented REST API client needed
GitHub Actions Workflow Not Implemented Template generation needed

Business Value

  • Zero Custom UI: GitHub renders findings, annotations, and PR decorations
  • Native Integration: Findings appear in Security tab alongside Dependabot/CodeQL
  • Alert Management: GitHub's existing dismiss/reopen/severity workflow
  • PR Blocking: Branch protection rules can require scan results
  • Enterprise Ready: Supports GitHub.com and GitHub Enterprise Server

What SARIF Is

SARIF (Static Analysis Results Interchange Format) is an OASIS standard (version 2.1.0) for representing static analysis results. GitHub Code Scanning accepts a subset of SARIF 2.1.0 and renders it as security alerts.

SARIF Structure

SarifLog
├── $schema: "https://json.schemastore.org/sarif-2.1.0.json"
├── version: "2.1.0"
└── runs[]
    ├── tool
    │   └── driver
    │       ├── name: "StellaOps Scanner"
    │       ├── version: "1.0.0"
    │       └── rules[]
    │           ├── id: "STELLA-VULN-001"
    │           ├── name: "Critical Vulnerability"
    │           └── properties (CWE, CVSS, etc.)
    ├── results[]
    │   ├── ruleId: "STELLA-VULN-001"
    │   ├── level: "error" | "warning" | "note"
    │   ├── message.text
    │   ├── locations[]
    │   │   └── physicalLocation
    │   │       ├── artifactLocation.uri
    │   │       └── region.startLine
    │   └── fingerprints (deduplication)
    └── versionControlProvenance (git metadata)

Three Upload Options

# .github/workflows/stellaops-scan.yml
name: StellaOps Scan
on:
  push:
    branches: [main, release/*]
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 3 * * 1"  # Weekly Monday 3 AM

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write  # Required for Code Scanning
    steps:
      - uses: actions/checkout@v4

      - name: Run StellaOps Scanner
        uses: stellaops/scanner-action@v1
        with:
          image: ${{ github.repository }}:${{ github.sha }}
          output-format: sarif
          output-file: results.sarif
          # Optional: filter by severity
          min-severity: medium

      - name: Upload SARIF to Code Scanning
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif
          category: stellaops-scanner
          # Optional: wait for processing
          wait-for-processing: true

Option 2: REST API

For scans running outside GitHub Actions:

# Gzip + base64 encode the SARIF file
gzip -c results.sarif | base64 -w0 > sarif.b64

# Upload to GitHub Code Scanning API
curl -X POST \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  "https://api.github.com/repos/OWNER/REPO/code-scanning/sarifs" \
  -d "{
    \"commit_sha\": \"$(git rev-parse HEAD)\",
    \"ref\": \"refs/heads/main\",
    \"sarif\": \"$(cat sarif.b64)\",
    \"tool_name\": \"StellaOps Scanner\"
  }"

Required Scopes:

  • Public repos: public_repo
  • Private repos: security_events

Option 3: StellaOps CLI

# Scan and upload in one command
stella scan \
  --image myregistry/myapp:latest \
  --sarif results.sarif \
  --github-upload \
  --github-token $GITHUB_TOKEN \
  --github-repo owner/repo \
  --github-ref refs/heads/main \
  --github-sha $(git rev-parse HEAD)

# Or: scan first, upload separately
stella scan --image myregistry/myapp:latest --sarif results.sarif
stella github upload \
  --sarif results.sarif \
  --repo owner/repo \
  --ref refs/heads/main

StellaOps SARIF Rule Taxonomy

Vulnerability Rules (STELLA-VULN-*)

Rule ID Name Level Description
STELLA-VULN-001 Critical Vulnerability error CVSS >= 9.0 or KEV-listed
STELLA-VULN-002 High Vulnerability error CVSS 7.0-8.9
STELLA-VULN-003 Medium Vulnerability warning CVSS 4.0-6.9
STELLA-VULN-004 Low Vulnerability note CVSS < 4.0
STELLA-VULN-005 Reachable Vulnerability error Runtime-confirmed reachable
STELLA-VULN-006 Static Reachable Vulnerability warning Static-only reachable

Secret Detection Rules (STELLA-SEC-*)

Rule ID Name Level Description
STELLA-SEC-001 Hardcoded Secret error API key, password, token in code
STELLA-SEC-002 Private Key Exposure error PEM, PKCS#8 private key
STELLA-SEC-003 Credential Pattern warning Potential credential pattern

Supply Chain Rules (STELLA-SC-*)

Rule ID Name Level Description
STELLA-SC-001 Unsigned Package warning Package lacks signature
STELLA-SC-002 Unknown Provenance warning No SLSA provenance
STELLA-SC-003 Typosquat Candidate error Potential typosquatting
STELLA-SC-004 Deprecated Package note Package marked deprecated

Binary Hardening Rules (STELLA-BIN-*)

Rule ID Name Level Description
STELLA-BIN-001 Missing RELRO warning No full RELRO
STELLA-BIN-002 No Stack Canary warning Stack protection disabled
STELLA-BIN-003 No PIE warning Position-independent disabled
STELLA-BIN-004 No Fortify note FORTIFY_SOURCE not used

SmartDiff Rules (SDIFF-*) - Already Implemented

Rule ID Name Level Description
SDIFF001 Material Risk Change warning Risk profile changed
SDIFF002 Binary Hardening Regression error Security control removed
SDIFF003 VEX Candidate note VEX status changed
SDIFF004 Reachability Change warning Reachability status changed

SARIF Schema for Findings

Complete Finding Example

{
  "version": "2.1.0",
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "runs": [{
    "tool": {
      "driver": {
        "name": "StellaOps Scanner",
        "version": "3.2.1",
        "informationUri": "https://stellaops.io/scanner",
        "rules": [{
          "id": "STELLA-VULN-001",
          "name": "CriticalVulnerability",
          "shortDescription": {
            "text": "Critical vulnerability detected"
          },
          "fullDescription": {
            "text": "A critical severity vulnerability (CVSS >= 9.0) was detected in a dependency."
          },
          "helpUri": "https://stellaops.io/rules/STELLA-VULN-001",
          "properties": {
            "precision": "high",
            "problem.severity": "error",
            "security-severity": "9.8",
            "tags": ["security", "vulnerability", "critical"]
          }
        }],
        "supportedTaxonomies": [{
          "name": "CWE",
          "guid": "d4c8a3c4-8f5e-4f3a-9a6b-2c7d8e9f0a1b"
        }]
      }
    },
    "taxonomies": [{
      "name": "CWE",
      "guid": "d4c8a3c4-8f5e-4f3a-9a6b-2c7d8e9f0a1b",
      "taxa": [{
        "id": "502",
        "name": "Deserialization of Untrusted Data"
      }]
    }],
    "results": [{
      "ruleId": "STELLA-VULN-001",
      "ruleIndex": 0,
      "level": "error",
      "message": {
        "text": "Critical vulnerability CVE-2021-44228 (Log4Shell) in org.apache.logging.log4j:log4j-core@2.14.1. CVSS: 10.0. This vulnerability allows remote code execution via JNDI injection.",
        "markdown": "**Critical vulnerability** [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) (Log4Shell) in `org.apache.logging.log4j:log4j-core@2.14.1`.\n\n**CVSS:** 10.0 (Critical)\n\n**Description:** Remote code execution via JNDI injection.\n\n**Remediation:** Upgrade to log4j-core >= 2.17.0"
      },
      "locations": [{
        "physicalLocation": {
          "artifactLocation": {
            "uri": "pom.xml",
            "uriBaseId": "%SRCROOT%"
          },
          "region": {
            "startLine": 45,
            "startColumn": 1,
            "endLine": 49,
            "endColumn": 1,
            "snippet": {
              "text": "<dependency>\n  <groupId>org.apache.logging.log4j</groupId>\n  <artifactId>log4j-core</artifactId>\n  <version>2.14.1</version>\n</dependency>"
            }
          }
        },
        "logicalLocations": [{
          "name": "org.apache.logging.log4j:log4j-core",
          "kind": "package",
          "fullyQualifiedName": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"
        }]
      }],
      "fingerprints": {
        "stellaops/v1": "sha256:a1b2c3d4e5f6...",
        "primaryLocationLineHash": "abc123..."
      },
      "partialFingerprints": {
        "primaryLocationLineHash": "abc123..."
      },
      "taxa": [{
        "id": "502",
        "toolComponent": {
          "name": "CWE"
        }
      }],
      "properties": {
        "stellaops.finding.id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "stellaops.component.purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
        "stellaops.vulnerability.cve": "CVE-2021-44228",
        "stellaops.vulnerability.cvss": 10.0,
        "stellaops.vulnerability.severity": "critical",
        "stellaops.vulnerability.epss": 0.975,
        "stellaops.vulnerability.kev": true,
        "stellaops.reachability.state": "RuntimeObserved",
        "stellaops.reachability.confidence": 0.92,
        "stellaops.vex.status": "affected",
        "stellaops.evidence.uris": [
          "stella://reachgraph/blake3:abc123",
          "stella://signals/runtime/tenant/sha256:def456"
        ]
      }
    }],
    "artifacts": [{
      "location": {
        "uri": "pom.xml",
        "uriBaseId": "%SRCROOT%"
      },
      "mimeType": "application/xml",
      "hashes": {
        "sha-256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
      }
    }],
    "versionControlProvenance": [{
      "repositoryUri": "https://github.com/example/myapp",
      "revisionId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
      "branch": "main",
      "mappedTo": {
        "uriBaseId": "%SRCROOT%"
      }
    }],
    "properties": {
      "stellaops.scan.id": "scan-12345",
      "stellaops.scan.artifact": "sha256:abc123...",
      "stellaops.scan.timestamp": "2026-01-09T10:30:00Z",
      "stellaops.scan.version": "3.2.1",
      "stellaops.attestation": {
        "digest": "sha256:sig789...",
        "predicateType": "https://stellaops.io/attestation/scan/v1",
        "rekorLogId": 12345678
      }
    }
  }]
}

Fingerprinting Strategy

Fingerprints enable GitHub to deduplicate alerts across scans:

Primary Fingerprint (stellaops/v1)

SHA-256(
  ruleId + "|" +
  component_purl + "|" +
  vulnerability_id + "|" +
  artifact_digest
)

Partial Fingerprints (GitHub-computed fallback)

When source code is available, provide:

  • primaryLocationLineHash: Hash of code at finding location
  • primaryLocationContextHash: Hash of surrounding context

Deduplication Behavior

Scenario GitHub Behavior
Same fingerprint, new scan Updates existing alert
New fingerprint Creates new alert
Missing fingerprint in new scan Closes alert as fixed
Fingerprint reappears Reopens alert

GitHub Code Scanning API Integration

Upload Endpoint

POST /repos/{owner}/{repo}/code-scanning/sarifs

Request Format

{
  "commit_sha": "a1b2c3d4e5f6...",
  "ref": "refs/heads/main",
  "sarif": "<gzip+base64 encoded SARIF>",
  "checkout_uri": "file:///home/runner/work/repo/repo",
  "started_at": "2026-01-09T10:00:00Z",
  "tool_name": "StellaOps Scanner"
}

Response

{
  "id": "47177e22-5596-11eb-80a1-c1e54ef945c6",
  "url": "https://api.github.com/repos/owner/repo/code-scanning/sarifs/47177e22-5596-11eb-80a1-c1e54ef945c6"
}

Status Polling

GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}

Response includes processing_status: pending | complete | failed


GitHub Enterprise Server Support

The existing GitHubAppConnectorPlugin supports GHES:

// Endpoint resolution
var apiBase = isEnterprise
    ? $"https://{hostname}/api/v3"
    : "https://api.github.com";

GHES Configuration

# etc/integrations.yaml
github:
  type: github_enterprise
  hostname: github.mycompany.com
  api_version: "2022-11-28"
  app_id: 12345
  private_key_path: /secrets/github-app.pem

Important Gotchas

1. One Tool Per Run (June 2025 Deadline)

GitHub is deprecating combined runs. Each tool must have its own run:

{
  "runs": [
    { "tool": { "driver": { "name": "StellaOps Scanner" } }, "results": [...] },
    { "tool": { "driver": { "name": "StellaOps SmartDiff" } }, "results": [...] }
  ]
}

Not:

{
  "runs": [
    {
      "tool": { "driver": { "name": "StellaOps" } },
      "results": [/* mixed scanner + smartdiff */]
    }
  ]
}

2. Permissions

Context Required Permission
GitHub Actions security-events: write
REST API (public) public_repo scope
REST API (private) security_events scope
GitHub App security_events: write

3. PR Uploads from Forks

  • Direct API uploads from forks have restrictions
  • Use github/codeql-action/upload-sarif action instead
  • The action handles fork context correctly

4. SARIF Size Limits

Limit Value
Uncompressed 10 MB
Compressed (gzip) Recommended for API
Results per run 10,000 (soft limit)

5. Rate Limits

  • 1000 requests/hour for Code Scanning API
  • Use conditional requests (If-None-Match) where possible

Integration Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                              StellaOps Scanner                               │
│  ┌─────────────┐   ┌─────────────────┐   ┌─────────────────────────────┐   │
│  │ Scan Engine │──>│ Findings Ledger │──>│ SARIF Export Service        │   │
│  └─────────────┘   └─────────────────┘   │  - FindingsSarifMapper      │   │
│                                           │  - SarifRuleRegistry        │   │
│                                           │  - FingerprintGenerator     │   │
│                                           └─────────────┬───────────────┘   │
└─────────────────────────────────────────────────────────┼───────────────────┘
                                                          │
                                                          │ SARIF 2.1.0
                                                          ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           GitHub Integration Service                         │
│  ┌─────────────────────┐   ┌─────────────────────┐   ┌─────────────────┐   │
│  │ GitHubAppConnector  │   │ CodeScanningClient  │   │ SarifUploader   │   │
│  │ (existing)          │   │ (new)               │   │ (new)           │   │
│  └─────────────────────┘   └─────────────────────┘   └─────────────────┘   │
└─────────────────────────────────────────────────────────┬───────────────────┘
                                                          │
                                                          │ REST API / Actions
                                                          ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                             GitHub Code Scanning                             │
│  ┌─────────────────┐   ┌─────────────────┐   ┌─────────────────────────┐   │
│  │ Security Tab    │   │ PR Annotations  │   │ Branch Protection      │   │
│  │ Alerts          │   │ Check Runs      │   │ Rules                  │   │
│  └─────────────────┘   └─────────────────┘   └─────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘

CLI Commands

Scan with SARIF Output

# Basic scan with SARIF output
stella scan --image myapp:latest --format sarif --output results.sarif

# With severity filter
stella scan --image myapp:latest --format sarif --output results.sarif \
  --min-severity high

# With reachability evidence
stella scan --image myapp:latest --format sarif --output results.sarif \
  --include-reachability

# Pretty-printed for debugging
stella scan --image myapp:latest --format sarif --output results.sarif \
  --pretty

GitHub Upload

# Upload SARIF to GitHub Code Scanning
stella github upload-sarif \
  --sarif results.sarif \
  --repo owner/repo \
  --ref refs/heads/main \
  --sha $(git rev-parse HEAD)

# With GitHub Enterprise
stella github upload-sarif \
  --sarif results.sarif \
  --repo owner/repo \
  --ref refs/heads/main \
  --sha $(git rev-parse HEAD) \
  --github-url https://github.mycompany.com

# Wait for processing
stella github upload-sarif \
  --sarif results.sarif \
  --repo owner/repo \
  --wait --timeout 5m

Generate Workflow

# Generate GitHub Actions workflow
stella github generate-workflow \
  --repo owner/repo \
  --output .github/workflows/stellaops-scan.yml \
  --triggers push,pull_request,schedule \
  --schedule "0 3 * * 1"

Success Criteria

Quantitative

Metric Target
SARIF schema validation 100% pass rate
Upload success rate > 99%
Processing time (1000 findings) < 30 seconds
Fingerprint stability 100% (same input = same fingerprint)

Qualitative

  • Findings appear correctly in GitHub Security tab
  • PR annotations show at correct line numbers
  • Alert deduplication works across scans
  • Branch protection rules can gate on scan results


Sprint Index

Sprint ID Title Status
SPRINT_20260109_010_000 INDEX: GitHub Code Scanning Planning
SPRINT_20260109_010_001 Findings SARIF Exporter Planning
SPRINT_20260109_010_002 GitHub Code Scanning Client Planning
SPRINT_20260109_010_003 CI/CD Workflow Templates Planning

Last updated: 09-Jan-2026