Security findings that arrive in a dashboard get fixed when someone has time. Findings that arrive in the pull request, while the author still has the change in their head, get fixed before merge. The difference is not the scanner. It is where the result lands, who it is addressed to, and whether the developer believes it.

In short

  • Comment where the work happens. A GitHub App or GitLab integration scans every pull request’s head and posts one summary comment, edited on later pushes, plus a check run or commit status.
  • Gate on what the change introduces, not on history. The check fails only for new findings at or above the gate priority, so a PR is never blocked by debt it did not create.
  • Route every finding to an owner. CODEOWNERS (GitHub and GitLab syntax) or the file’s last committer becomes the owner; auto-assignment is one setting.
  • Hand over the fix, not just the finding. A security lead can open a fix PR that bumps the manifest to the fixed version, or applies an AI patch only when it matches exactly.
  • Close the loop with the ticketing system honestly. Jira two-way sync marks a finding for verification when the issue is done, and the next scan decides.

The economics of where a finding lands

A finding raised against the default branch weeks after merge has to be rediscovered: someone has to work out which change introduced it, who owns the file now, and whether it still matters. A finding raised in the pull request has all of that attached: the author, the diff, the reviewer and the reason for the change. The cost of fixing it there is a commit; later it is a ticket, a context switch and a negotiation.

Industry
data

Industry guidance has long held that defects are cheaper to fix the earlier they are found, and secure development frameworks such as NIST’s Secure Software Development Framework (SP 800-218) recommend checking code for vulnerabilities as part of the development workflow rather than after release.

Sources: NIST SP 800-218 (SSDF) practices PW.7 and PW.8; widely cited software-engineering cost-of-defect literature (estimates vary).

TODAY A dashboard and a monthly report

Findings land on the default branch, detached from the change that caused them. Security chases owners; developers see a list of other people’s debt.

WITH RISK CONTEXT A comment, a check and an owner on every PR

The author sees what their change adds, the gate judges only that, and anything merged arrives with an owner and, often, a fix PR.

What happens on every pull request

sequenceDiagram participant Dev as Developer participant GH as GitHub or GitLab participant IF as InsightFortify participant W as Worker scanners Dev->>GH: opens or updates a pull request GH->>IF: signed webhook - pull_request IF->>W: preview scan of the PR head W-->>IF: results, fingerprinted like a normal scan IF->>IF: compare with the repository's open findings IF->>GH: one summary comment - new, fixed, gate verdict IF->>GH: check run - annotations on new findings alt new finding at or above the gate GH-->>Dev: check fails with the line and the fix else nothing new at the gate GH-->>Dev: check passes end

A preview scan writes no findings. It records what merging would add and fix, then reports it on the PR.

Three design choices make this tolerable for developers:

  • One comment, edited in place. Later pushes update the same comment instead of adding another, so the conversation is not buried.
  • New findings only. The gate looks at what the change introduces, scored with the repository’s context. Existing debt is visible in the console but never fails someone else’s PR.
  • Reporting never fails the scan. If GitHub is slow or a permission is missing, the error is kept on the pull request record; the security data is still there.

Forks and annotations

The preview scans refs/pull/N/head (or the GitLab merge-request ref), so pull requests from forks work. The GitHub check run annotates up to 50 new findings on their lines; GitLab gets a commit status and an MR note.

Owners: the step most programmes skip

A finding without an owner is a finding nobody fixes. After each repository scan, InsightFortify reads CODEOWNERS in GitHub and GitLab syntax — last match wins, GitLab sections combined — and attaches the owners to every file-level finding. Where CODEOWNERS names nobody and the clone has full history, the file’s last committer is used instead. A shallow clone never names the last pusher as owner of everything.

With auto-assignment on, unassigned open findings are assigned to the first email owner. Team owners (@org/team) are shown and filterable, so a security lead can ask for “every P1 owned by the payments team” in one filter.

Fix PRs: make the right thing the easy thing

How a fix PR is openedRequested by a security lead or analyst from the finding page
1
Choose the changeInsightFortify

Dependency findings: bump the manifest to the fixed version on the installed major line (package.json ranges kept, npm overrides / yarn resolutions / pnpm overrides for transitive ones; requirements, pyproject, go.mod, pom.xml).

2
Or apply the AI patchInsightFortify

Other findings: the AI remediation’s unified diff, applied only when its context matches the file exactly.

3
Commit to a new branchGitHub / GitLab API

Always insightfortify/fix-… off the default branch. It never writes to the default branch.

4
Open the PR or MRGitHub / GitLab API

With the explanation and a link back to the finding; lockfiles are not regenerated, and the PR says so.

5
Record itAudit trail

The URL, a fix_pr event and an audit row on the finding; a second request while one is open is refused.

Some findings cannot be fixed this way — container base images, build files such as Gradle, findings without a usable patch — and the request is refused with the reason rather than producing a broken PR.

A security lead does not have to click the button for every case. The reachable critical with a fix playbook template starts on a new finding and continues only when it is a dependency finding at P1 or P2, the vulnerable function is actually called, and a fixed version exists; then it opens the fix PR and a Jira issue that links it. Everything else is left for a person to judge.

Tickets that close honestly

Many organizations track remediation in Jira or ServiceNow, and most integrations make the same mistake: when the ticket is closed, the finding is closed. That turns a developer’s belief into a security fact. InsightFortify treats “Done” as a claim to verify.

flowchart LR A["Finding P1"] --> B["Jira issue opened
by hand or by a rule"] B --> C["Developer marks Done"] C --> D["Finding: pending verification"] D --> E{"Next scan
still sees it?"} E -- "no" --> F["Fixed, comment: verified"] E -- "yes" --> G["Issue reopened,
comment: still detected"] style F fill:#ccfbf1,stroke:#0d9488 style G fill:#fee2e2,stroke:#ef4444

Done is a claim; the next scan is the evidence. Missed webhooks are caught by a reconciliation poll.

The same path works the other way: dismissing a finding with a reason moves the issue through a configured transition such as “Won’t Do”, and reopening one reopens the issue. ServiceNow records are created and kept in step by polling. Notification rules send new P1s, SLA breaches, newly exploited vulnerabilities, attack paths, runtime detections and failed gates to Slack, Teams, email or a signed webhook, and each finding is announced once per event however often it is rescored. Rules are the simple mode: one event, one channel. When the response needs a decision — only if internet-facing, ask a person first, open the ticket and then tell the channel — draw it as a playbook; any rule converts to one in a click.

The Integrations page in InsightFortify: notification rules for attack paths, new P1s and SLA breaches
Notification rules. Each event goes to one channel once per finding, however often it is rescored.

What we have and have not verified

The GitHub, GitLab, Jira, ServiceNow, Slack and Teams clients are built to the vendors’ documented APIs and tested against stand-ins of those APIs, including a full browser run against a mock Jira. Playbook actions use the same clients. We have not yet run them against live customer instances; expect a short integration check during onboarding.

Rolling it out without losing developer trust

Weeks 1–2

Comment only

  • Install the App on two willing teams
  • Gate off: comments and checks report, never fail
  • Collect feedback on noise
Weeks 3–6

Gate on P1, owners on

  • Fail checks on new P1s only
  • Turn on CODEOWNERS auto-assignment
  • Open fix PRs for the top dependency findings
Weeks 7–12

Close the loop

  • Jira two-way for P1/P2
  • Slack or Teams rules for SLA breaches
  • Dry-run, then switch on the fix-PR playbook
  • Extend to every repository

What the developer actually sees

The summary comment is written for the author of the change, not for the security team. An illustrative example of its shape:

InsightFortify — this pull request
Gate: fail — 1 new finding at P1 or above

New (2)
  P1  9.4  Hard-coded AWS access key        config/settings.py:14
  P3  4.1  lodash 4.17.15 → 4.17.21          package.json  (transitive)

Fixed by this change (1)
  P2  7.0  SQL built from request input     api/orders.py:88

Existing findings in this repository are not counted against this PR.
Details and fixes: link to each finding in the console

Illustrative comment. The check run carries the same new findings as line annotations.

Three things in that comment do most of the work: the gate result is stated first, fixes are credited as well as problems raised, and the line about existing findings answers the most common objection before it is made.

Objections you will hear, and the answers

ObjectionAnswer
“This will block releases for old problems.”It cannot: the gate judges only what the pull request introduces. Debt is tracked separately, with owners and SLAs.
“The bot will spam our PRs.”One comment per pull request, edited in place on every push; annotations are capped at 50.
“We don’t want a tool pushing to our repositories.”Fix PRs are opened only on request by a security lead or analyst, always on a new branch, and never merged by InsightFortify.
“Closing the Jira ticket should be enough.”Closing marks the finding for verification; the next scan confirms it. That protects the developer as much as the auditor.
“What if the security tool is down?”Reporting failures are recorded on the pull request record and never fail the scan; the gate is a policy you can turn off.

How to measure whether it is working

MetricWhat good looks likeWhere it comes from
Share of new P1/P2 findings fixed before mergeRising quarter on quarterPull request records: new versus fixed per PR
Findings with an ownerAbove 90% of open P1/P2Owners from CODEOWNERS or committers
Median time to remediate P1Inside the 7-day default SLADashboard: time to fix by priority and team
Tickets reopened after verificationLow and fallingJira sync: “still detected” reopenings
Fix PRs mergedMost fix PRs merged within a weekFix PR links on findings

A note on preview scans

Pull request scans are previews: they record what merging would add and fix, but they do not write findings into the queue. This matters for the integrity of the numbers a CISO reports. A pull request that is abandoned should not leave findings behind, and a vulnerability fixed on a branch is not fixed until it reaches the default branch. The queue reflects what is merged; the pull request record reflects what is proposed. Both are kept, and the scan page shows each pull request’s verdict alongside the scans of the branch it targets.

What it means for each reader

For the CISO

Remediation happens before merge, so the backlog grows more slowly. The gate is a policy you set, not a vendor default.

Ticket closure is verified by evidence, which is what an auditor will ask about.

For the AppSec lead

Start with comments only, then gate on new P1s. Never gate on existing debt.

Owners and fix PRs remove the two biggest sources of delay: finding who, and writing the change.

For the board

Fewer findings reach production, and the ones that do have an owner and a due date.

The developer experience is part of the security control, not a nice-to-have.

Developers fix what reaches them in the pull request, addressed to them, with the fix attached.

Gate on what the change introduces, route everything else to an owner, and verify every closed ticket with a scan.

Keep reading