lockhawk 0.2.10 → 0.2.12-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ npm install --save-dev lockhawk # for use in package scripts and CI
|
|
|
64
64
|
|
|
65
65
|
```
|
|
66
66
|
lockhawk scan [path] Scan a project (this is the default command)
|
|
67
|
-
-f, --format <fmt> table | json | sarif | html | junit
|
|
67
|
+
-f, --format <fmt> table | json | sarif | html | junit | markdown (default: table)
|
|
68
68
|
-o, --output <file> write the report to a file
|
|
69
69
|
--severity-threshold <level> minimum severity to include in the report
|
|
70
70
|
--fail-on <level> minimum severity that causes a non-zero exit (default: high)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as c}from"./chunk-IJMHOVBV.js";import{toHtml as $,toJson as b,toJunit as k,toMarkdown as v,toSarifString as S}from"@lockhawk/core";import o from"chalk";import m from"cli-table3";var i={critical:n=>o.bgRed.white.bold(` ${n} `),high:n=>o.hex("#d9822b").bold(n),medium:n=>o.yellow(n),low:n=>o.blue(n),unknown:n=>o.gray(n),none:n=>o.green(n)};function l(n){let e=[],{summary:h,target:r,stats:u,database:p}=n;e.push(o.bold(`
|
|
3
|
+
lockhawk`)+o.dim(` \xB7 ${r.root.name}${r.root.version?`@${r.root.version}`:""} \xB7 ${r.manager} \xB7 ${u.totalPackages} packages`));for(let t of p.warnings)e.push(o.yellow(`\u26A0 ${t}`));if(n.findings.length===0)return e.push(o.green.bold(`
|
|
4
|
+
\u2713 No known vulnerabilities found.
|
|
5
|
+
`)),e.push(o.dim(d(n))),e.join(`
|
|
6
|
+
`);let s=new m({head:["Severity","Package","Advisory","Fixed in","Path"].map(t=>o.dim(t)),style:{head:[],border:[]},colWidths:[12,26,22,12,40],wordWrap:!0});for(let t of n.findings){let a=t.severity,f=`${a.level}${a.score?` ${a.score}`:""}`,g=t.dependencyPaths[0]?.join(" \u203A ")??t.packageName;s.push([i[a.level](f),`${t.packageName}
|
|
7
|
+
${o.dim(t.version)}${t.direct?o.dim(" (direct)"):""}`,t.id,t.fixedVersions[0]??o.dim("none"),o.dim(g)])}return e.push(""),e.push(s.toString()),e.push(""),e.push(w(h)),e.push(o.dim(d(n))),e.join(`
|
|
8
|
+
`)}function w(n){let e=[];return n.critical&&e.push(i.critical(`${n.critical} critical`)),n.high&&e.push(i.high(`${n.high} high`)),n.medium&&e.push(i.medium(`${n.medium} medium`)),n.low&&e.push(i.low(`${n.low} low`)),n.unknown&&e.push(i.unknown(`${n.unknown} unknown`)),o.bold(`Found ${n.total} ${n.total===1?"vulnerability":"vulnerabilities"}`)+(e.length?` (${e.join(", ")})`:"")+o.dim(` \xB7 ${n.fixable} fixable`)}function d(n){let e=n.database.ageHours!==void 0?`, ${n.database.ageHours}h old`:"";return`
|
|
9
|
+
Data from OSV.dev \xB7 database: ${n.database.source}${e} \xB7 scanned in ${n.stats.durationMs??0}ms`}async function T(n,e){switch(e){case"json":return b(n);case"sarif":return S(n);case"junit":return k(n);case"markdown":return v(n);case"html":return $(n,await c());default:return l(n)}}export{T as a};
|
|
10
|
+
//# sourceMappingURL=chunk-HIU7FZE5.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as c,Option as n}from"commander";var t=new c;t.name("lockhawk").description("Fast, free, accurate npm dependency vulnerability scanner (local + CI/CD), powered by OSV.dev").version("0.2.
|
|
2
|
+
import{Command as c,Option as n}from"commander";var t=new c;t.name("lockhawk").description("Fast, free, accurate npm dependency vulnerability scanner (local + CI/CD), powered by OSV.dev").version("0.2.11");var a=["none","low","medium","high","critical"];t.command("scan",{isDefault:!0}).description("Scan a project for vulnerable dependencies").argument("[path]","project directory to scan",".").addOption(new n("-f, --format <format>","output format").choices(["table","json","sarif","html","junit","markdown"]).default("table")).option("-o, --output <file>","write the report to a file instead of stdout").addOption(new n("--severity-threshold <level>","minimum severity to report").choices(a)).addOption(new n("--fail-on <level>","minimum severity that causes a non-zero exit").choices(a).default("high")).option("--offline","use only the local offline database (no network)").option("--online","force live OSV.dev queries").option("--strict-network","fail the scan on network errors instead of degrading gracefully").option("--prod-only","ignore dev dependencies").option("--ignore <ids...>","advisory ids to suppress").option("--ignore-file <path>","path to a .lockhawkignore file").option("--cache-dir <dir>","override the cache directory").option("--cache-ttl <hours>","cache freshness window in hours",e=>Number(e)).option("--no-cache","bypass the on-disk cache").option("--concurrency <n>","max concurrent OSV requests",e=>Number(e)).action((e,o)=>import("./scan-OTEZJBCT.js").then(r=>r.runScan(e,o)));var i=t.command("db").description("Manage the offline OSV database");i.command("update").description("Download or refresh the offline npm advisory database").option("--cache-dir <dir>","override the cache directory").option("--force","ignore conditional caching and re-download").action(e=>import("./db-FFGMJJW7.js").then(o=>o.runDbUpdate(e)));i.command("status").description("Show offline database freshness").option("--cache-dir <dir>","override the cache directory").action(e=>import("./db-FFGMJJW7.js").then(o=>o.runDbStatus(e)));i.command("path").description("Print the offline database directory").option("--cache-dir <dir>","override the cache directory").action(e=>import("./db-FFGMJJW7.js").then(o=>o.runDbPath(e)));t.command("report").description("Re-render a saved JSON result into another format").requiredOption("-i, --input <file>","path to a JSON scan result").addOption(new n("-f, --format <format>","output format").choices(["table","json","sarif","html","junit","markdown"]).default("html")).option("-o, --output <file>","write the report to a file instead of stdout").action(e=>import("./report-DC6YM35N.js").then(o=>o.runReport(e)));t.command("serve").description("Run a scan and open an interactive dashboard locally").argument("[path]","project directory to scan",".").option("-i, --input <file>","serve a saved JSON result instead of scanning").option("-p, --port <port>","port to listen on",e=>Number(e),7777).option("--no-open","do not open the browser automatically").option("--offline","use only the local offline database").option("--online","force live OSV.dev queries").option("--cache-dir <dir>","override the cache directory").option("--cache-ttl <hours>","cache freshness window in hours",e=>Number(e)).option("--cache","reuse the on-disk OSV cache (serve scans fresh by default)").option("--no-cache","scan fresh, bypassing the on-disk cache (the default)").action((e,o)=>import("./serve-XUY7WB73.js").then(r=>r.runServe(e,o)));t.parseAsync().catch(e=>{process.stderr.write(`lockhawk: ${e instanceof Error?e.message:String(e)}
|
|
3
3
|
`),process.exitCode=3});
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as n}from"./chunk-
|
|
2
|
+
import{a as n}from"./chunk-HIU7FZE5.js";import"./chunk-IJMHOVBV.js";import{readFileSync as i,writeFileSync as s}from"fs";async function a(r){let o;try{o=JSON.parse(i(r.input,"utf8"))}catch(e){process.stderr.write(`lockhawk: could not read ${r.input}: ${e instanceof Error?e.message:e}
|
|
3
3
|
`),process.exitCode=2;return}let t=await n(o,r.format??"html");r.output?(s(r.output,t.endsWith(`
|
|
4
4
|
`)?t:`${t}
|
|
5
5
|
`),process.stderr.write(`Report written to ${r.output}
|
|
6
6
|
`)):process.stdout.write(`${t}
|
|
7
7
|
`)}export{a as runReport};
|
|
8
|
-
//# sourceMappingURL=report-
|
|
8
|
+
//# sourceMappingURL=report-DC6YM35N.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as m}from"./chunk-
|
|
2
|
+
import{a as m}from"./chunk-HIU7FZE5.js";import"./chunk-IJMHOVBV.js";import{writeFileSync as N}from"fs";import{join as O,resolve as b}from"path";import k from"ora";import{LockfileError as v,scan as T,shouldFail as x}from"@lockhawk/core";import{existsSync as S,readFileSync as w}from"fs";import{cosmiconfigSync as F}from"cosmiconfig";function d(o){try{return F("lockhawk").search(o)?.config??{}}catch{return{}}}function g(o,e=new Date){if(!S(o))return[];let t=[];for(let r of w(o,"utf8").split(/\r?\n/)){let c=r.replace(/#.*$/,"").trim();if(!c)continue;let[i,a]=c.split(/\s+/);if(i){if(a){let l=Date.parse(a);if(!Number.isNaN(l)&&l<e.getTime())continue}t.push(i)}}return t}var s={OK:0,FINDINGS:1,USAGE:2,INTERNAL:3,NETWORK:4};async function L(o,e){let t=b(o||"."),r=d(t),c=e.offline?"offline":e.online?"online":r.mode??"auto",i=e.format??"table",a=e.failOn??r.failOn??"high",l=[...e.ignore??[],...r.ignore??[],...g(e.ignoreFile??O(t,".lockhawkignore"))],u=i==="table"&&!!process.stderr.isTTY&&!process.env.CI?k({stream:process.stderr,text:"Scanning\u2026"}).start():void 0,h={path:t,mode:c,cacheDir:e.cacheDir,cacheTtlHours:e.cacheTtl,noCache:e.cache===!1,concurrency:e.concurrency,prodOnly:e.prodOnly??r.prodOnly,ignore:l,strictNetwork:e.strictNetwork,severityThreshold:e.severityThreshold??r.severityThreshold,onProgress:n=>{u&&(u.text=n)}},f;try{f=await T(h)}catch(n){u?.stop();let y=n instanceof Error?n.message:String(n);process.stderr.write(`lockhawk: ${y}
|
|
3
3
|
`),n instanceof v?process.exitCode=s.USAGE:process.exitCode=e.strictNetwork?s.NETWORK:s.INTERNAL;return}u?.stop();let p=await m(f,i);e.output?(N(e.output,p.endsWith(`
|
|
4
4
|
`)?p:`${p}
|
|
5
5
|
`),process.stderr.write(`Report written to ${e.output}
|
|
6
6
|
${C(f)}
|
|
7
7
|
`)):process.stdout.write(`${p}
|
|
8
8
|
`),process.exitCode=x(f.summary,a)?s.FINDINGS:s.OK}function C(o){let e=o.summary;if(e.total===0)return"\u2713 No known vulnerabilities found.";let t=["critical","high","medium","low","unknown"].filter(r=>e[r]>0).map(r=>`${e[r]} ${r}`);return`Found ${e.total} ${e.total===1?"vulnerability":"vulnerabilities"} (${t.join(", ")}).`}export{s as EXIT,L as runScan};
|
|
9
|
-
//# sourceMappingURL=scan-
|
|
9
|
+
//# sourceMappingURL=scan-OTEZJBCT.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lockhawk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12-alpha.0",
|
|
4
4
|
"description": "Fast, free, accurate npm dependency vulnerability scanner for local + CI/CD with an interactive HTML dashboard and SARIF/JUnit output, powered by OSV.dev",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"cosmiconfig": "^9.0.0",
|
|
64
64
|
"open": "^10.1.0",
|
|
65
65
|
"ora": "^8.1.1",
|
|
66
|
-
"@lockhawk/core": "0.2.
|
|
66
|
+
"@lockhawk/core": "0.2.12-alpha.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@types/node": "^22.10.2",
|
package/dist/chunk-OIXS6N3H.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{a as c}from"./chunk-IJMHOVBV.js";import{toHtml as b,toJson as w,toJunit as k,toSarifString as v}from"@lockhawk/core";import t from"chalk";import m from"cli-table3";var i={critical:n=>t.bgRed.white.bold(` ${n} `),high:n=>t.hex("#d9822b").bold(n),medium:n=>t.yellow(n),low:n=>t.blue(n),unknown:n=>t.gray(n),none:n=>t.green(n)};function l(n){let e=[],{summary:h,target:r,stats:u,database:p}=n;e.push(t.bold(`
|
|
3
|
-
lockhawk`)+t.dim(` \xB7 ${r.root.name}${r.root.version?`@${r.root.version}`:""} \xB7 ${r.manager} \xB7 ${u.totalPackages} packages`));for(let o of p.warnings)e.push(t.yellow(`\u26A0 ${o}`));if(n.findings.length===0)return e.push(t.green.bold(`
|
|
4
|
-
\u2713 No known vulnerabilities found.
|
|
5
|
-
`)),e.push(t.dim(d(n))),e.join(`
|
|
6
|
-
`);let s=new m({head:["Severity","Package","Advisory","Fixed in","Path"].map(o=>t.dim(o)),style:{head:[],border:[]},colWidths:[12,26,22,12,40],wordWrap:!0});for(let o of n.findings){let a=o.severity,f=`${a.level}${a.score?` ${a.score}`:""}`,g=o.dependencyPaths[0]?.join(" \u203A ")??o.packageName;s.push([i[a.level](f),`${o.packageName}
|
|
7
|
-
${t.dim(o.version)}${o.direct?t.dim(" (direct)"):""}`,o.id,o.fixedVersions[0]??t.dim("none"),t.dim(g)])}return e.push(""),e.push(s.toString()),e.push(""),e.push($(h)),e.push(t.dim(d(n))),e.join(`
|
|
8
|
-
`)}function $(n){let e=[];return n.critical&&e.push(i.critical(`${n.critical} critical`)),n.high&&e.push(i.high(`${n.high} high`)),n.medium&&e.push(i.medium(`${n.medium} medium`)),n.low&&e.push(i.low(`${n.low} low`)),n.unknown&&e.push(i.unknown(`${n.unknown} unknown`)),t.bold(`Found ${n.total} ${n.total===1?"vulnerability":"vulnerabilities"}`)+(e.length?` (${e.join(", ")})`:"")+t.dim(` \xB7 ${n.fixable} fixable`)}function d(n){let e=n.database.ageHours!==void 0?`, ${n.database.ageHours}h old`:"";return`
|
|
9
|
-
Data from OSV.dev \xB7 database: ${n.database.source}${e} \xB7 scanned in ${n.stats.durationMs??0}ms`}async function F(n,e){switch(e){case"json":return w(n);case"sarif":return v(n);case"junit":return k(n);case"html":return b(n,await c());default:return l(n)}}export{F as a};
|
|
10
|
-
//# sourceMappingURL=chunk-OIXS6N3H.js.map
|