BrokenApp
Back to blog
ProductJan 10, 20265 min read

From scan to GitHub issue in one command

Finding vulnerabilities is only half the problem. The other half is getting them into the workflow where they'll actually get fixed. If a scan report sits in a terminal output or a downloaded JSON file, it's dead on arrival. Developers fix issues that are in their issue tracker, assigned to them, with enough context to act on.

BrokenApp's GitHub integration bridges the gap between detection and remediation. A single command syncs scan findings to GitHub Issues, exports SARIF for Code Scanning, and posts comments on pull requests. No manual triage, no copy-pasting, no drift between what the scanner found and what the team tracks.

The github sync command

After running a scan, the brokenapp github sync command reads the scan report and creates a GitHub issue for each finding. Each issue includes the vulnerability title, severity, CWE identifier, affected URL, reproduction steps, evidence (screenshots and network traces), and a recommended fix.

# Scan and sync to GitHub in one pipeline
$ brokenapp scan https://staging.example.com
$ brokenapp github sync --repo owner/repo --report ./report.json
Created #142 — IDOR on /api/users/:id (High)
Created #143 — Missing rate limit on /auth/login (Medium)
Skipped #138 — Duplicate: exposed .env file (fingerprint match)
Closed #127 — Resolved: open redirect on /callback

Issues are created with configurable labels (default: security, brokenapp) and can be assigned to specific team members or teams. The command authenticates using a GitHub personal access token or a GitHub App installation token for organization-wide deployments.

Fingerprint-based issue matching

The core challenge of syncing scan results to an issue tracker is deduplication. If you run a scan every day, you don't want 30 copies of the same IDOR finding cluttering your backlog. But you also can't match on title alone — the same vulnerability might have slightly different descriptions between scan runs if the affected URL includes dynamic parameters.

BrokenApp solves this with Blake3-based fingerprinting. Each finding is assigned a deterministic fingerprint computed from the vulnerability type, the normalized URL path (with dynamic segments replaced by placeholders), and the HTTP method. This fingerprint is embedded in the GitHub issue body as a hidden HTML comment.

When github sync runs, it fetches all open issues with the brokenapp label and extracts their fingerprints. New findings are matched against existing fingerprints. If a match is found, the issue is skipped (or optionally updated with fresh evidence). If no match exists, a new issue is created. This approach is resilient to URL parameter changes, description rewording, and title edits.

# Fingerprint embedded in issue body (hidden comment)
<!-- brokenapp:fingerprint:a3f8c1d9e2b74506 -->
# Fingerprint computation
blake3(vuln_type + normalized_path + method)
blake3("idor" + "/api/users/:id" + "GET") → a3f8c1d9e2b74506

Auto-closing resolved issues

Fingerprint matching also enables automatic issue closure. When a finding that existed in a previous scan no longer appears in the current scan, the sync command closes the corresponding GitHub issue with a comment explaining that the vulnerability was not detected in the latest scan.

This creates a self-maintaining issue tracker. As developers fix vulnerabilities and the next scan confirms the fix, the issues close themselves. No manual triage needed. If a vulnerability regresses and reappears in a future scan, the sync command reopens the existing issue rather than creating a duplicate, preserving the full history of the finding.

Auto-close is conservative by default. Issues are only closed when the scan covers the same scope as the original finding. If you scan a subset of your application, the sync command won't close issues for URLs outside the scan scope. This prevents false closures when running targeted scans.

SARIF 2.1.0 export for GitHub Code Scanning

In addition to GitHub Issues, BrokenApp exports scan results in SARIF 2.1.0 format — the standard consumed by GitHub Code Scanning. Uploading a SARIF file to your repository surfaces findings directly in the Security tab, inline on pull request diffs, and in the code scanning API.

# Export SARIF and upload to GitHub Code Scanning
$ brokenapp export sarif --report ./report.json --output results.sarif
$ gh api repos/owner/repo/code-scanning/sarifs \
-X POST \
-f commit_sha=$(git rev-parse HEAD) \
-f ref=refs/heads/main \

The SARIF output includes full rule metadata for each finding. Every rule ID maps to a CWE identifier and an OWASP Top 10 category. The rule descriptions include severity, confidence, and remediation guidance. This metadata is rendered natively by GitHub's Code Scanning UI, giving reviewers all the context they need without leaving the pull request.

PR comment integration

For teams that run BrokenApp in CI on every pull request, the brokenapp github comment command posts a summary comment on the PR with the scan results. The comment includes a table of findings with severity, type, and affected URL, plus a diff against the baseline showing new and resolved findings.

The comment is updated in place on subsequent pushes to the same PR — the command finds its previous comment by a marker and edits it rather than posting a new one. This keeps the PR timeline clean and ensures the latest scan results are always visible at the top of the review.

# CI workflow step — post PR comment
- name: Comment scan results on PR
run: |
brokenapp scan $STAGING_URL --report pr-report.json
brokenapp github comment \
--repo $GITHUB_REPOSITORY \
--pr $PR_NUMBER \
--report pr-report.json \
--baseline main-report.json

The security feedback loop in CI

When all three integrations — Issues, SARIF, and PR comments — are wired into your CI pipeline, you get a complete security feedback loop. A developer pushes a branch. CI deploys a preview environment and runs BrokenApp against it. The PR comment shows whether the branch introduces new vulnerabilities or resolves existing ones. SARIF results appear inline on the diff. If the branch merges, the next scan against the main branch syncs findings to Issues, closing anything that was fixed and opening anything new.

This workflow means security findings are never more than one commit behind. There's no quarterly penetration test, no backlog of findings from six months ago, no spreadsheet tracking remediation. The scanner runs on every change, the results live where the code lives, and the issues track themselves.

# Full CI pipeline
brokenapp scan $URL --report report.json
brokenapp github sync --repo $REPO --report report.json
brokenapp github comment --repo $REPO --pr $PR --report report.json
brokenapp export sarif --report report.json --output results.sarif
# Scan → Issues → PR comment → Code Scanning
# Every commit. Every branch. Every finding tracked.