npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

node-sarif-builder

v3.3.1

Published

Module to help building SARIF log files

Readme

node-sarif-builder

Version Downloads/week Downloads/total Generated by github-dependents-info Test Mega-Linter GitHub contributors GitHub stars License PRs Welcome

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 (example)

SARIF logs can be:

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 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
npm install node-sarif-builder
  • with yarn
yarn add node-sarif-builder

Use

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


  • Start by importing module
const { SarifBuilder, SarifRunBuilder, SarifResultBuilder, SarifRuleBuilder } = require("node-sarif-builder");

  • Create and init SarifBuilder and SarifRunBuilder objects
// 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)
// 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
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
    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

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