# Share a Semgrep Report — Findings at a URL, Not a SARIF File

Canonical: https://commareports.com/share-semgrep-report
Published: 2026-08-29

> Semgrep emits JSON and SARIF, which nobody reads. Convert to HTML, publish it from CI, and get one link per scan with triage threads anchored to the finding instead of a spreadsheet.

# Share a Semgrep report

Semgrep is fast, the rules are good, and the output is a JSON file. Or a
SARIF file. Either way it is a machine artifact, and the humans who have
to decide what to do about a finding get a terminal dump pasted into a
ticket.

PR annotations cover the changed-lines case well. They cover nothing else:
the full-repo backlog scan, the new ruleset somebody is evaluating, the
report a customer's security questionnaire asked for. Those need something
a person can read at an address.

## Convert to HTML

```bash
semgrep ci --sarif --output semgrep.sarif

pip install sarif-tools
sarif html semgrep.sarif --output semgrep.html
```

SARIF is the right intermediate here — it is the format the rest of the
security tooling ecosystem already speaks, so the converter you set up for
Semgrep also handles CodeQL, Trivy and anything else that emits it.

The result is a **single self-contained file**.

## Publish it

```bash
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html semgrep.html \
        --arg title "Semgrep — $(git rev-parse --short HEAD)" \
        '{title: $title, html: $html}')"
```

One call, no assets. Use a [scoped token](/docs/api-tokens)
(`reports:write`) from CI secrets, and `PATCH` a saved report id so one URL
accumulates a revision per scan instead of a new orphan link every run.

`semgrep ci` exits non-zero when it finds blocking issues, so make the
publish unconditional — `if: always()` in GitHub Actions,
`after_script` in GitLab, `post { always { … } }` in Jenkins. See
[publishing from CI](/docs/ci).

## Triage, on the finding

This is the part a SARIF file structurally cannot do. Static analysis
findings are a queue of decisions, and the decisions are what get lost:

- **False positive**, because the sink is already sanitised two frames up.
- **True but accepted**, with a reason and an owner.
- **Real**, and here is the ticket.

Published to a URL, each of those is a thread **anchored to the finding**,
surviving across scans. The next person who sees rule
`javascript.express.security.audit.xss` fire on the same file finds the
previous decision attached to it rather than re-deriving it. See
[commenting on HTML](/comment-on-html).

Revision diffs answer the trend question honestly: two scans, one diff,
which findings actually cleared — rather than a count that moved because
someone changed the ruleset.

## Treat it as sensitive

The report names file paths and usually quotes vulnerable source. Access
is per report: private, your team, anyone signed in at your domain, or
anyone with the link, with view / comment / edit rights. Default to
team or private, and use a link-only URL deliberately when you actually mean
to hand it to an auditor. See [sharing & access control](/docs/sharing).

Report HTML renders inside a sandboxed iframe (`allow-scripts`, no
`allow-same-origin`), so a finding that quotes an XSS payload cannot reach
anyone's session while you are reading about it. See the
[security model](https://commareports.com/security).

## Limits

- **Entry HTML: 5 MB.** A first full-repo scan can blow past that —
  publish by severity, or scope the scan to the paths under review.
  Assets: 25 MB per file, 250 MB and 500 files total.
- **Scripts run, sandboxed** — no same-origin access.
- **60 requests/minute per token.**

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited
revision history.

**[Publish a Semgrep report →](https://commareports.com/)**

### Related

- [Share a security scan report](/share-security-scan-report) · [Share a Trivy report](/share-trivy-report)
- [Share a Snyk report](/share-snyk-report) · [Share a Bandit report](/share-bandit-report)
- [Share a SonarQube report](/share-sonarqube-report) · [Share a ZAP report](/share-zap-report)
- [Publish from CI](/docs/ci) · [Scoped tokens](/docs/api-tokens)
