SARIF output
cyscan scan . --format sarif
Produces a SARIF 2.1.0 document on stdout. Pipe it to a file, upload it to GitHub Code Scanning, or consume it with any SARIF-compatible viewer.
Shape
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "cyscan",
"informationUri": "https://github.com/cybrium-ai/cyscan",
"rules": [
{
"id": "CBR-PY-SQLI-STRING-CONCAT",
"name": "CBR-PY-SQLI-STRING-CONCAT",
"shortDescription": { "text": "String-concatenated SQL into cursor.execute" },
"fullDescription": { "text": "A SQL query is assembled via string concatenation..." },
"defaultConfiguration": { "level": "error" },
"properties": {
"security-severity": 7.5,
"cwe": ["CWE-89"]
}
}
]
}
},
"results": [
{
"ruleId": "CBR-PY-SQLI-STRING-CONCAT",
"level": "error",
"message": { "text": "A SQL query is assembled via string concatenation..." },
"locations": [
{
"physicalLocation": {
"artifactLocation": { "uri": "app/users.py" },
"region": {
"startLine": 42,
"startColumn": 17,
"endLine": 42,
"endColumn": 85,
"snippet": { "text": "cursor.execute(..." }
}
}
}
],
"properties": {
"fix_recipe": "CWE-89-PARAMETERIZE",
"packageCoordinate": null
}
}
]
}
]
}
Severity mapping
| Cyscan severity | SARIF level | security-severity (CVSS-ish) |
|---|---|---|
| critical | error | 9.5 |
| high | error | 7.5 |
| medium | warning | 5.0 |
| low | note | 3.0 |
| info | note | 1.0 |
GitHub code scanning uses security-severity for its own Critical / High / Medium / Low buckets — keeping it aligned with CVSS means you don't have to configure anything.
Supply-chain findings
Dep-scoped findings have no line/column and their physicalLocation is file-only (no region). packageCoordinate is populated so downstream joiners can identify the dependency:
"physicalLocation": {
"artifactLocation": { "uri": "package-lock.json" }
},
"properties": {
"packageCoordinate": "event-stream@3.3.6"
}
This is the hook the Cybrium platform uses to annotate each finding with reachability.
Uploading to GitHub code scanning
# .github/workflows/cyscan.yml
name: Cyscan
on: [push, pull_request]
jobs:
cyscan:
runs-on: ubuntu-latest
permissions:
security-events: write # required for SARIF upload
contents: read
steps:
- uses: actions/checkout@v4
- uses: cybrium-ai/cyscan-action@v1 # coming soon — use the install step below in the meantime
- run: cyscan scan . --format sarif --fail-on high > cyscan.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: cyscan.sarif
Manual install (until the action lands):
- name: Install cyscan
run: |
curl -sSL "https://github.com/cybrium-ai/cyscan/releases/latest/download/cyscan_$(uname -s | tr A-Z a-z)_x86_64.tar.gz" \
| tar -xz -C /usr/local/bin
Findings show up in your repo's Security → Code scanning tab and inline in PR diffs.
Uploading to GitLab
# .gitlab-ci.yml
cyscan:
image: ubuntu:24.04
stage: test
script:
- cyscan scan . --format sarif > cyscan.sarif
artifacts:
reports:
sast: cyscan.sarif
Validating against the schema
# Using `npm`:
npx sarif-multitool validate cyscan.sarif
# Or with the official python lib:
pip install sarif-tools
sarif check cyscan.sarif
Diffing two scans
SARIF documents are stable enough to diff directly. A small helper:
jq '.runs[0].results | map({ rule: .ruleId, file: .locations[0].physicalLocation.artifactLocation.uri, line: .locations[0].physicalLocation.region.startLine })' \
old.sarif > old.json
jq ... new.sarif > new.json
diff old.json new.json
Or use the sarif-diff package.