# node-sarif-builder

> Module to help building SARIF log files

Latest version **5.0.0** (published 2026-08-11) · MIT license · 0 weekly downloads

## Install

```sh
npm install node-sarif-builder
pnpm add node-sarif-builder
yarn add node-sarif-builder
bun add node-sarif-builder
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 5.0.0 |
| Published | 2026-08-11 |
| First published | 2022-01-10 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=22 |
| Dependencies | 1 |
| Unpacked size | 62.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 18 |
| Author | Nicolas Vuillamy |
| Maintainers | nvuillam |
| Keywords | sarif, builder, node, simple, linter, output, format |

## Links

- npm: https://www.npmjs.com/package/node-sarif-builder
- Repository: https://github.com/nvuillam/node-sarif-builder
- Homepage: https://github.com/nvuillam/node-sarif-builder#readme
- Issues: https://github.com/nvuillam/node-sarif-builder/issues
- npm.io page: https://npm.io/package/node-sarif-builder

## Dependencies (1)

- [@types/sarif](https://npm.io/package/@types/sarif.md) ^2.1.7

## Alternatives

- [eslint-plugin-sonarjs](https://npm.io/package/eslint-plugin-sonarjs.md) — 2.9M weekly downloads
- [eslint-config-expo](https://npm.io/package/eslint-config-expo.md) — 1.5M weekly downloads
- [@matter/protocol](https://npm.io/package/@matter/protocol.md) — 63.5K weekly downloads
- [@eventcatalog/linter](https://npm.io/package/@eventcatalog/linter.md) — 24.8K weekly downloads
- [@inrupt/eslint-config-base](https://npm.io/package/@inrupt/eslint-config-base.md) — 4.5K weekly downloads

## Recent versions

- 5.0.0 (latest) — 2026-08-11
- 3.3.2-alpha202512300944.0 (alpha) — 2025-12-30
- 3.3.2-beta202511230758.0 (beta) — 2025-11-23
- 4.1.0 — 2026-04-19
- 4.0.0 — 2026-02-28
- 3.4.0 — 2025-12-30
- 3.3.1 — 2025-11-23
- 3.3.1-beta202511230757.0 — 2025-11-23
- 3.3.1-beta202511230756.0 — 2025-11-23
- 3.3.1-beta202511230706.0 — 2025-11-23
- 3.3.0 — 2025-11-16
- 3.2.1-beta202411102137.0 — 2024-11-10
- 3.2.1-beta202411102135.0 — 2024-11-10
- 3.2.1-beta202411092233.0 — 2024-11-09
- 3.2.1-beta202410270144.0 — 2024-10-27
- … 134 more at https://npm.io/package/node-sarif-builder/versions

## README

# node-sarif-builder

[![Version](https://img.shields.io/npm/v/node-sarif-builder.svg)](https://npmjs.org/package/node-sarif-builder)
[![Downloads/week](https://img.shields.io/npm/dw/node-sarif-builder.svg)](https://npmjs.org/package/node-sarif-builder)
[![Downloads/total](https://img.shields.io/npm/dt/node-sarif-builder.svg)](https://npmjs.org/package/node-sarif-builder)<!-- gh-dependents-info-used-by-start -->
[![Generated by github-dependents-info](https://img.shields.io/static/v1?label=Used%20by&message=6556&color=informational&logo=slickpic)](https://github.com/nvuillam/node-sarif-builder/blob/main/docs/github-dependents-info.md)<!-- gh-dependents-info-used-by-end -->
[![Test](https://github.com/nvuillam/node-sarif-builder/workflows/Test/badge.svg?branch=main)](https://github.com/nvuillam/node-sarif-builder/actions?query=workflow%3ATest+branch%3Amain)
[![Mega-Linter](https://github.com/nvuillam/node-sarif-builder/workflows/MegaLinter/badge.svg?branch=main)](https://megalinter.github.io/)
[![GitHub contributors](https://img.shields.io/github/contributors/nvuillam/node-sarif-builder.svg)](https://github.com/nvuillam/node-sarif-builder/graphs/contributors/)
[![GitHub stars](https://img.shields.io/github/stars/nvuillam/node-sarif-builder?label=stars&maxAge=3600)](https://github.com/nvuillam/node-sarif-builder/stargazers/)
[![License](https://img.shields.io/npm/l/node-sarif-builder.svg)](https://github.com/nvuillam/node-sarif-builder/blob/master/package.json)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)

## Introduction

Until today, every SAST tool (not exhaustive list available at <https://analysis-tools.dev/>) is using its own custom output format.

In order to **unify SAST tools output format**, more and more tools and services are implementing [**SARIF format**](https://sarifweb.azurewebsites.net/) ([example](https://github.com/microsoft/sarif-tutorials/blob/main/samples/1-Introduction/simple-example.sarif))

SARIF logs can be:
- **Uploaded to DevOps tools**, like [Github](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning), [Azure DevOps](https://github.com/microsoft/sarif-azuredevops-extension) to show issues directly in their web UI <!-- markdown-link-check-disable-line -->
- **Visualized in IDEs**, like [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MS-SarifVSCode.sarif-viewer), [Visual Studio](https://marketplace.visualstudio.com/items?itemName=WDGIS.MicrosoftSarifViewer), [Jetbrains editors](https://plugins.jetbrains.com/plugin/16938-qodana)
- **Aggregated by multi-language linters**, like [MegaLinter](https://megalinter.io/latest/)

Example of linters that can output logs in SARIF format:

- bandit (python)
- checkov (terraform)
- checkstyle (java)
- cfn-lint (AWS CloudFormation)
- codeql (multi-language)
- devskim (security)
- eslint (javascript,typescript,json)
- gitleaks (security)
- ktlint (Kotlin)
- hadolint (Dockerfile)
- MegaLinter (linters orchestrator)
- psalm (php)
- semgrep (multi-language)
- revive (Go)
- tflint (terraform)
- terrascan (terrasform)
- trivy (security)
- and many more...

If you are a **maintainer** of any **javascript/typescript based** SAST tool, but also IaC tool, or **any type of tool that can return a list of errors with a level of severity**, you can either:

- read the whole [OASIS Specification](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html) and implement it
- **simply use this library** to add SARIF as additional output format, so your tool will be natively compliant with any of SARIF-compliant tools !

## Installation

- with npm

```shell
npm install node-sarif-builder
```

- with yarn

```shell
yarn add node-sarif-builder
```

## Use

With node-sarif-builder, you can generate complex SARIF format with simple methods

___

- Start by importing module

```javascript
const { SarifBuilder, SarifRunBuilder, SarifResultBuilder, SarifRuleBuilder } = require("node-sarif-builder");
```

___

- Create and init **SarifBuilder** and **SarifRunBuilder** objects

```javascript
// SARIF builder
const sarifBuilder = new SarifBuilder();
// SARIF Run builder
const sarifRunBuilder = new SarifRunBuilder().initSimple({
    toolDriverName: "npm-groovy-lint",                           // Name of your analyzer tool
    toolDriverVersion: "9.0.5",                                  // Version of your analyzer tool
    url: "https://nvuillam.github.io/npm-groovy-lint/"           // Url of your analyzer tool
});
```

___

- Add all rules that can be found in your results (recommended but optional)

```javascript
// Add SARIF rules
for (const rule of rules) {                           // rules from your linter in any format
    const sarifRuleBuiler = new SarifRuleBuilder().initSimple({
        ruleId: rule.id,                              // ex: "no-any"
        shortDescriptionText: rule.description,       // ex: "Do not use any in your code !"
        helpUri: rule.docUrl                          // ex: "http://my.linter.com/rules/no-any"
    });
    sarifRunBuilder.addRule(sarifRuleBuiler);
}
```

___

- For each found issue, create a SarifResultBuilder and add it to the SarifRunBuilder object

```javascript
import { pathToFileURL } from 'url'

// Add results
for (const issue of issues) { // issues from your linter in any format
    const sarifResultBuilder = new SarifResultBuilder();
    const sarifResultInit = {
         // Transcode to a SARIF level:  can be "warning" or "error" or "note"
        level: issue.severity === "info" ? "note" : issue.severity,
        messageText: err.msg,                                     // Ex: "any is forbidden !"
        ruleId: err.rule,                                         // Ex: "no-any"
        fileUri: process.env.SARIF_URI_ABSOLUTE                   // Ex: src/myfile.ts
            ? pathToFileURL(fileNm)
            : path.relative(process.cwd(), fileNm).replace(/\\/g, '/'),
    };
    // When possible, provide location of the issue in the source code
    if (issue.range) {
        sarifResultInit.startLine = issue.range.start.line;        // any integer >= 1 (optional)
        sarifResultInit.startColumn = issue.range.start.character; // any integer >= 1 (optional)
        sarifResultInit.endLine = issue.range.end.line;            // any integer >= 1 (optional)
        sarifResultInit.endColumn = issue.range.end.character;     // any integer >= 1 (optional)
    }
    // Init sarifResultBuilder
    sarifResultBuilder.initSimple(sarifResultInit); 
    // Add result to sarifRunBuilder
    sarifRunBuilder.addResult(sarifResultBuilder);
}
```

___

- Add run to sarifBuilder then generate JSON SARIF output file

```javascript
    sarifBuilder.addRun(sarifRunBuilder);
    const sarifJsonString = sarifBuilder.buildSarifJsonString({ indent: false }); // indent:true if you like
    fs.writeFileSync(outputSarifFile,sarifJsonString);
    // const sarifObj = sarifBuilder.buildSarifOutput();                          // You could also just get the Sarif log as an object and not a string
```

## Full example

- Working in [npm-groovy-lint](https://github.com/nvuillam/npm-groovy-lint)

```javascript
import { pathToFileURL } from 'url'

function buildSarifResult(lintResult) {
    // SARIF builder
    const sarifBuilder = new SarifBuilder();
    // SARIF Run builder
    const sarifRunBuilder = new SarifRunBuilder().initSimple({
        toolDriverName: "npm-groovy-lint",
        toolDriverVersion: "9.0.5", 
        url: "https://nvuillam.github.io/npm-groovy-lint/"
    });
    // SARIF rules
    for (const ruleId of Object.keys(lintResult.rules || {})) {
        const rule = lintResult.rules[ruleId];
        const sarifRuleBuiler = new SarifRuleBuilder().initSimple({
            ruleId: ruleId,
            shortDescriptionText: rule.description,
            helpUri: rule.docUrl
        });
        sarifRunBuilder.addRule(sarifRuleBuiler);
    }
    // Add SARIF results (individual errors)
    for (const fileNm of Object.keys(lintResult.files)) {
        const fileErrors = lintResult.files[fileNm].errors;
        for (const err of fileErrors) {
            const sarifResultBuilder = new SarifResultBuilder();
            const sarifResultInit = {
                level: err.severity === "info" ? "note" : err.severity, // Other values can be "warning" or "error"
                messageText: err.msg,
                ruleId: err.rule,
                fileUri: process.env.SARIF_URI_ABSOLUTE
                    ? pathToFileURL(fileNm)
                    : path.relative(process.cwd(), fileNm).replace(/\\/g, '/')
            };
            if (err.range) {
                sarifResultInit.startLine = fixLine(err.range.start.line);
                sarifResultInit.startColumn = fixCol(err.range.start.character);
                sarifResultInit.endLine = fixLine(err.range.end.line);
                sarifResultInit.endColumn = fixCol(err.range.end.character);
            }
            sarifResultBuilder.initSimple(sarifResultInit);
            sarifRunBuilder.addResult(sarifResultBuilder);
        }
    }
    sarifBuilder.addRun(sarifRunBuilder);
    return sarifBuilder.buildSarifJsonString({ indent: false });
}

function fixLine(val) {
    if (val === null) {
        return undefined;
    }
    return val === 0 ? 1 : val;
}

function fixCol(val) {
    if (val === null) {
        return undefined;
    }
    return val === 0 ? 1 : val + 1;
}
```

## Test

You can confirm that your generated SARIF logs are valid on <https://sarifweb.azurewebsites.net/Validation>

---
_Source: https://npm.io/package/node-sarif-builder · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
