secureflow-cli 1.2.0 → 2.0.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/dist/git.d.ts +2 -2
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +10 -10
- package/dist/git.js.map +1 -1
- package/dist/index.js +65 -21
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +31 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +45 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/sarif.d.ts +4 -4
- package/dist/sarif.d.ts.map +1 -1
- package/dist/sarif.js +31 -31
- package/dist/sarif.js.map +1 -1
- package/dist/scanner.d.ts +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +90 -45
- package/dist/scanner.js.map +1 -1
- package/package.json +35 -35
package/dist/git.d.ts
CHANGED
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
*/
|
|
22
22
|
/** A problem with the repository or the git invocation, not with the content. */
|
|
23
23
|
export declare class GitError extends Error {
|
|
24
|
-
readonly cause?: unknown;
|
|
25
|
-
constructor(message: string, cause?: unknown);
|
|
24
|
+
readonly cause?: unknown | undefined;
|
|
25
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
26
26
|
}
|
|
27
27
|
/** Whether the current directory is inside a work tree. */
|
|
28
28
|
export declare function isGitRepository(): boolean;
|
package/dist/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAaH,iFAAiF;AACjF,qBAAa,QAAS,SAAQ,KAAK;
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAaH,iFAAiF;AACjF,qBAAa,QAAS,SAAQ,KAAK;IAG/B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;gBADxB,OAAO,EAAE,MAAM,EACN,KAAK,CAAC,EAAE,OAAO,YAAA;CAK3B;AASD,2DAA2D;AAC3D,wBAAgB,eAAe,IAAI,OAAO,CAMzC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAgBzC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM7D"}
|
package/dist/git.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* The inverse is just as bad: unstaged debug code blocks a commit that does not
|
|
20
20
|
* contain it, which teaches people to reach for `--no-verify`.
|
|
21
21
|
*/
|
|
22
|
-
import { execFileSync } from
|
|
22
|
+
import { execFileSync } from "child_process";
|
|
23
23
|
/**
|
|
24
24
|
* Buffer ceiling for git output.
|
|
25
25
|
*
|
|
@@ -34,19 +34,19 @@ export class GitError extends Error {
|
|
|
34
34
|
constructor(message, cause) {
|
|
35
35
|
super(message);
|
|
36
36
|
this.cause = cause;
|
|
37
|
-
this.name =
|
|
37
|
+
this.name = "GitError";
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
function git(args) {
|
|
41
|
-
return execFileSync(
|
|
42
|
-
encoding:
|
|
41
|
+
return execFileSync("git", args, {
|
|
42
|
+
encoding: "utf-8",
|
|
43
43
|
maxBuffer: MAX_GIT_BUFFER,
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
/** Whether the current directory is inside a work tree. */
|
|
47
47
|
export function isGitRepository() {
|
|
48
48
|
try {
|
|
49
|
-
return git([
|
|
49
|
+
return git(["rev-parse", "--is-inside-work-tree"]).trim() === "true";
|
|
50
50
|
}
|
|
51
51
|
catch {
|
|
52
52
|
return false;
|
|
@@ -68,15 +68,15 @@ export function isGitRepository() {
|
|
|
68
68
|
export function getStagedFiles() {
|
|
69
69
|
let output;
|
|
70
70
|
try {
|
|
71
|
-
output = git([
|
|
71
|
+
output = git(["diff", "--cached", "--name-only", "-z", "--diff-filter=ACMR"]);
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
74
74
|
throw new GitError(isGitRepository()
|
|
75
|
-
?
|
|
76
|
-
:
|
|
75
|
+
? "Could not list staged files. `git diff --cached` failed."
|
|
76
|
+
: "Not a git repository (or git is not on PATH).", error);
|
|
77
77
|
}
|
|
78
78
|
// NUL-separated, with a trailing separator on a non-empty list.
|
|
79
|
-
return output.split(
|
|
79
|
+
return output.split("\u0000").filter((entry) => entry.length > 0);
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* The staged content of `path` — the bytes that will actually be committed.
|
|
@@ -87,7 +87,7 @@ export function getStagedFiles() {
|
|
|
87
87
|
*/
|
|
88
88
|
export function readStagedContent(path) {
|
|
89
89
|
try {
|
|
90
|
-
return git([
|
|
90
|
+
return git(["show", `:${path}`]);
|
|
91
91
|
}
|
|
92
92
|
catch {
|
|
93
93
|
return null;
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC,iFAAiF;AACjF,MAAM,OAAO,QAAS,SAAQ,KAAK;
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC,iFAAiF;AACjF,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGtB;IAFX,YACE,OAAe,EACN,KAAe;QAExB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,UAAK,GAAL,KAAK,CAAU;QAGxB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,SAAS,GAAG,CAAC,IAAc;IACzB,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;QAC/B,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,cAAc;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,MAAc,CAAC;IAEnB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAChF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAChB,eAAe,EAAE;YACf,CAAC,CAAC,0DAA0D;YAC5D,CAAC,CAAC,+CAA+C,EACnD,KAAK,CACN,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,OAAO,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import fs from
|
|
3
|
-
import { GitError, getStagedFiles, readStagedContent } from
|
|
4
|
-
import { scanFile, formatScanResults } from
|
|
5
|
-
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { GitError, getStagedFiles, readStagedContent } from "./git.js";
|
|
4
|
+
import { scanFile, formatScanResults } from "./scanner.js";
|
|
5
|
+
import { NetworkUnavailableError, requestAiFileScan } from "./lib/api-client.js";
|
|
6
|
+
const VERBOSE = process.argv.includes("--verbose");
|
|
7
|
+
const NO_AI = process.argv.includes("--no-ai");
|
|
6
8
|
function parseFormatArg() {
|
|
7
|
-
const formatIndex = process.argv.findIndex((arg) => arg ===
|
|
9
|
+
const formatIndex = process.argv.findIndex((arg) => arg === "--format");
|
|
8
10
|
if (formatIndex !== -1) {
|
|
9
11
|
const valStr = process.argv[formatIndex + 1];
|
|
10
12
|
if (valStr) {
|
|
11
13
|
const val = valStr.toLowerCase();
|
|
12
|
-
if (val ===
|
|
14
|
+
if (val === "sarif" || val === "json" || val === "text") {
|
|
13
15
|
return val;
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
|
-
return
|
|
19
|
+
return "text";
|
|
18
20
|
}
|
|
19
21
|
function parseOutputArg() {
|
|
20
|
-
const outIndex = process.argv.findIndex((arg) => arg ===
|
|
22
|
+
const outIndex = process.argv.findIndex((arg) => arg === "-o" || arg === "--output");
|
|
21
23
|
if (outIndex !== -1) {
|
|
22
24
|
const valStr = process.argv[outIndex + 1];
|
|
23
25
|
if (valStr) {
|
|
@@ -38,7 +40,34 @@ function reportViolations(result) {
|
|
|
38
40
|
console.error(` why: ${violation.reason} passed to a console call`);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
function
|
|
43
|
+
function reportAiFinding(finding) {
|
|
44
|
+
console.error(`🤖 [SecureFlow AI] ${finding.severity} ${finding.type} in ${finding.fileLocation}${finding.lineStart ? `:${finding.lineStart}` : ""}`);
|
|
45
|
+
console.error(` -> ${finding.description}`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Best-effort AI-powered scan on top of the always-on local scan above.
|
|
49
|
+
* Never throws and never delays the commit beyond its own short internal
|
|
50
|
+
* timeout -- if the network is down, this is a silent (or
|
|
51
|
+
* --verbose-logged) no-op and the local scan result stands on its own,
|
|
52
|
+
* unchanged.
|
|
53
|
+
*/
|
|
54
|
+
async function runAiScanIfAvailable(stagedForAi) {
|
|
55
|
+
if (NO_AI || stagedForAi.length === 0)
|
|
56
|
+
return [];
|
|
57
|
+
try {
|
|
58
|
+
return await requestAiFileScan(stagedForAi);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof NetworkUnavailableError) {
|
|
62
|
+
if (VERBOSE) {
|
|
63
|
+
console.warn("⚠️ [SecureFlow] AI scan unreachable -- continuing with local scan only.");
|
|
64
|
+
}
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function main() {
|
|
42
71
|
const format = parseFormatArg();
|
|
43
72
|
const outputPath = parseOutputArg();
|
|
44
73
|
let staged;
|
|
@@ -51,6 +80,7 @@ function main() {
|
|
|
51
80
|
}
|
|
52
81
|
const fileResults = [];
|
|
53
82
|
const unreadable = [];
|
|
83
|
+
const stagedForAi = [];
|
|
54
84
|
let violationCount = 0;
|
|
55
85
|
if (staged.length > 0) {
|
|
56
86
|
for (const path of staged) {
|
|
@@ -59,19 +89,31 @@ function main() {
|
|
|
59
89
|
unreadable.push(path);
|
|
60
90
|
continue;
|
|
61
91
|
}
|
|
92
|
+
stagedForAi.push({ path, content });
|
|
62
93
|
const result = scanFile(path, content);
|
|
63
94
|
fileResults.push(result);
|
|
64
|
-
if (format ===
|
|
95
|
+
if (format === "text") {
|
|
65
96
|
reportSkipped(result);
|
|
66
97
|
reportViolations(result);
|
|
67
98
|
}
|
|
68
99
|
violationCount += result.violations.length;
|
|
69
100
|
}
|
|
70
101
|
}
|
|
71
|
-
|
|
102
|
+
// AI-powered pass, additive on top of the local scan above. Only
|
|
103
|
+
// affects the text output/exit code today -- JSON/SARIF export stays
|
|
104
|
+
// local-scan-only for now so existing automated consumers of those
|
|
105
|
+
// formats aren't changed by this PR.
|
|
106
|
+
const aiFindings = await runAiScanIfAvailable(stagedForAi);
|
|
107
|
+
if (format === "text") {
|
|
108
|
+
for (const finding of aiFindings) {
|
|
109
|
+
reportAiFinding(finding);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const aiViolationCount = aiFindings.filter((f) => f.severity === "HIGH" || f.severity === "CRITICAL").length;
|
|
113
|
+
if (format === "sarif" || format === "json") {
|
|
72
114
|
const outputString = formatScanResults(fileResults, format);
|
|
73
115
|
if (outputPath) {
|
|
74
|
-
fs.writeFileSync(outputPath, outputString,
|
|
116
|
+
fs.writeFileSync(outputPath, outputString, "utf-8");
|
|
75
117
|
console.log(`📄 [SecureFlow] Scan report exported in ${format.toUpperCase()} format to ${outputPath}`);
|
|
76
118
|
}
|
|
77
119
|
else {
|
|
@@ -79,23 +121,25 @@ function main() {
|
|
|
79
121
|
}
|
|
80
122
|
}
|
|
81
123
|
else if (outputPath) {
|
|
82
|
-
const textOutput = formatScanResults(fileResults,
|
|
83
|
-
fs.writeFileSync(outputPath, textOutput,
|
|
124
|
+
const textOutput = formatScanResults(fileResults, "text");
|
|
125
|
+
fs.writeFileSync(outputPath, textOutput, "utf-8");
|
|
84
126
|
console.log(`📄 [SecureFlow] Scan report written to ${outputPath}`);
|
|
85
127
|
}
|
|
86
|
-
if (unreadable.length > 0 && format ===
|
|
87
|
-
console.warn(`⚠️ [SecureFlow] Could not read ${unreadable.length} staged entr${unreadable.length === 1 ?
|
|
128
|
+
if (unreadable.length > 0 && format === "text") {
|
|
129
|
+
console.warn(`⚠️ [SecureFlow] Could not read ${unreadable.length} staged entr${unreadable.length === 1 ? "y" : "ies"} (submodule, symlink or conflicted): ${unreadable.join(", ")}`);
|
|
88
130
|
}
|
|
89
|
-
if (violationCount > 0) {
|
|
90
|
-
if (format ===
|
|
91
|
-
console.error(`\n❌ SecureFlow blocked this commit: ${violationCount} secret-logging violation${violationCount === 1 ?
|
|
131
|
+
if (violationCount > 0 || aiViolationCount > 0) {
|
|
132
|
+
if (format === "text") {
|
|
133
|
+
console.error(`\n❌ SecureFlow blocked this commit: ${violationCount} secret-logging violation${violationCount === 1 ? "" : "s"}${aiViolationCount > 0
|
|
134
|
+
? ` and ${aiViolationCount} AI-detected HIGH/CRITICAL finding${aiViolationCount === 1 ? "" : "s"}`
|
|
135
|
+
: ""}. Remove the exposed secrets/env variables, then re-stage.`);
|
|
92
136
|
}
|
|
93
137
|
return 1;
|
|
94
138
|
}
|
|
95
|
-
if (format ===
|
|
139
|
+
if (format === "text") {
|
|
96
140
|
console.log(`✅ SecureFlow scan passed (${staged.length} staged file(s)).`);
|
|
97
141
|
}
|
|
98
142
|
return 0;
|
|
99
143
|
}
|
|
100
|
-
process.exit(
|
|
144
|
+
main().then((code) => process.exit(code));
|
|
101
145
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAA0C,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin client for the AI-powered scanning endpoint the SecureFlow GitHub
|
|
3
|
+
* App uses (src/lib/armor/scanner.ts, exposed at POST /api/cli/scan).
|
|
4
|
+
* Gives the CLI parity with the App's AI review, additive on top of the
|
|
5
|
+
* always-available local scan in `scanner.ts`.
|
|
6
|
+
*/
|
|
7
|
+
export interface StagedFileForAiScan {
|
|
8
|
+
path: string;
|
|
9
|
+
content: string;
|
|
10
|
+
}
|
|
11
|
+
/** Mirrors `ScanFinding` from src/lib/armor/scanner.ts. */
|
|
12
|
+
export interface AiFinding {
|
|
13
|
+
type: string;
|
|
14
|
+
severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
15
|
+
description: string;
|
|
16
|
+
fileLocation: string;
|
|
17
|
+
codeSnippet: string;
|
|
18
|
+
lineStart?: number;
|
|
19
|
+
lineEnd?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class NetworkUnavailableError extends Error {
|
|
22
|
+
constructor(cause?: unknown);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Sends staged file contents to the hosted AI scanner. Fails fast (short
|
|
26
|
+
* timeout) and always throws `NetworkUnavailableError` on any failure so
|
|
27
|
+
* callers can swallow it and fall back to the local-only scan -- never
|
|
28
|
+
* block a commit on connectivity.
|
|
29
|
+
*/
|
|
30
|
+
export declare function requestAiFileScan(files: StagedFileForAiScan[], baseUrl?: string): Promise<AiFinding[]>;
|
|
31
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,KAAK,CAAC,EAAE,OAAO;CAK5B;AAKD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,mBAAmB,EAAE,EAC5B,OAAO,GAAE,MAAyB,GACjC,OAAO,CAAC,SAAS,EAAE,CAAC,CAuBtB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin client for the AI-powered scanning endpoint the SecureFlow GitHub
|
|
3
|
+
* App uses (src/lib/armor/scanner.ts, exposed at POST /api/cli/scan).
|
|
4
|
+
* Gives the CLI parity with the App's AI review, additive on top of the
|
|
5
|
+
* always-available local scan in `scanner.ts`.
|
|
6
|
+
*/
|
|
7
|
+
export class NetworkUnavailableError extends Error {
|
|
8
|
+
constructor(cause) {
|
|
9
|
+
super("SecureFlow API unreachable");
|
|
10
|
+
this.name = "NetworkUnavailableError";
|
|
11
|
+
this.cause = cause;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const DEFAULT_TIMEOUT_MS = 5_000;
|
|
15
|
+
const DEFAULT_BASE_URL = "https://secure-flow-six.vercel.app";
|
|
16
|
+
/**
|
|
17
|
+
* Sends staged file contents to the hosted AI scanner. Fails fast (short
|
|
18
|
+
* timeout) and always throws `NetworkUnavailableError` on any failure so
|
|
19
|
+
* callers can swallow it and fall back to the local-only scan -- never
|
|
20
|
+
* block a commit on connectivity.
|
|
21
|
+
*/
|
|
22
|
+
export async function requestAiFileScan(files, baseUrl = DEFAULT_BASE_URL) {
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
25
|
+
try {
|
|
26
|
+
const res = await fetch(`${baseUrl}/api/cli/scan`, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: { "Content-Type": "application/json" },
|
|
29
|
+
body: JSON.stringify({ files }),
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
throw new Error(`SecureFlow API responded with ${res.status}`);
|
|
34
|
+
}
|
|
35
|
+
const data = (await res.json());
|
|
36
|
+
return data.findings ?? [];
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw new NetworkUnavailableError(err);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
clearTimeout(timeout);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,KAAe;QACzB,KAAK,CAAC,4BAA4B,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,MAAM,kBAAkB,GAAG,KAAK,CAAC;AACjC,MAAM,gBAAgB,GAAG,oCAAoC,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAA4B,EAC5B,UAAkB,gBAAgB;IAElC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAEzE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,eAAe,EAAE;YACjD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;YAC/B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA8B,CAAC;QAC7D,OAAO,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,uBAAuB,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
|
package/dist/sarif.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Converts CLI scan results into standardized OASIS SARIF v2.1.0 schema format
|
|
5
5
|
* for direct ingestion by GitHub Advanced Security, GitLab Security Dashboards, and enterprise CI/CD systems.
|
|
6
6
|
*/
|
|
7
|
-
import type { FileScanResult } from
|
|
7
|
+
import type { FileScanResult } from "./scanner.js";
|
|
8
8
|
export interface SarifArtifactLocation {
|
|
9
9
|
uri: string;
|
|
10
10
|
uriBaseId?: string;
|
|
@@ -35,7 +35,7 @@ export interface SarifReportingDescriptor {
|
|
|
35
35
|
text: string;
|
|
36
36
|
};
|
|
37
37
|
defaultConfiguration?: {
|
|
38
|
-
level:
|
|
38
|
+
level: "error" | "warning" | "note" | "none";
|
|
39
39
|
};
|
|
40
40
|
helpUri?: string;
|
|
41
41
|
properties?: Record<string, unknown>;
|
|
@@ -43,7 +43,7 @@ export interface SarifReportingDescriptor {
|
|
|
43
43
|
export interface SarifResult {
|
|
44
44
|
ruleId: string;
|
|
45
45
|
ruleIndex?: number;
|
|
46
|
-
level:
|
|
46
|
+
level: "error" | "warning" | "note" | "none";
|
|
47
47
|
message: {
|
|
48
48
|
text: string;
|
|
49
49
|
};
|
|
@@ -65,7 +65,7 @@ export interface SarifRun {
|
|
|
65
65
|
}
|
|
66
66
|
export interface SarifDocument {
|
|
67
67
|
$schema: string;
|
|
68
|
-
version:
|
|
68
|
+
version: "2.1.0";
|
|
69
69
|
runs: SarifRun[];
|
|
70
70
|
}
|
|
71
71
|
/**
|
package/dist/sarif.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,oBAAoB,CAAC,EAAE;QACrB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;KAC9C,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7C,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,MAAM,CAAC;YACb,YAAY,CAAC,EAAE,MAAM,CAAC;YACtB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,cAAc,CAAC,EAAE,MAAM,CAAC;YACxB,KAAK,EAAE,wBAAwB,EAAE,CAAC;SACnC,CAAC;KACH,CAAC;IACF,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AA4CD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,aAAa,CAmFf;AAED;;GAEG;AACH,wBAAgB,eAAe,
|
|
1
|
+
{"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,qBAAqB,CAAC;IACxC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,oBAAoB,CAAC,EAAE;QACrB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;KAC9C,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7C,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,MAAM,CAAC;YACb,YAAY,CAAC,EAAE,MAAM,CAAC;YACtB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,cAAc,CAAC,EAAE,MAAM,CAAC;YACxB,KAAK,EAAE,wBAAwB,EAAE,CAAC;SACnC,CAAC;KACH,CAAC;IACF,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AA4CD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,aAAa,CAmFf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,MAAM,CAGR"}
|
package/dist/sarif.js
CHANGED
|
@@ -5,51 +5,51 @@
|
|
|
5
5
|
* for direct ingestion by GitHub Advanced Security, GitLab Security Dashboards, and enterprise CI/CD systems.
|
|
6
6
|
*/
|
|
7
7
|
const DEFAULT_RULE_DEFINITIONS = {
|
|
8
|
-
|
|
9
|
-
id:
|
|
10
|
-
name:
|
|
8
|
+
"environment variable": {
|
|
9
|
+
id: "SECUREFLOW-001",
|
|
10
|
+
name: "ConsoleSecretLoggingEnvironmentVariable",
|
|
11
11
|
shortDescription: {
|
|
12
|
-
text:
|
|
12
|
+
text: "Console logging of environment variable containing potential secret",
|
|
13
13
|
},
|
|
14
14
|
fullDescription: {
|
|
15
|
-
text:
|
|
15
|
+
text: "Passing process.env or other environment variable getters into console methods exposes credentials in build logs or standard output.",
|
|
16
16
|
},
|
|
17
17
|
defaultConfiguration: {
|
|
18
|
-
level:
|
|
18
|
+
level: "error",
|
|
19
19
|
},
|
|
20
|
-
helpUri:
|
|
20
|
+
helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
|
|
21
21
|
},
|
|
22
|
-
|
|
23
|
-
id:
|
|
24
|
-
name:
|
|
22
|
+
"secret-named identifier": {
|
|
23
|
+
id: "SECUREFLOW-002",
|
|
24
|
+
name: "ConsoleSecretLoggingSecretIdentifier",
|
|
25
25
|
shortDescription: {
|
|
26
|
-
text:
|
|
26
|
+
text: "Console logging of secret-named identifier or credential parameter",
|
|
27
27
|
},
|
|
28
28
|
fullDescription: {
|
|
29
|
-
text:
|
|
29
|
+
text: "Identifiers containing secret, password, apikey, token, or auth parameters passed directly into console logging statements.",
|
|
30
30
|
},
|
|
31
31
|
defaultConfiguration: {
|
|
32
|
-
level:
|
|
32
|
+
level: "error",
|
|
33
33
|
},
|
|
34
|
-
helpUri:
|
|
34
|
+
helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
|
|
35
35
|
},
|
|
36
|
-
|
|
37
|
-
id:
|
|
38
|
-
name:
|
|
36
|
+
"generic-secret-logging": {
|
|
37
|
+
id: "SECUREFLOW-000",
|
|
38
|
+
name: "ConsoleSecretLoggingGeneric",
|
|
39
39
|
shortDescription: {
|
|
40
|
-
text:
|
|
40
|
+
text: "Potential secret credential logging in console output",
|
|
41
41
|
},
|
|
42
42
|
defaultConfiguration: {
|
|
43
|
-
level:
|
|
43
|
+
level: "error",
|
|
44
44
|
},
|
|
45
|
-
helpUri:
|
|
45
|
+
helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
|
|
46
46
|
},
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
49
49
|
* Maps CLI scan results into a valid OASIS SARIF v2.1.0 document object.
|
|
50
50
|
*/
|
|
51
51
|
export function generateSarifReport(scanResults, options) {
|
|
52
|
-
const version = options?.toolVersion ||
|
|
52
|
+
const version = options?.toolVersion || "0.1.0";
|
|
53
53
|
const rulesMap = new Map();
|
|
54
54
|
const sarifResults = [];
|
|
55
55
|
for (const fileResult of scanResults) {
|
|
@@ -57,7 +57,7 @@ export function generateSarifReport(scanResults, options) {
|
|
|
57
57
|
continue;
|
|
58
58
|
}
|
|
59
59
|
for (const violation of fileResult.violations) {
|
|
60
|
-
const reasonKey = violation.reason ||
|
|
60
|
+
const reasonKey = violation.reason || "generic-secret-logging";
|
|
61
61
|
let ruleInfo = rulesMap.get(reasonKey);
|
|
62
62
|
if (!ruleInfo) {
|
|
63
63
|
const descriptor = DEFAULT_RULE_DEFINITIONS[reasonKey] || {
|
|
@@ -67,9 +67,9 @@ export function generateSarifReport(scanResults, options) {
|
|
|
67
67
|
text: `Console logging of ${violation.reason}`,
|
|
68
68
|
},
|
|
69
69
|
defaultConfiguration: {
|
|
70
|
-
level:
|
|
70
|
+
level: "error",
|
|
71
71
|
},
|
|
72
|
-
helpUri:
|
|
72
|
+
helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
|
|
73
73
|
};
|
|
74
74
|
ruleInfo = { descriptor, index: rulesMap.size };
|
|
75
75
|
rulesMap.set(reasonKey, ruleInfo);
|
|
@@ -77,7 +77,7 @@ export function generateSarifReport(scanResults, options) {
|
|
|
77
77
|
sarifResults.push({
|
|
78
78
|
ruleId: ruleInfo.descriptor.id,
|
|
79
79
|
ruleIndex: ruleInfo.index,
|
|
80
|
-
level: ruleInfo.descriptor.defaultConfiguration?.level ||
|
|
80
|
+
level: ruleInfo.descriptor.defaultConfiguration?.level || "error",
|
|
81
81
|
message: {
|
|
82
82
|
text: `[SecureFlow] ${violation.reason} passed to console call: "${violation.text}"`,
|
|
83
83
|
},
|
|
@@ -85,7 +85,7 @@ export function generateSarifReport(scanResults, options) {
|
|
|
85
85
|
{
|
|
86
86
|
physicalLocation: {
|
|
87
87
|
artifactLocation: {
|
|
88
|
-
uri: fileResult.path.replace(/\\/g,
|
|
88
|
+
uri: fileResult.path.replace(/\\/g, "/"),
|
|
89
89
|
},
|
|
90
90
|
region: {
|
|
91
91
|
startLine: Math.max(1, violation.line),
|
|
@@ -105,18 +105,18 @@ export function generateSarifReport(scanResults, options) {
|
|
|
105
105
|
const rulesArray = Array.from(rulesMap.values()).map((r) => r.descriptor);
|
|
106
106
|
if (rulesArray.length === 0) {
|
|
107
107
|
// Appended `!` to override 'undefined' error resulting from Record<string, ...> signature
|
|
108
|
-
rulesArray.push(DEFAULT_RULE_DEFINITIONS[
|
|
108
|
+
rulesArray.push(DEFAULT_RULE_DEFINITIONS["generic-secret-logging"]);
|
|
109
109
|
}
|
|
110
110
|
return {
|
|
111
|
-
$schema:
|
|
112
|
-
version:
|
|
111
|
+
$schema: "https://json.schemastore.org/sarif-2.1.0.json",
|
|
112
|
+
version: "2.1.0",
|
|
113
113
|
runs: [
|
|
114
114
|
{
|
|
115
115
|
tool: {
|
|
116
116
|
driver: {
|
|
117
|
-
name:
|
|
117
|
+
name: "SecureFlow CLI",
|
|
118
118
|
semanticVersion: version,
|
|
119
|
-
informationUri:
|
|
119
|
+
informationUri: "https://github.com/GauravKarakoti/SecureFlow",
|
|
120
120
|
rules: rulesArray,
|
|
121
121
|
},
|
|
122
122
|
},
|
package/dist/sarif.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sarif.js","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sarif.js","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"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"}
|
package/dist/scanner.d.ts
CHANGED
|
@@ -85,7 +85,7 @@ export interface FileScanResult {
|
|
|
85
85
|
}
|
|
86
86
|
/** Scan one staged blob. */
|
|
87
87
|
export declare function scanFile(path: string, content: string): FileScanResult;
|
|
88
|
-
export type OutputFormat =
|
|
88
|
+
export type OutputFormat = "text" | "json" | "sarif";
|
|
89
89
|
/**
|
|
90
90
|
* Format scan results based on the chosen output format ('text' | 'json' | 'sarif').
|
|
91
91
|
*/
|
package/dist/scanner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,6BAA6B;AAC7B,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,6BAA6B;AAC7B,MAAM,WAAW,SAAS;IACxB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB;AAwFD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAa,CAAC;AAE5C,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CASzE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAKD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA4EzD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYjF;AAED,uCAAuC;AACvC,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CA2B7D;AAED,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,4BAA4B;AAC5B,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAUtE;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EAAE,EACzB,MAAM,GAAE,YAAqB,GAC5B,MAAM,CAmBR"}
|
package/dist/scanner.js
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
* the part that decides whether a commit is blocked can actually be tested
|
|
7
7
|
* (#593).
|
|
8
8
|
*/
|
|
9
|
-
import { formatSarifJson } from
|
|
9
|
+
import { formatSarifJson } from "./sarif.js";
|
|
10
10
|
/** Console methods that put their arguments somewhere durable. */
|
|
11
|
-
const CONSOLE_METHODS = [
|
|
11
|
+
const CONSOLE_METHODS = ["log", "info", "warn", "error", "debug", "trace", "table", "dir"];
|
|
12
12
|
/**
|
|
13
13
|
* Start of a console call. Whitespace is permitted around the dot and the
|
|
14
14
|
* parenthesis because a formatter will put it there.
|
|
15
15
|
*/
|
|
16
|
-
const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join(
|
|
16
|
+
const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join("|")})\\s*\\(`, "g");
|
|
17
17
|
/**
|
|
18
18
|
* What makes an argument list suspicious.
|
|
19
19
|
*
|
|
@@ -22,26 +22,71 @@ const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join('|'
|
|
|
22
22
|
* expression does.
|
|
23
23
|
*/
|
|
24
24
|
const INDICATORS = [
|
|
25
|
-
[
|
|
26
|
-
|
|
25
|
+
[
|
|
26
|
+
"environment variable",
|
|
27
|
+
/\b(?:process\s*\.\s*env|import\s*\.\s*meta\s*\.\s*env|Deno\s*\.\s*env|os\s*\.\s*environ)\b/,
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"secret-named identifier",
|
|
31
|
+
/\b\w*(?:password|passwd|secret|token|credential|apikey|privatekey)\w*\b/i,
|
|
32
|
+
],
|
|
27
33
|
// `key` and `auth` on their own are common enough in ordinary code
|
|
28
34
|
// (`keyof`, `authorised`, `keys`) that they are only flagged when they read
|
|
29
35
|
// as a whole word or as an obvious compound.
|
|
30
|
-
[
|
|
36
|
+
[
|
|
37
|
+
"secret-named identifier",
|
|
38
|
+
/\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|auth[_-]?token|authorization)\b/i,
|
|
39
|
+
],
|
|
31
40
|
];
|
|
32
41
|
/** Extensions never worth scanning as source text. */
|
|
33
42
|
const BINARY_EXTENSIONS = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
".png",
|
|
44
|
+
".jpg",
|
|
45
|
+
".jpeg",
|
|
46
|
+
".gif",
|
|
47
|
+
".ico",
|
|
48
|
+
".webp",
|
|
49
|
+
".avif",
|
|
50
|
+
".bmp",
|
|
51
|
+
".tiff",
|
|
52
|
+
".pdf",
|
|
53
|
+
".zip",
|
|
54
|
+
".gz",
|
|
55
|
+
".tar",
|
|
56
|
+
".bz2",
|
|
57
|
+
".7z",
|
|
58
|
+
".rar",
|
|
59
|
+
".woff",
|
|
60
|
+
".woff2",
|
|
61
|
+
".ttf",
|
|
62
|
+
".otf",
|
|
63
|
+
".eot",
|
|
64
|
+
".mp3",
|
|
65
|
+
".mp4",
|
|
66
|
+
".wav",
|
|
67
|
+
".mov",
|
|
68
|
+
".avi",
|
|
69
|
+
".webm",
|
|
70
|
+
".so",
|
|
71
|
+
".dylib",
|
|
72
|
+
".dll",
|
|
73
|
+
".exe",
|
|
74
|
+
".wasm",
|
|
75
|
+
".class",
|
|
76
|
+
".jar",
|
|
77
|
+
".sqlite",
|
|
78
|
+
".db",
|
|
40
79
|
];
|
|
41
80
|
/** Generated files that are large, uninteresting, and full of hashes. */
|
|
42
81
|
const GENERATED_FILES = [
|
|
43
|
-
|
|
44
|
-
|
|
82
|
+
"package-lock.json",
|
|
83
|
+
"yarn.lock",
|
|
84
|
+
"pnpm-lock.yaml",
|
|
85
|
+
"bun.lockb",
|
|
86
|
+
"composer.lock",
|
|
87
|
+
"Cargo.lock",
|
|
88
|
+
"Gemfile.lock",
|
|
89
|
+
"poetry.lock",
|
|
45
90
|
];
|
|
46
91
|
/**
|
|
47
92
|
* Bytes above which a staged blob is skipped.
|
|
@@ -53,12 +98,12 @@ export const MAX_SCANNED_BYTES = 512 * 1024;
|
|
|
53
98
|
/** Whether `path` should be scanned at all. */
|
|
54
99
|
export function shouldScanFile(path, byteLength) {
|
|
55
100
|
const lower = path.toLowerCase();
|
|
56
|
-
const basename = lower.split(
|
|
101
|
+
const basename = lower.split("/").pop() ?? lower;
|
|
57
102
|
if (GENERATED_FILES.some((name) => basename === name.toLowerCase()))
|
|
58
103
|
return false;
|
|
59
104
|
if (BINARY_EXTENSIONS.some((ext) => lower.endsWith(ext)))
|
|
60
105
|
return false;
|
|
61
|
-
if (typeof byteLength ===
|
|
106
|
+
if (typeof byteLength === "number" && byteLength > MAX_SCANNED_BYTES)
|
|
62
107
|
return false;
|
|
63
108
|
return true;
|
|
64
109
|
}
|
|
@@ -69,10 +114,10 @@ export function shouldScanFile(path, byteLength) {
|
|
|
69
114
|
* extension, since a staged blob can be anything.
|
|
70
115
|
*/
|
|
71
116
|
export function looksBinary(content) {
|
|
72
|
-
return content.includes(
|
|
117
|
+
return content.includes("\u0000");
|
|
73
118
|
}
|
|
74
119
|
/** Filler used where a string literal's contents were. */
|
|
75
|
-
const MASK_CHAR =
|
|
120
|
+
const MASK_CHAR = "·";
|
|
76
121
|
/**
|
|
77
122
|
* Blank out the *contents* of string literals, preserving length.
|
|
78
123
|
*
|
|
@@ -92,7 +137,7 @@ const MASK_CHAR = '·';
|
|
|
92
137
|
* the rest of the file.
|
|
93
138
|
*/
|
|
94
139
|
export function maskStringLiterals(source) {
|
|
95
|
-
const out = source.split(
|
|
140
|
+
const out = source.split("");
|
|
96
141
|
let index = 0;
|
|
97
142
|
while (index < out.length) {
|
|
98
143
|
const char = out[index];
|
|
@@ -100,24 +145,24 @@ export function maskStringLiterals(source) {
|
|
|
100
145
|
// cursor but leaves the text in the output, so the commented-out code was
|
|
101
146
|
// still scanned. The old detector only handled `//` at the very start of a
|
|
102
147
|
// trimmed line, so a trailing comment was scanned as code either way.
|
|
103
|
-
if (char ===
|
|
104
|
-
while (index < out.length && out[index] !==
|
|
148
|
+
if (char === "/" && out[index + 1] === "/") {
|
|
149
|
+
while (index < out.length && out[index] !== "\n") {
|
|
105
150
|
out[index] = MASK_CHAR;
|
|
106
151
|
index += 1;
|
|
107
152
|
}
|
|
108
153
|
continue;
|
|
109
154
|
}
|
|
110
|
-
if (char ===
|
|
155
|
+
if (char === "/" && out[index + 1] === "*") {
|
|
111
156
|
index += 2;
|
|
112
|
-
while (index < out.length && !(out[index] ===
|
|
113
|
-
if (out[index] !==
|
|
157
|
+
while (index < out.length && !(out[index] === "*" && out[index + 1] === "/")) {
|
|
158
|
+
if (out[index] !== "\n")
|
|
114
159
|
out[index] = MASK_CHAR;
|
|
115
160
|
index += 1;
|
|
116
161
|
}
|
|
117
162
|
index += 2;
|
|
118
163
|
continue;
|
|
119
164
|
}
|
|
120
|
-
if (char !== '"' && char !== "'" && char !==
|
|
165
|
+
if (char !== '"' && char !== "'" && char !== "`") {
|
|
121
166
|
index += 1;
|
|
122
167
|
continue;
|
|
123
168
|
}
|
|
@@ -125,11 +170,11 @@ export function maskStringLiterals(source) {
|
|
|
125
170
|
index += 1;
|
|
126
171
|
while (index < out.length) {
|
|
127
172
|
const current = out[index];
|
|
128
|
-
if (current ===
|
|
173
|
+
if (current === "\\") {
|
|
129
174
|
// Escaped character: mask both, and never let it terminate the literal.
|
|
130
|
-
if (out[index] !==
|
|
175
|
+
if (out[index] !== "\n")
|
|
131
176
|
out[index] = MASK_CHAR;
|
|
132
|
-
if (index + 1 < out.length && out[index + 1] !==
|
|
177
|
+
if (index + 1 < out.length && out[index + 1] !== "\n")
|
|
133
178
|
out[index + 1] = MASK_CHAR;
|
|
134
179
|
index += 2;
|
|
135
180
|
continue;
|
|
@@ -140,28 +185,28 @@ export function maskStringLiterals(source) {
|
|
|
140
185
|
}
|
|
141
186
|
// An unterminated quote must not swallow the rest of the file. Only a
|
|
142
187
|
// template literal legally spans lines.
|
|
143
|
-
if (current ===
|
|
188
|
+
if (current === "\n" && quote !== "`")
|
|
144
189
|
break;
|
|
145
190
|
// `${ … }` inside a template literal is code. Leave it visible, tracking
|
|
146
191
|
// brace depth so a nested object literal does not end it early.
|
|
147
|
-
if (quote ===
|
|
192
|
+
if (quote === "`" && current === "$" && out[index + 1] === "{") {
|
|
148
193
|
let depth = 1;
|
|
149
194
|
index += 2;
|
|
150
195
|
while (index < out.length && depth > 0) {
|
|
151
|
-
if (out[index] ===
|
|
196
|
+
if (out[index] === "{")
|
|
152
197
|
depth += 1;
|
|
153
|
-
else if (out[index] ===
|
|
198
|
+
else if (out[index] === "}")
|
|
154
199
|
depth -= 1;
|
|
155
200
|
index += 1;
|
|
156
201
|
}
|
|
157
202
|
continue;
|
|
158
203
|
}
|
|
159
|
-
if (current !==
|
|
204
|
+
if (current !== "\n")
|
|
160
205
|
out[index] = MASK_CHAR;
|
|
161
206
|
index += 1;
|
|
162
207
|
}
|
|
163
208
|
}
|
|
164
|
-
return out.join(
|
|
209
|
+
return out.join("");
|
|
165
210
|
}
|
|
166
211
|
/**
|
|
167
212
|
* Text of the balanced argument list starting at `openParen`, or null when the
|
|
@@ -181,9 +226,9 @@ export function maskStringLiterals(source) {
|
|
|
181
226
|
export function readArgumentList(source, openParen) {
|
|
182
227
|
let depth = 0;
|
|
183
228
|
for (let i = openParen; i < source.length; i += 1) {
|
|
184
|
-
if (source[i] ===
|
|
229
|
+
if (source[i] === "(")
|
|
185
230
|
depth += 1;
|
|
186
|
-
else if (source[i] ===
|
|
231
|
+
else if (source[i] === ")") {
|
|
187
232
|
depth -= 1;
|
|
188
233
|
if (depth === 0)
|
|
189
234
|
return source.slice(openParen + 1, i);
|
|
@@ -195,7 +240,7 @@ export function readArgumentList(source, openParen) {
|
|
|
195
240
|
export function lineOf(source, offset) {
|
|
196
241
|
let line = 1;
|
|
197
242
|
for (let i = 0; i < offset && i < source.length; i += 1) {
|
|
198
|
-
if (source[i] ===
|
|
243
|
+
if (source[i] === "\n")
|
|
199
244
|
line += 1;
|
|
200
245
|
}
|
|
201
246
|
return line;
|
|
@@ -226,7 +271,7 @@ export function findSecretLogging(source) {
|
|
|
226
271
|
const line = lineOf(masked, match.index);
|
|
227
272
|
violations.push({
|
|
228
273
|
line,
|
|
229
|
-
text: (lines[line - 1] ??
|
|
274
|
+
text: (lines[line - 1] ?? "").trim(),
|
|
230
275
|
reason: indicator[0],
|
|
231
276
|
});
|
|
232
277
|
}
|
|
@@ -234,26 +279,26 @@ export function findSecretLogging(source) {
|
|
|
234
279
|
}
|
|
235
280
|
/** Scan one staged blob. */
|
|
236
281
|
export function scanFile(path, content) {
|
|
237
|
-
if (!shouldScanFile(path, Buffer.byteLength(content,
|
|
238
|
-
return { path, violations: [], skipped:
|
|
282
|
+
if (!shouldScanFile(path, Buffer.byteLength(content, "utf-8"))) {
|
|
283
|
+
return { path, violations: [], skipped: "excluded by type or size" };
|
|
239
284
|
}
|
|
240
285
|
if (looksBinary(content)) {
|
|
241
|
-
return { path, violations: [], skipped:
|
|
286
|
+
return { path, violations: [], skipped: "binary content" };
|
|
242
287
|
}
|
|
243
288
|
return { path, violations: findSecretLogging(content) };
|
|
244
289
|
}
|
|
245
290
|
/**
|
|
246
291
|
* Format scan results based on the chosen output format ('text' | 'json' | 'sarif').
|
|
247
292
|
*/
|
|
248
|
-
export function formatScanResults(results, format =
|
|
249
|
-
if (format ===
|
|
293
|
+
export function formatScanResults(results, format = "text") {
|
|
294
|
+
if (format === "json") {
|
|
250
295
|
return JSON.stringify(results, null, 2);
|
|
251
296
|
}
|
|
252
|
-
if (format ===
|
|
297
|
+
if (format === "sarif") {
|
|
253
298
|
return formatSarifJson(results);
|
|
254
299
|
}
|
|
255
300
|
// Default text summary
|
|
256
|
-
let text =
|
|
301
|
+
let text = "";
|
|
257
302
|
for (const r of results) {
|
|
258
303
|
for (const v of r.violations) {
|
|
259
304
|
text += `🚨 [SecureFlow] Secret logging detected in ${r.path}:${v.line}\n`;
|
package/dist/scanner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAY7C,kEAAkE;AAClE,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAE3F;;;GAGG;AACH,MAAM,YAAY,GAAG,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "secureflow-cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Pre-commit secret logging detector for secure development workflows",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"secureflow": "./dist/index.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"build": "tsc",
|
|
11
|
-
"prepare": "npm run build",
|
|
12
|
-
"publish": "npm publish --access public",
|
|
13
|
-
"test": "vitest run",
|
|
14
|
-
"test:watch": "vitest"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"security",
|
|
18
|
-
"secrets",
|
|
19
|
-
"scanner",
|
|
20
|
-
"pre-commit",
|
|
21
|
-
"husky",
|
|
22
|
-
"secureflow"
|
|
23
|
-
],
|
|
24
|
-
"author": "Gaurav Karakoti",
|
|
25
|
-
"license": "ISC",
|
|
26
|
-
"type": "module",
|
|
27
|
-
"files": [
|
|
28
|
-
"dist"
|
|
29
|
-
],
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@types/node": "^26.4.
|
|
32
|
-
"typescript": "^6",
|
|
33
|
-
"vitest": "^
|
|
34
|
-
}
|
|
35
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "secureflow-cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Pre-commit secret logging detector for secure development workflows",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"secureflow": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"prepare": "npm run build",
|
|
12
|
+
"publish": "npm publish --access public",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"security",
|
|
18
|
+
"secrets",
|
|
19
|
+
"scanner",
|
|
20
|
+
"pre-commit",
|
|
21
|
+
"husky",
|
|
22
|
+
"secureflow"
|
|
23
|
+
],
|
|
24
|
+
"author": "Gaurav Karakoti",
|
|
25
|
+
"license": "ISC",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^26.4.1",
|
|
32
|
+
"typescript": "^6",
|
|
33
|
+
"vitest": "^5.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|