secureflow-cli 1.1.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 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;IACJ,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IAArD,YAAY,OAAO,EAAE,MAAM,EAAW,KAAK,CAAC,EAAE,OAAO,EAGpD;CACF;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"}
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 'child_process';
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 = 'GitError';
37
+ this.name = "GitError";
38
38
  }
39
39
  }
40
40
  function git(args) {
41
- return execFileSync('git', args, {
42
- encoding: 'utf-8',
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(['rev-parse', '--is-inside-work-tree']).trim() === 'true';
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(['diff', '--cached', '--name-only', '-z', '--diff-filter=ACMR']);
71
+ output = git(["diff", "--cached", "--name-only", "-z", "--diff-filter=ACMR"]);
72
72
  }
73
73
  catch (error) {
74
74
  throw new GitError(isGitRepository()
75
- ? 'Could not list staged files. `git diff --cached` failed.'
76
- : 'Not a git repository (or git is not on PATH).', error);
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('\u0000').filter((entry) => entry.length > 0);
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(['show', `:${path}`]);
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;IACK,KAAK;IAA3C,YAAY,OAAe,EAAW,KAAe;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;qBADqB,KAAK;QAEzC,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"}
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,69 +1,145 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * SecureFlow pre-commit hook.
4
- *
5
- * The shell only: read the staged set, scan each blob, report, exit. The
6
- * detection logic lives in `./scanner` and the git access in `./git`, so both
7
- * can be tested without a process exit or a repository (#593).
8
- */
9
- import { GitError, getStagedFiles, readStagedContent } from './git.js';
10
- import { scanFile } from './scanner.js';
11
- const VERBOSE = process.argv.includes('--verbose');
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");
8
+ function parseFormatArg() {
9
+ const formatIndex = process.argv.findIndex((arg) => arg === "--format");
10
+ if (formatIndex !== -1) {
11
+ const valStr = process.argv[formatIndex + 1];
12
+ if (valStr) {
13
+ const val = valStr.toLowerCase();
14
+ if (val === "sarif" || val === "json" || val === "text") {
15
+ return val;
16
+ }
17
+ }
18
+ }
19
+ return "text";
20
+ }
21
+ function parseOutputArg() {
22
+ const outIndex = process.argv.findIndex((arg) => arg === "-o" || arg === "--output");
23
+ if (outIndex !== -1) {
24
+ const valStr = process.argv[outIndex + 1];
25
+ if (valStr) {
26
+ return valStr;
27
+ }
28
+ }
29
+ return null;
30
+ }
12
31
  function reportSkipped(result) {
13
32
  if (VERBOSE && result.skipped) {
14
- console.log(` ↷ skipped ${result.path} (${result.skipped})`);
33
+ console.log(` ↷ skipped ${result.path} (${result.skipped})`);
15
34
  }
16
35
  }
17
36
  function reportViolations(result) {
18
37
  for (const violation of result.violations) {
19
38
  console.error(`🚨 [SecureFlow] Secret logging detected in ${result.path}:${violation.line}`);
20
- console.error(` -> ${violation.text}`);
21
- console.error(` why: ${violation.reason} passed to a console call`);
39
+ console.error(` -> ${violation.text}`);
40
+ console.error(` why: ${violation.reason} passed to a console call`);
22
41
  }
23
42
  }
24
- function main() {
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() {
71
+ const format = parseFormatArg();
72
+ const outputPath = parseOutputArg();
25
73
  let staged;
26
74
  try {
27
75
  staged = getStagedFiles();
28
76
  }
29
77
  catch (error) {
30
- // Distinguished rather than collapsed into "Are you in a git repository?",
31
- // which was previously printed for a buffer overflow, a missing git binary
32
- // and a genuine non-repository alike.
33
78
  console.error(`❌ [SecureFlow] ${error instanceof GitError ? error.message : String(error)}`);
34
79
  return 1;
35
80
  }
36
- if (staged.length === 0) {
37
- console.log('✅ SecureFlow scan passed (nothing staged).');
38
- return 0;
39
- }
81
+ const fileResults = [];
40
82
  const unreadable = [];
83
+ const stagedForAi = [];
41
84
  let violationCount = 0;
42
- for (const path of staged) {
43
- // The staged blob, not the working-tree file. This is the whole fix: the
44
- // hook now checks the content that is about to be committed rather than
45
- // whatever happens to be on disk when it runs.
46
- const content = readStagedContent(path);
47
- if (content === null) {
48
- unreadable.push(path);
49
- continue;
85
+ if (staged.length > 0) {
86
+ for (const path of staged) {
87
+ const content = readStagedContent(path);
88
+ if (content === null) {
89
+ unreadable.push(path);
90
+ continue;
91
+ }
92
+ stagedForAi.push({ path, content });
93
+ const result = scanFile(path, content);
94
+ fileResults.push(result);
95
+ if (format === "text") {
96
+ reportSkipped(result);
97
+ reportViolations(result);
98
+ }
99
+ violationCount += result.violations.length;
100
+ }
101
+ }
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);
50
110
  }
51
- const result = scanFile(path, content);
52
- reportSkipped(result);
53
- reportViolations(result);
54
- violationCount += result.violations.length;
55
111
  }
56
- if (unreadable.length > 0) {
57
- // Named rather than silently passed. A file we could not read is a file we
58
- // did not check, and saying so is the difference between a gap and a lie.
59
- console.warn(`⚠️ [SecureFlow] Could not read ${unreadable.length} staged entr${unreadable.length === 1 ? 'y' : 'ies'} (submodule, symlink or conflicted): ${unreadable.join(', ')}`);
112
+ const aiViolationCount = aiFindings.filter((f) => f.severity === "HIGH" || f.severity === "CRITICAL").length;
113
+ if (format === "sarif" || format === "json") {
114
+ const outputString = formatScanResults(fileResults, format);
115
+ if (outputPath) {
116
+ fs.writeFileSync(outputPath, outputString, "utf-8");
117
+ console.log(`📄 [SecureFlow] Scan report exported in ${format.toUpperCase()} format to ${outputPath}`);
118
+ }
119
+ else {
120
+ console.log(outputString);
121
+ }
122
+ }
123
+ else if (outputPath) {
124
+ const textOutput = formatScanResults(fileResults, "text");
125
+ fs.writeFileSync(outputPath, textOutput, "utf-8");
126
+ console.log(`📄 [SecureFlow] Scan report written to ${outputPath}`);
60
127
  }
61
- if (violationCount > 0) {
62
- console.error(`\n❌ SecureFlow blocked this commit: ${violationCount} secret-logging violation${violationCount === 1 ? '' : 's'}. Remove the exposed secrets/env variables, then re-stage.`);
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(", ")}`);
130
+ }
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.`);
136
+ }
63
137
  return 1;
64
138
  }
65
- console.log(`✅ SecureFlow scan passed (${staged.length} staged file(s)).`);
139
+ if (format === "text") {
140
+ console.log(`✅ SecureFlow scan passed (${staged.length} staged file(s)).`);
141
+ }
66
142
  return 0;
67
143
  }
68
- process.exit(main());
144
+ main().then((code) => process.exit(code));
69
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":"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"}
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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * SARIF (Static Analysis Results Interchange Format) Exporter for SecureFlow CLI (#728)
3
+ *
4
+ * Converts CLI scan results into standardized OASIS SARIF v2.1.0 schema format
5
+ * for direct ingestion by GitHub Advanced Security, GitLab Security Dashboards, and enterprise CI/CD systems.
6
+ */
7
+ import type { FileScanResult } from "./scanner.js";
8
+ export interface SarifArtifactLocation {
9
+ uri: string;
10
+ uriBaseId?: string;
11
+ }
12
+ export interface SarifRegion {
13
+ startLine: number;
14
+ startColumn?: number;
15
+ endLine?: number;
16
+ endColumn?: number;
17
+ snippet?: {
18
+ text: string;
19
+ };
20
+ }
21
+ export interface SarifPhysicalLocation {
22
+ artifactLocation: SarifArtifactLocation;
23
+ region: SarifRegion;
24
+ }
25
+ export interface SarifLocation {
26
+ physicalLocation: SarifPhysicalLocation;
27
+ }
28
+ export interface SarifReportingDescriptor {
29
+ id: string;
30
+ name: string;
31
+ shortDescription: {
32
+ text: string;
33
+ };
34
+ fullDescription?: {
35
+ text: string;
36
+ };
37
+ defaultConfiguration?: {
38
+ level: "error" | "warning" | "note" | "none";
39
+ };
40
+ helpUri?: string;
41
+ properties?: Record<string, unknown>;
42
+ }
43
+ export interface SarifResult {
44
+ ruleId: string;
45
+ ruleIndex?: number;
46
+ level: "error" | "warning" | "note" | "none";
47
+ message: {
48
+ text: string;
49
+ };
50
+ locations: SarifLocation[];
51
+ properties?: Record<string, unknown>;
52
+ }
53
+ export interface SarifRun {
54
+ tool: {
55
+ driver: {
56
+ name: string;
57
+ organization?: string;
58
+ version?: string;
59
+ semanticVersion?: string;
60
+ informationUri?: string;
61
+ rules: SarifReportingDescriptor[];
62
+ };
63
+ };
64
+ results: SarifResult[];
65
+ }
66
+ export interface SarifDocument {
67
+ $schema: string;
68
+ version: "2.1.0";
69
+ runs: SarifRun[];
70
+ }
71
+ /**
72
+ * Maps CLI scan results into a valid OASIS SARIF v2.1.0 document object.
73
+ */
74
+ export declare function generateSarifReport(scanResults: FileScanResult[], options?: {
75
+ toolVersion?: string;
76
+ repoUri?: string;
77
+ }): SarifDocument;
78
+ /**
79
+ * Format SARIF report as pretty JSON string.
80
+ */
81
+ export declare function formatSarifJson(scanResults: FileScanResult[], options?: {
82
+ toolVersion?: string;
83
+ }): string;
84
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +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,CAC7B,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,MAAM,CAGR"}
package/dist/sarif.js ADDED
@@ -0,0 +1,135 @@
1
+ /**
2
+ * SARIF (Static Analysis Results Interchange Format) Exporter for SecureFlow CLI (#728)
3
+ *
4
+ * Converts CLI scan results into standardized OASIS SARIF v2.1.0 schema format
5
+ * for direct ingestion by GitHub Advanced Security, GitLab Security Dashboards, and enterprise CI/CD systems.
6
+ */
7
+ const DEFAULT_RULE_DEFINITIONS = {
8
+ "environment variable": {
9
+ id: "SECUREFLOW-001",
10
+ name: "ConsoleSecretLoggingEnvironmentVariable",
11
+ shortDescription: {
12
+ text: "Console logging of environment variable containing potential secret",
13
+ },
14
+ fullDescription: {
15
+ text: "Passing process.env or other environment variable getters into console methods exposes credentials in build logs or standard output.",
16
+ },
17
+ defaultConfiguration: {
18
+ level: "error",
19
+ },
20
+ helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
21
+ },
22
+ "secret-named identifier": {
23
+ id: "SECUREFLOW-002",
24
+ name: "ConsoleSecretLoggingSecretIdentifier",
25
+ shortDescription: {
26
+ text: "Console logging of secret-named identifier or credential parameter",
27
+ },
28
+ fullDescription: {
29
+ text: "Identifiers containing secret, password, apikey, token, or auth parameters passed directly into console logging statements.",
30
+ },
31
+ defaultConfiguration: {
32
+ level: "error",
33
+ },
34
+ helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
35
+ },
36
+ "generic-secret-logging": {
37
+ id: "SECUREFLOW-000",
38
+ name: "ConsoleSecretLoggingGeneric",
39
+ shortDescription: {
40
+ text: "Potential secret credential logging in console output",
41
+ },
42
+ defaultConfiguration: {
43
+ level: "error",
44
+ },
45
+ helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
46
+ },
47
+ };
48
+ /**
49
+ * Maps CLI scan results into a valid OASIS SARIF v2.1.0 document object.
50
+ */
51
+ export function generateSarifReport(scanResults, options) {
52
+ const version = options?.toolVersion || "0.1.0";
53
+ const rulesMap = new Map();
54
+ const sarifResults = [];
55
+ for (const fileResult of scanResults) {
56
+ if (!fileResult.violations || fileResult.violations.length === 0) {
57
+ continue;
58
+ }
59
+ for (const violation of fileResult.violations) {
60
+ const reasonKey = violation.reason || "generic-secret-logging";
61
+ let ruleInfo = rulesMap.get(reasonKey);
62
+ if (!ruleInfo) {
63
+ const descriptor = DEFAULT_RULE_DEFINITIONS[reasonKey] || {
64
+ id: `SECUREFLOW-${rulesMap.size + 100}`,
65
+ name: `ConsoleSecretLoggingCustomRule${rulesMap.size + 1}`,
66
+ shortDescription: {
67
+ text: `Console logging of ${violation.reason}`,
68
+ },
69
+ defaultConfiguration: {
70
+ level: "error",
71
+ },
72
+ helpUri: "https://github.com/GauravKarakoti/SecureFlow#rules",
73
+ };
74
+ ruleInfo = { descriptor, index: rulesMap.size };
75
+ rulesMap.set(reasonKey, ruleInfo);
76
+ }
77
+ sarifResults.push({
78
+ ruleId: ruleInfo.descriptor.id,
79
+ ruleIndex: ruleInfo.index,
80
+ level: ruleInfo.descriptor.defaultConfiguration?.level || "error",
81
+ message: {
82
+ text: `[SecureFlow] ${violation.reason} passed to console call: "${violation.text}"`,
83
+ },
84
+ locations: [
85
+ {
86
+ physicalLocation: {
87
+ artifactLocation: {
88
+ uri: fileResult.path.replace(/\\/g, "/"),
89
+ },
90
+ region: {
91
+ startLine: Math.max(1, violation.line),
92
+ snippet: {
93
+ text: violation.text,
94
+ },
95
+ },
96
+ },
97
+ },
98
+ ],
99
+ properties: {
100
+ reason: violation.reason,
101
+ },
102
+ });
103
+ }
104
+ }
105
+ const rulesArray = Array.from(rulesMap.values()).map((r) => r.descriptor);
106
+ if (rulesArray.length === 0) {
107
+ // Appended `!` to override 'undefined' error resulting from Record<string, ...> signature
108
+ rulesArray.push(DEFAULT_RULE_DEFINITIONS["generic-secret-logging"]);
109
+ }
110
+ return {
111
+ $schema: "https://json.schemastore.org/sarif-2.1.0.json",
112
+ version: "2.1.0",
113
+ runs: [
114
+ {
115
+ tool: {
116
+ driver: {
117
+ name: "SecureFlow CLI",
118
+ semanticVersion: version,
119
+ informationUri: "https://github.com/GauravKarakoti/SecureFlow",
120
+ rules: rulesArray,
121
+ },
122
+ },
123
+ results: sarifResults,
124
+ },
125
+ ],
126
+ };
127
+ }
128
+ /**
129
+ * Format SARIF report as pretty JSON string.
130
+ */
131
+ export function formatSarifJson(scanResults, options) {
132
+ const sarifDoc = generateSarifReport(scanResults, options);
133
+ return JSON.stringify(sarifDoc, null, 2);
134
+ }
135
+ //# sourceMappingURL=sarif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.js","sourceRoot":"","sources":["../src/sarif.ts"],"names":[],"mappings":"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"}
package/dist/scanner.d.ts CHANGED
@@ -85,4 +85,9 @@ 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 = "text" | "json" | "sarif";
89
+ /**
90
+ * Format scan results based on the chosen output format ('text' | 'json' | 'sarif').
91
+ */
92
+ export declare function formatScanResults(results: FileScanResult[], format?: OutputFormat): string;
88
93
  //# sourceMappingURL=scanner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,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;AA8CD;;;;;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"}
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,13 +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 "./sarif.js";
9
10
  /** Console methods that put their arguments somewhere durable. */
10
- const CONSOLE_METHODS = ['log', 'info', 'warn', 'error', 'debug', 'trace', 'table', 'dir'];
11
+ const CONSOLE_METHODS = ["log", "info", "warn", "error", "debug", "trace", "table", "dir"];
11
12
  /**
12
13
  * Start of a console call. Whitespace is permitted around the dot and the
13
14
  * parenthesis because a formatter will put it there.
14
15
  */
15
- const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join('|')})\\s*\\(`, 'g');
16
+ const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join("|")})\\s*\\(`, "g");
16
17
  /**
17
18
  * What makes an argument list suspicious.
18
19
  *
@@ -21,26 +22,71 @@ const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join('|'
21
22
  * expression does.
22
23
  */
23
24
  const INDICATORS = [
24
- ['environment variable', /\b(?:process\s*\.\s*env|import\s*\.\s*meta\s*\.\s*env|Deno\s*\.\s*env|os\s*\.\s*environ)\b/],
25
- ['secret-named identifier', /\b\w*(?:password|passwd|secret|token|credential|apikey|privatekey)\w*\b/i],
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
+ ],
26
33
  // `key` and `auth` on their own are common enough in ordinary code
27
34
  // (`keyof`, `authorised`, `keys`) that they are only flagged when they read
28
35
  // as a whole word or as an obvious compound.
29
- ['secret-named identifier', /\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|auth[_-]?token|authorization)\b/i],
36
+ [
37
+ "secret-named identifier",
38
+ /\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|auth[_-]?token|authorization)\b/i,
39
+ ],
30
40
  ];
31
41
  /** Extensions never worth scanning as source text. */
32
42
  const BINARY_EXTENSIONS = [
33
- '.png', '.jpg', '.jpeg', '.gif', '.ico', '.webp', '.avif', '.bmp', '.tiff',
34
- '.pdf', '.zip', '.gz', '.tar', '.bz2', '.7z', '.rar',
35
- '.woff', '.woff2', '.ttf', '.otf', '.eot',
36
- '.mp3', '.mp4', '.wav', '.mov', '.avi', '.webm',
37
- '.so', '.dylib', '.dll', '.exe', '.wasm', '.class', '.jar',
38
- '.sqlite', '.db',
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",
39
79
  ];
40
80
  /** Generated files that are large, uninteresting, and full of hashes. */
41
81
  const GENERATED_FILES = [
42
- 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb', 'composer.lock',
43
- 'Cargo.lock', 'Gemfile.lock', 'poetry.lock',
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",
44
90
  ];
45
91
  /**
46
92
  * Bytes above which a staged blob is skipped.
@@ -52,12 +98,12 @@ export const MAX_SCANNED_BYTES = 512 * 1024;
52
98
  /** Whether `path` should be scanned at all. */
53
99
  export function shouldScanFile(path, byteLength) {
54
100
  const lower = path.toLowerCase();
55
- const basename = lower.split('/').pop() ?? lower;
101
+ const basename = lower.split("/").pop() ?? lower;
56
102
  if (GENERATED_FILES.some((name) => basename === name.toLowerCase()))
57
103
  return false;
58
104
  if (BINARY_EXTENSIONS.some((ext) => lower.endsWith(ext)))
59
105
  return false;
60
- if (typeof byteLength === 'number' && byteLength > MAX_SCANNED_BYTES)
106
+ if (typeof byteLength === "number" && byteLength > MAX_SCANNED_BYTES)
61
107
  return false;
62
108
  return true;
63
109
  }
@@ -68,10 +114,10 @@ export function shouldScanFile(path, byteLength) {
68
114
  * extension, since a staged blob can be anything.
69
115
  */
70
116
  export function looksBinary(content) {
71
- return content.includes('\u0000');
117
+ return content.includes("\u0000");
72
118
  }
73
119
  /** Filler used where a string literal's contents were. */
74
- const MASK_CHAR = '·';
120
+ const MASK_CHAR = "·";
75
121
  /**
76
122
  * Blank out the *contents* of string literals, preserving length.
77
123
  *
@@ -91,7 +137,7 @@ const MASK_CHAR = '·';
91
137
  * the rest of the file.
92
138
  */
93
139
  export function maskStringLiterals(source) {
94
- const out = source.split('');
140
+ const out = source.split("");
95
141
  let index = 0;
96
142
  while (index < out.length) {
97
143
  const char = out[index];
@@ -99,24 +145,24 @@ export function maskStringLiterals(source) {
99
145
  // cursor but leaves the text in the output, so the commented-out code was
100
146
  // still scanned. The old detector only handled `//` at the very start of a
101
147
  // trimmed line, so a trailing comment was scanned as code either way.
102
- if (char === '/' && out[index + 1] === '/') {
103
- while (index < out.length && out[index] !== '\n') {
148
+ if (char === "/" && out[index + 1] === "/") {
149
+ while (index < out.length && out[index] !== "\n") {
104
150
  out[index] = MASK_CHAR;
105
151
  index += 1;
106
152
  }
107
153
  continue;
108
154
  }
109
- if (char === '/' && out[index + 1] === '*') {
155
+ if (char === "/" && out[index + 1] === "*") {
110
156
  index += 2;
111
- while (index < out.length && !(out[index] === '*' && out[index + 1] === '/')) {
112
- if (out[index] !== '\n')
157
+ while (index < out.length && !(out[index] === "*" && out[index + 1] === "/")) {
158
+ if (out[index] !== "\n")
113
159
  out[index] = MASK_CHAR;
114
160
  index += 1;
115
161
  }
116
162
  index += 2;
117
163
  continue;
118
164
  }
119
- if (char !== '"' && char !== "'" && char !== '`') {
165
+ if (char !== '"' && char !== "'" && char !== "`") {
120
166
  index += 1;
121
167
  continue;
122
168
  }
@@ -124,11 +170,11 @@ export function maskStringLiterals(source) {
124
170
  index += 1;
125
171
  while (index < out.length) {
126
172
  const current = out[index];
127
- if (current === '\\') {
173
+ if (current === "\\") {
128
174
  // Escaped character: mask both, and never let it terminate the literal.
129
- if (out[index] !== '\n')
175
+ if (out[index] !== "\n")
130
176
  out[index] = MASK_CHAR;
131
- if (index + 1 < out.length && out[index + 1] !== '\n')
177
+ if (index + 1 < out.length && out[index + 1] !== "\n")
132
178
  out[index + 1] = MASK_CHAR;
133
179
  index += 2;
134
180
  continue;
@@ -139,28 +185,28 @@ export function maskStringLiterals(source) {
139
185
  }
140
186
  // An unterminated quote must not swallow the rest of the file. Only a
141
187
  // template literal legally spans lines.
142
- if (current === '\n' && quote !== '`')
188
+ if (current === "\n" && quote !== "`")
143
189
  break;
144
190
  // `${ … }` inside a template literal is code. Leave it visible, tracking
145
191
  // brace depth so a nested object literal does not end it early.
146
- if (quote === '`' && current === '$' && out[index + 1] === '{') {
192
+ if (quote === "`" && current === "$" && out[index + 1] === "{") {
147
193
  let depth = 1;
148
194
  index += 2;
149
195
  while (index < out.length && depth > 0) {
150
- if (out[index] === '{')
196
+ if (out[index] === "{")
151
197
  depth += 1;
152
- else if (out[index] === '}')
198
+ else if (out[index] === "}")
153
199
  depth -= 1;
154
200
  index += 1;
155
201
  }
156
202
  continue;
157
203
  }
158
- if (current !== '\n')
204
+ if (current !== "\n")
159
205
  out[index] = MASK_CHAR;
160
206
  index += 1;
161
207
  }
162
208
  }
163
- return out.join('');
209
+ return out.join("");
164
210
  }
165
211
  /**
166
212
  * Text of the balanced argument list starting at `openParen`, or null when the
@@ -180,9 +226,9 @@ export function maskStringLiterals(source) {
180
226
  export function readArgumentList(source, openParen) {
181
227
  let depth = 0;
182
228
  for (let i = openParen; i < source.length; i += 1) {
183
- if (source[i] === '(')
229
+ if (source[i] === "(")
184
230
  depth += 1;
185
- else if (source[i] === ')') {
231
+ else if (source[i] === ")") {
186
232
  depth -= 1;
187
233
  if (depth === 0)
188
234
  return source.slice(openParen + 1, i);
@@ -194,7 +240,7 @@ export function readArgumentList(source, openParen) {
194
240
  export function lineOf(source, offset) {
195
241
  let line = 1;
196
242
  for (let i = 0; i < offset && i < source.length; i += 1) {
197
- if (source[i] === '\n')
243
+ if (source[i] === "\n")
198
244
  line += 1;
199
245
  }
200
246
  return line;
@@ -225,7 +271,7 @@ export function findSecretLogging(source) {
225
271
  const line = lineOf(masked, match.index);
226
272
  violations.push({
227
273
  line,
228
- text: (lines[line - 1] ?? '').trim(),
274
+ text: (lines[line - 1] ?? "").trim(),
229
275
  reason: indicator[0],
230
276
  });
231
277
  }
@@ -233,12 +279,33 @@ export function findSecretLogging(source) {
233
279
  }
234
280
  /** Scan one staged blob. */
235
281
  export function scanFile(path, content) {
236
- if (!shouldScanFile(path, Buffer.byteLength(content, 'utf-8'))) {
237
- return { path, violations: [], skipped: 'excluded by type or size' };
282
+ if (!shouldScanFile(path, Buffer.byteLength(content, "utf-8"))) {
283
+ return { path, violations: [], skipped: "excluded by type or size" };
238
284
  }
239
285
  if (looksBinary(content)) {
240
- return { path, violations: [], skipped: 'binary content' };
286
+ return { path, violations: [], skipped: "binary content" };
241
287
  }
242
288
  return { path, violations: findSecretLogging(content) };
243
289
  }
290
+ /**
291
+ * Format scan results based on the chosen output format ('text' | 'json' | 'sarif').
292
+ */
293
+ export function formatScanResults(results, format = "text") {
294
+ if (format === "json") {
295
+ return JSON.stringify(results, null, 2);
296
+ }
297
+ if (format === "sarif") {
298
+ return formatSarifJson(results);
299
+ }
300
+ // Default text summary
301
+ let text = "";
302
+ for (const r of results) {
303
+ for (const v of r.violations) {
304
+ text += `🚨 [SecureFlow] Secret logging detected in ${r.path}:${v.line}\n`;
305
+ text += ` -> ${v.text}\n`;
306
+ text += ` why: ${v.reason} passed to a console call\n`;
307
+ }
308
+ }
309
+ return text;
310
+ }
244
311
  //# sourceMappingURL=scanner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "secureflow-cli",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Pre-commit secret logging detector for secure development workflows",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
@@ -9,7 +9,9 @@
9
9
  "scripts": {
10
10
  "build": "tsc",
11
11
  "prepare": "npm run build",
12
- "publish": "npm publish --access public"
12
+ "publish": "npm publish --access public",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest"
13
15
  },
14
16
  "keywords": [
15
17
  "security",
@@ -26,7 +28,8 @@
26
28
  "dist"
27
29
  ],
28
30
  "devDependencies": {
29
- "@types/node": "^26.2.0",
30
- "typescript": "^7.0.2"
31
+ "@types/node": "^26.4.1",
32
+ "typescript": "^6",
33
+ "vitest": "^5.0.0"
31
34
  }
32
35
  }