From 7976f610f58ed590bd1b4c75645bef8748e447b4 Mon Sep 17 00:00:00 2001 From: Moshe Avni Date: Thu, 18 Jan 2024 14:06:38 +0200 Subject: [PATCH 1/5] fix(formatting): npm_groovy_lint fix timeout and no error https://github.com/nvuillam/npm-groovy-lint?tab=readme-ov-file#usage --- lua/null-ls/builtins/formatting/npm_groovy_lint.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/null-ls/builtins/formatting/npm_groovy_lint.lua b/lua/null-ls/builtins/formatting/npm_groovy_lint.lua index 53666769..ce49ef6a 100644 --- a/lua/null-ls/builtins/formatting/npm_groovy_lint.lua +++ b/lua/null-ls/builtins/formatting/npm_groovy_lint.lua @@ -13,7 +13,8 @@ return h.make_builtin({ filetypes = { "groovy", "java", "Jenkinsfile" }, generator_opts = { command = "npm-groovy-lint", - args = { "--format", "-" }, + args = { "--failon", "none", "--format", "-" }, + timeout = 5000, to_stdin = true, }, factory = h.formatter_factory, From b6e0e045d63aa6ebd838a000fe84bf052952f8b9 Mon Sep 17 00:00:00 2001 From: mosheavni Date: Wed, 31 Jul 2024 17:58:58 +0000 Subject: [PATCH 2/5] chore: Auto generate docs --- doc/null-ls.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/null-ls.txt b/doc/null-ls.txt index 78bba3b8..c4c59258 100644 --- a/doc/null-ls.txt +++ b/doc/null-ls.txt @@ -1,4 +1,4 @@ -*null-ls.txt* Last change: 2024 July 28 +*null-ls.txt* Last change: 2024 July 31 ============================================================================== Table of Contents *null-ls-table-of-contents* From 0e57d12506d0f92e5769954006caeaf966fce517 Mon Sep 17 00:00:00 2001 From: mosheavni Date: Sun, 22 Dec 2024 08:20:27 +0000 Subject: [PATCH 3/5] chore: Auto generate docs --- doc/null-ls.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/null-ls.txt b/doc/null-ls.txt index c5d5eaaf..a1acba76 100644 --- a/doc/null-ls.txt +++ b/doc/null-ls.txt @@ -1,4 +1,4 @@ -*null-ls.txt* Last change: 2024 December 18 +*null-ls.txt* Last change: 2024 December 22 ============================================================================== Table of Contents *null-ls-table-of-contents* @@ -425,4 +425,4 @@ ALTERNATIVES *null-ls-alternatives* - hover.nvim : Hover plugin framework for Neovim. -vim:tw=78:ts=8:ft=help:norl: +vim:tw=78:ts=8:ft=help:norl: \ No newline at end of file From 13316ec4c5f149b9c7ba175c304168e4880304a7 Mon Sep 17 00:00:00 2001 From: Moshe Avni Date: Sun, 28 Dec 2025 13:51:36 +0200 Subject: [PATCH 4/5] feat: add gitleaks diagnostic builtin Add support for gitleaks SAST tool for detecting hardcoded secrets like passwords, API keys, and tokens in git repos. --- lua/null-ls/builtins/diagnostics/gitleaks.lua | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 lua/null-ls/builtins/diagnostics/gitleaks.lua diff --git a/lua/null-ls/builtins/diagnostics/gitleaks.lua b/lua/null-ls/builtins/diagnostics/gitleaks.lua new file mode 100644 index 00000000..4fbce2c8 --- /dev/null +++ b/lua/null-ls/builtins/diagnostics/gitleaks.lua @@ -0,0 +1,60 @@ +local h = require("null-ls.helpers") +local methods = require("null-ls.methods") + +local DIAGNOSTICS = methods.internal.DIAGNOSTICS + +local handle_gitleaks_output = function(params) + local parser = h.diagnostics.from_json({ + attributes = { + code = "code", + }, + }) + + local offenses = {} + for _, finding in ipairs(params.output or {}) do + table.insert(offenses, { + message = finding.Description, + ruleId = finding.RuleID, + code = finding.RuleID, + line = finding.StartLine, + column = finding.StartColumn, + endLine = finding.EndLine, + endColumn = finding.EndColumn, + }) + end + + return parser({ output = offenses }) +end + +return h.make_builtin({ + name = "gitleaks", + meta = { + url = "https://github.com/gitleaks/gitleaks", + description = "Gitleaks is a SAST tool for detecting and preventing hardcoded secrets like passwords, API keys, and tokens in git repos.", + }, + method = DIAGNOSTICS, + filetypes = {}, + generator_opts = { + command = "gitleaks", + args = { + "dir", + "--report-format", + "json", + "--report-path", + "-", + "--exit-code", + "0", + "--no-banner", + "$FILENAME", + }, + format = "json", + to_stdin = false, + from_stderr = true, + ignore_stderr = true, + check_exit_code = function(code) + return code == 0 + end, + on_output = handle_gitleaks_output, + }, + factory = h.generator_factory, +}) From 0e69a432c44a52134c51fa2e995caa1a18a95e69 Mon Sep 17 00:00:00 2001 From: Moshe Avni Date: Sun, 28 Dec 2025 14:22:06 +0200 Subject: [PATCH 5/5] add tests, convert to stdin --- lua/null-ls/builtins/diagnostics/gitleaks.lua | 8 +- .../builtins/diagnostics/gitleaks_spec.lua | 107 ++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 test/spec/builtins/diagnostics/gitleaks_spec.lua diff --git a/lua/null-ls/builtins/diagnostics/gitleaks.lua b/lua/null-ls/builtins/diagnostics/gitleaks.lua index 4fbce2c8..d4e4b151 100644 --- a/lua/null-ls/builtins/diagnostics/gitleaks.lua +++ b/lua/null-ls/builtins/diagnostics/gitleaks.lua @@ -8,6 +8,9 @@ local handle_gitleaks_output = function(params) attributes = { code = "code", }, + diagnostic = { + source = "gitleaks", + }, }) local offenses = {} @@ -37,7 +40,7 @@ return h.make_builtin({ generator_opts = { command = "gitleaks", args = { - "dir", + "stdin", "--report-format", "json", "--report-path", @@ -45,10 +48,9 @@ return h.make_builtin({ "--exit-code", "0", "--no-banner", - "$FILENAME", }, format = "json", - to_stdin = false, + to_stdin = true, from_stderr = true, ignore_stderr = true, check_exit_code = function(code) diff --git a/test/spec/builtins/diagnostics/gitleaks_spec.lua b/test/spec/builtins/diagnostics/gitleaks_spec.lua new file mode 100644 index 00000000..bc9abc6f --- /dev/null +++ b/test/spec/builtins/diagnostics/gitleaks_spec.lua @@ -0,0 +1,107 @@ +local diagnostics = require("null-ls.builtins").diagnostics + +describe("diagnostics gitleaks", function() + local parser = diagnostics.gitleaks._opts.on_output + + it("should create a diagnostic from gitleaks output", function() + local output = vim.json.decode([[ + [ + { + "RuleID": "generic-api-key", + "Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.", + "StartLine": 192, + "EndLine": 192, + "StartColumn": 8, + "EndColumn": 67, + "Match": "ocp-apim-subscription-key: 5ccb5b137e7444d885be752eda7f767a'", + "Secret": "5ccb5b137e7444d885be752eda7f767a", + "File": "zsh/zsh.d/functions.zsh", + "SymlinkFile": "", + "Commit": "", + "Entropy": 3.5695488, + "Author": "", + "Email": "", + "Date": "", + "Message": "", + "Tags": [], + "Fingerprint": "zsh/zsh.d/functions.zsh:generic-api-key:192" + } + ] + ]]) + local diagnostic = parser({ output = output }) + assert.same({ + { + row = 192, + col = 8, + end_row = 192, + end_col = 67, + message = "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.", + source = "gitleaks", + code = "generic-api-key", + }, + }, diagnostic) + end) + + it("should handle multiple findings", function() + local output = vim.json.decode([[ + [ + { + "RuleID": "generic-api-key", + "Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.", + "StartLine": 10, + "EndLine": 10, + "StartColumn": 5, + "EndColumn": 30, + "Match": "api_key = 'abc123'", + "Secret": "abc123", + "File": "config.py", + "Fingerprint": "config.py:generic-api-key:10" + }, + { + "RuleID": "aws-access-token", + "Description": "Detected AWS Access Token, risking unauthorized cloud resource access and data breaches.", + "StartLine": 25, + "EndLine": 25, + "StartColumn": 12, + "EndColumn": 50, + "Match": "AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI", + "Secret": "wJalrXUtnFEMI", + "File": "env.sh", + "Fingerprint": "env.sh:aws-access-token:25" + } + ] + ]]) + local diagnostic = parser({ output = output }) + assert.same({ + { + row = 10, + col = 5, + end_row = 10, + end_col = 30, + message = "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.", + source = "gitleaks", + code = "generic-api-key", + }, + { + row = 25, + col = 12, + end_row = 25, + end_col = 50, + message = "Detected AWS Access Token, risking unauthorized cloud resource access and data breaches.", + source = "gitleaks", + code = "aws-access-token", + }, + }, diagnostic) + end) + + it("should handle empty output", function() + local output = vim.json.decode("[]") + local diagnostic = parser({ output = output }) + assert.same({}, diagnostic) + end) + + it("should handle nil output", function() + local diagnostic = parser({ output = nil }) + assert.same({}, diagnostic) + end) +end)