secureflow-cli 1.2.0 → 2.1.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/exporters.d.ts +49 -0
- package/dist/exporters.d.ts.map +1 -0
- package/dist/exporters.js +187 -0
- package/dist/exporters.js.map +1 -0
- 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 +84 -21
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +41 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +62 -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 +2 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +98 -46
- package/dist/scanner.js.map +1 -1
- package/package.json +35 -35
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":"AAAA;;;;;GAKG;AA4EH,MAAM,wBAAwB,GAA6C;IACzE,sBAAsB,EAAE;QACtB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,yCAAyC;QAC/C,gBAAgB,EAAE;YAChB,IAAI,EAAE,qEAAqE;SAC5E;QACD,eAAe,EAAE;YACf,IAAI,EAAE,sIAAsI;SAC7I;QACD,oBAAoB,EAAE;YACpB,KAAK,EAAE,OAAO;SACf;QACD,OAAO,EAAE,oDAAoD;KAC9D;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,sCAAsC;QAC5C,gBAAgB,EAAE;YAChB,IAAI,EAAE,oEAAoE;SAC3E;QACD,eAAe,EAAE;YACf,IAAI,EAAE,6HAA6H;SACpI;QACD,oBAAoB,EAAE;YACpB,KAAK,EAAE,OAAO;SACf;QACD,OAAO,EAAE,oDAAoD;KAC9D;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,6BAA6B;QACnC,gBAAgB,EAAE;YAChB,IAAI,EAAE,uDAAuD;SAC9D;QACD,oBAAoB,EAAE;YACpB,KAAK,EAAE,OAAO;SACf;QACD,OAAO,EAAE,oDAAoD;KAC9D;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAA6B,EAC7B,OAGC;IAED,MAAM,OAAO,GAAG,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmE,CAAC;IAC5F,MAAM,YAAY,GAAkB,EAAE,CAAC;IAEvC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjE,SAAS;QACX,CAAC;QAED,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,IAAI,wBAAwB,CAAC;YAC/D,IAAI,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAEvC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,UAAU,GAAG,wBAAwB,CAAC,SAAS,CAAC,IAAI;oBACxD,EAAE,EAAE,cAAc,QAAQ,CAAC,IAAI,GAAG,GAAG,EAAE;oBACvC,IAAI,EAAE,iCAAiC,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE;oBAC1D,gBAAgB,EAAE;wBAChB,IAAI,EAAE,sBAAsB,SAAS,CAAC,MAAM,EAAE;qBAC/C;oBACD,oBAAoB,EAAE;wBACpB,KAAK,EAAE,OAAO;qBACf;oBACD,OAAO,EAAE,oDAAoD;iBAC9D,CAAC;gBAEF,QAAQ,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAChD,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACpC,CAAC;YAED,YAAY,CAAC,IAAI,CAAC;gBAChB,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;gBAC9B,SAAS,EAAE,QAAQ,CAAC,KAAK;gBACzB,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,oBAAoB,EAAE,KAAK,IAAI,OAAO;gBACjE,OAAO,EAAE;oBACP,IAAI,EAAE,gBAAgB,SAAS,CAAC,MAAM,6BAA6B,SAAS,CAAC,IAAI,GAAG;iBACrF;gBACD,SAAS,EAAE;oBACT;wBACE,gBAAgB,EAAE;4BAChB,gBAAgB,EAAE;gCAChB,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;6BACzC;4BACD,MAAM,EAAE;gCACN,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC;gCACtC,OAAO,EAAE;oCACP,IAAI,EAAE,SAAS,CAAC,IAAI;iCACrB;6BACF;yBACF;qBACF;iBACF;gBACD,UAAU,EAAE;oBACV,MAAM,EAAE,SAAS,CAAC,MAAM;iBACzB;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC1E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,0FAA0F;QAC1F,UAAU,CAAC,IAAI,CAAC,wBAAwB,CAAC,wBAAwB,CAAE,CAAC,CAAC;IACvE,CAAC;IAED,OAAO;QACL,OAAO,EAAE,+CAA+C;QACxD,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN,IAAI,EAAE,gBAAgB;wBACtB,eAAe,EAAE,OAAO;wBACxB,cAAc,EAAE,8CAA8C;wBAC9D,KAAK,EAAE,UAAU;qBAClB;iBACF;gBACD,OAAO,EAAE,YAAY;aACtB;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,WAA6B,EAC7B,OAAkC;IAElC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC3C,CAAC"}
|
package/dist/scanner.d.ts
CHANGED
|
@@ -85,9 +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 =
|
|
88
|
+
export type OutputFormat = "text" | "json" | "sarif" | "csv" | "html";
|
|
89
89
|
/**
|
|
90
|
-
* Format scan results based on the chosen output format ('text' | 'json' | 'sarif').
|
|
90
|
+
* Format scan results based on the chosen output format ('text' | 'json' | 'sarif' | 'csv' | 'html').
|
|
91
91
|
*/
|
|
92
92
|
export declare function formatScanResults(results: FileScanResult[], format?: OutputFormat): string;
|
|
93
93
|
//# sourceMappingURL=scanner.d.ts.map
|
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;
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,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,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtE;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EAAE,EACzB,MAAM,GAAE,YAAqB,GAC5B,MAAM,CA2BR"}
|
package/dist/scanner.js
CHANGED
|
@@ -6,14 +6,15 @@
|
|
|
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
|
+
import { formatCsv, formatHtml } from "./exporters.js";
|
|
10
11
|
/** Console methods that put their arguments somewhere durable. */
|
|
11
|
-
const CONSOLE_METHODS = [
|
|
12
|
+
const CONSOLE_METHODS = ["log", "info", "warn", "error", "debug", "trace", "table", "dir"];
|
|
12
13
|
/**
|
|
13
14
|
* Start of a console call. Whitespace is permitted around the dot and the
|
|
14
15
|
* parenthesis because a formatter will put it there.
|
|
15
16
|
*/
|
|
16
|
-
const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join(
|
|
17
|
+
const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join("|")})\\s*\\(`, "g");
|
|
17
18
|
/**
|
|
18
19
|
* What makes an argument list suspicious.
|
|
19
20
|
*
|
|
@@ -22,26 +23,71 @@ const CONSOLE_CALL = new RegExp(`console\\s*\\.\\s*(?:${CONSOLE_METHODS.join('|'
|
|
|
22
23
|
* expression does.
|
|
23
24
|
*/
|
|
24
25
|
const INDICATORS = [
|
|
25
|
-
[
|
|
26
|
-
|
|
26
|
+
[
|
|
27
|
+
"environment variable",
|
|
28
|
+
/\b(?:process\s*\.\s*env|import\s*\.\s*meta\s*\.\s*env|Deno\s*\.\s*env|os\s*\.\s*environ)\b/,
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
"secret-named identifier",
|
|
32
|
+
/\b\w*(?:password|passwd|secret|token|credential|apikey|privatekey)\w*\b/i,
|
|
33
|
+
],
|
|
27
34
|
// `key` and `auth` on their own are common enough in ordinary code
|
|
28
35
|
// (`keyof`, `authorised`, `keys`) that they are only flagged when they read
|
|
29
36
|
// as a whole word or as an obvious compound.
|
|
30
|
-
[
|
|
37
|
+
[
|
|
38
|
+
"secret-named identifier",
|
|
39
|
+
/\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|auth[_-]?token|authorization)\b/i,
|
|
40
|
+
],
|
|
31
41
|
];
|
|
32
42
|
/** Extensions never worth scanning as source text. */
|
|
33
43
|
const BINARY_EXTENSIONS = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
".png",
|
|
45
|
+
".jpg",
|
|
46
|
+
".jpeg",
|
|
47
|
+
".gif",
|
|
48
|
+
".ico",
|
|
49
|
+
".webp",
|
|
50
|
+
".avif",
|
|
51
|
+
".bmp",
|
|
52
|
+
".tiff",
|
|
53
|
+
".pdf",
|
|
54
|
+
".zip",
|
|
55
|
+
".gz",
|
|
56
|
+
".tar",
|
|
57
|
+
".bz2",
|
|
58
|
+
".7z",
|
|
59
|
+
".rar",
|
|
60
|
+
".woff",
|
|
61
|
+
".woff2",
|
|
62
|
+
".ttf",
|
|
63
|
+
".otf",
|
|
64
|
+
".eot",
|
|
65
|
+
".mp3",
|
|
66
|
+
".mp4",
|
|
67
|
+
".wav",
|
|
68
|
+
".mov",
|
|
69
|
+
".avi",
|
|
70
|
+
".webm",
|
|
71
|
+
".so",
|
|
72
|
+
".dylib",
|
|
73
|
+
".dll",
|
|
74
|
+
".exe",
|
|
75
|
+
".wasm",
|
|
76
|
+
".class",
|
|
77
|
+
".jar",
|
|
78
|
+
".sqlite",
|
|
79
|
+
".db",
|
|
40
80
|
];
|
|
41
81
|
/** Generated files that are large, uninteresting, and full of hashes. */
|
|
42
82
|
const GENERATED_FILES = [
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
"package-lock.json",
|
|
84
|
+
"yarn.lock",
|
|
85
|
+
"pnpm-lock.yaml",
|
|
86
|
+
"bun.lockb",
|
|
87
|
+
"composer.lock",
|
|
88
|
+
"Cargo.lock",
|
|
89
|
+
"Gemfile.lock",
|
|
90
|
+
"poetry.lock",
|
|
45
91
|
];
|
|
46
92
|
/**
|
|
47
93
|
* Bytes above which a staged blob is skipped.
|
|
@@ -53,12 +99,12 @@ export const MAX_SCANNED_BYTES = 512 * 1024;
|
|
|
53
99
|
/** Whether `path` should be scanned at all. */
|
|
54
100
|
export function shouldScanFile(path, byteLength) {
|
|
55
101
|
const lower = path.toLowerCase();
|
|
56
|
-
const basename = lower.split(
|
|
102
|
+
const basename = lower.split("/").pop() ?? lower;
|
|
57
103
|
if (GENERATED_FILES.some((name) => basename === name.toLowerCase()))
|
|
58
104
|
return false;
|
|
59
105
|
if (BINARY_EXTENSIONS.some((ext) => lower.endsWith(ext)))
|
|
60
106
|
return false;
|
|
61
|
-
if (typeof byteLength ===
|
|
107
|
+
if (typeof byteLength === "number" && byteLength > MAX_SCANNED_BYTES)
|
|
62
108
|
return false;
|
|
63
109
|
return true;
|
|
64
110
|
}
|
|
@@ -69,10 +115,10 @@ export function shouldScanFile(path, byteLength) {
|
|
|
69
115
|
* extension, since a staged blob can be anything.
|
|
70
116
|
*/
|
|
71
117
|
export function looksBinary(content) {
|
|
72
|
-
return content.includes(
|
|
118
|
+
return content.includes("\u0000");
|
|
73
119
|
}
|
|
74
120
|
/** Filler used where a string literal's contents were. */
|
|
75
|
-
const MASK_CHAR =
|
|
121
|
+
const MASK_CHAR = "·";
|
|
76
122
|
/**
|
|
77
123
|
* Blank out the *contents* of string literals, preserving length.
|
|
78
124
|
*
|
|
@@ -92,7 +138,7 @@ const MASK_CHAR = '·';
|
|
|
92
138
|
* the rest of the file.
|
|
93
139
|
*/
|
|
94
140
|
export function maskStringLiterals(source) {
|
|
95
|
-
const out = source.split(
|
|
141
|
+
const out = source.split("");
|
|
96
142
|
let index = 0;
|
|
97
143
|
while (index < out.length) {
|
|
98
144
|
const char = out[index];
|
|
@@ -100,24 +146,24 @@ export function maskStringLiterals(source) {
|
|
|
100
146
|
// cursor but leaves the text in the output, so the commented-out code was
|
|
101
147
|
// still scanned. The old detector only handled `//` at the very start of a
|
|
102
148
|
// trimmed line, so a trailing comment was scanned as code either way.
|
|
103
|
-
if (char ===
|
|
104
|
-
while (index < out.length && out[index] !==
|
|
149
|
+
if (char === "/" && out[index + 1] === "/") {
|
|
150
|
+
while (index < out.length && out[index] !== "\n") {
|
|
105
151
|
out[index] = MASK_CHAR;
|
|
106
152
|
index += 1;
|
|
107
153
|
}
|
|
108
154
|
continue;
|
|
109
155
|
}
|
|
110
|
-
if (char ===
|
|
156
|
+
if (char === "/" && out[index + 1] === "*") {
|
|
111
157
|
index += 2;
|
|
112
|
-
while (index < out.length && !(out[index] ===
|
|
113
|
-
if (out[index] !==
|
|
158
|
+
while (index < out.length && !(out[index] === "*" && out[index + 1] === "/")) {
|
|
159
|
+
if (out[index] !== "\n")
|
|
114
160
|
out[index] = MASK_CHAR;
|
|
115
161
|
index += 1;
|
|
116
162
|
}
|
|
117
163
|
index += 2;
|
|
118
164
|
continue;
|
|
119
165
|
}
|
|
120
|
-
if (char !== '"' && char !== "'" && char !==
|
|
166
|
+
if (char !== '"' && char !== "'" && char !== "`") {
|
|
121
167
|
index += 1;
|
|
122
168
|
continue;
|
|
123
169
|
}
|
|
@@ -125,11 +171,11 @@ export function maskStringLiterals(source) {
|
|
|
125
171
|
index += 1;
|
|
126
172
|
while (index < out.length) {
|
|
127
173
|
const current = out[index];
|
|
128
|
-
if (current ===
|
|
174
|
+
if (current === "\\") {
|
|
129
175
|
// Escaped character: mask both, and never let it terminate the literal.
|
|
130
|
-
if (out[index] !==
|
|
176
|
+
if (out[index] !== "\n")
|
|
131
177
|
out[index] = MASK_CHAR;
|
|
132
|
-
if (index + 1 < out.length && out[index + 1] !==
|
|
178
|
+
if (index + 1 < out.length && out[index + 1] !== "\n")
|
|
133
179
|
out[index + 1] = MASK_CHAR;
|
|
134
180
|
index += 2;
|
|
135
181
|
continue;
|
|
@@ -140,28 +186,28 @@ export function maskStringLiterals(source) {
|
|
|
140
186
|
}
|
|
141
187
|
// An unterminated quote must not swallow the rest of the file. Only a
|
|
142
188
|
// template literal legally spans lines.
|
|
143
|
-
if (current ===
|
|
189
|
+
if (current === "\n" && quote !== "`")
|
|
144
190
|
break;
|
|
145
191
|
// `${ … }` inside a template literal is code. Leave it visible, tracking
|
|
146
192
|
// brace depth so a nested object literal does not end it early.
|
|
147
|
-
if (quote ===
|
|
193
|
+
if (quote === "`" && current === "$" && out[index + 1] === "{") {
|
|
148
194
|
let depth = 1;
|
|
149
195
|
index += 2;
|
|
150
196
|
while (index < out.length && depth > 0) {
|
|
151
|
-
if (out[index] ===
|
|
197
|
+
if (out[index] === "{")
|
|
152
198
|
depth += 1;
|
|
153
|
-
else if (out[index] ===
|
|
199
|
+
else if (out[index] === "}")
|
|
154
200
|
depth -= 1;
|
|
155
201
|
index += 1;
|
|
156
202
|
}
|
|
157
203
|
continue;
|
|
158
204
|
}
|
|
159
|
-
if (current !==
|
|
205
|
+
if (current !== "\n")
|
|
160
206
|
out[index] = MASK_CHAR;
|
|
161
207
|
index += 1;
|
|
162
208
|
}
|
|
163
209
|
}
|
|
164
|
-
return out.join(
|
|
210
|
+
return out.join("");
|
|
165
211
|
}
|
|
166
212
|
/**
|
|
167
213
|
* Text of the balanced argument list starting at `openParen`, or null when the
|
|
@@ -181,9 +227,9 @@ export function maskStringLiterals(source) {
|
|
|
181
227
|
export function readArgumentList(source, openParen) {
|
|
182
228
|
let depth = 0;
|
|
183
229
|
for (let i = openParen; i < source.length; i += 1) {
|
|
184
|
-
if (source[i] ===
|
|
230
|
+
if (source[i] === "(")
|
|
185
231
|
depth += 1;
|
|
186
|
-
else if (source[i] ===
|
|
232
|
+
else if (source[i] === ")") {
|
|
187
233
|
depth -= 1;
|
|
188
234
|
if (depth === 0)
|
|
189
235
|
return source.slice(openParen + 1, i);
|
|
@@ -195,7 +241,7 @@ export function readArgumentList(source, openParen) {
|
|
|
195
241
|
export function lineOf(source, offset) {
|
|
196
242
|
let line = 1;
|
|
197
243
|
for (let i = 0; i < offset && i < source.length; i += 1) {
|
|
198
|
-
if (source[i] ===
|
|
244
|
+
if (source[i] === "\n")
|
|
199
245
|
line += 1;
|
|
200
246
|
}
|
|
201
247
|
return line;
|
|
@@ -226,7 +272,7 @@ export function findSecretLogging(source) {
|
|
|
226
272
|
const line = lineOf(masked, match.index);
|
|
227
273
|
violations.push({
|
|
228
274
|
line,
|
|
229
|
-
text: (lines[line - 1] ??
|
|
275
|
+
text: (lines[line - 1] ?? "").trim(),
|
|
230
276
|
reason: indicator[0],
|
|
231
277
|
});
|
|
232
278
|
}
|
|
@@ -234,26 +280,32 @@ export function findSecretLogging(source) {
|
|
|
234
280
|
}
|
|
235
281
|
/** Scan one staged blob. */
|
|
236
282
|
export function scanFile(path, content) {
|
|
237
|
-
if (!shouldScanFile(path, Buffer.byteLength(content,
|
|
238
|
-
return { path, violations: [], skipped:
|
|
283
|
+
if (!shouldScanFile(path, Buffer.byteLength(content, "utf-8"))) {
|
|
284
|
+
return { path, violations: [], skipped: "excluded by type or size" };
|
|
239
285
|
}
|
|
240
286
|
if (looksBinary(content)) {
|
|
241
|
-
return { path, violations: [], skipped:
|
|
287
|
+
return { path, violations: [], skipped: "binary content" };
|
|
242
288
|
}
|
|
243
289
|
return { path, violations: findSecretLogging(content) };
|
|
244
290
|
}
|
|
245
291
|
/**
|
|
246
|
-
* Format scan results based on the chosen output format ('text' | 'json' | 'sarif').
|
|
292
|
+
* Format scan results based on the chosen output format ('text' | 'json' | 'sarif' | 'csv' | 'html').
|
|
247
293
|
*/
|
|
248
|
-
export function formatScanResults(results, format =
|
|
249
|
-
if (format ===
|
|
294
|
+
export function formatScanResults(results, format = "text") {
|
|
295
|
+
if (format === "json") {
|
|
250
296
|
return JSON.stringify(results, null, 2);
|
|
251
297
|
}
|
|
252
|
-
if (format ===
|
|
298
|
+
if (format === "sarif") {
|
|
253
299
|
return formatSarifJson(results);
|
|
254
300
|
}
|
|
301
|
+
if (format === "csv") {
|
|
302
|
+
return formatCsv(results);
|
|
303
|
+
}
|
|
304
|
+
if (format === "html") {
|
|
305
|
+
return formatHtml(results);
|
|
306
|
+
}
|
|
255
307
|
// Default text summary
|
|
256
|
-
let text =
|
|
308
|
+
let text = "";
|
|
257
309
|
for (const r of results) {
|
|
258
310
|
for (const v of r.violations) {
|
|
259
311
|
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;
|
|
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": "1.
|
|
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.1.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
|
+
}
|