toolip 2.0.0 → 2.0.1
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.
|
@@ -2,7 +2,7 @@ import type { Analyzer, AnalyzerContext, AnalyzerResult } from '../../contracts/
|
|
|
2
2
|
export declare class GitHistorySecretAnalyzer implements Analyzer {
|
|
3
3
|
private readonly maxCommits;
|
|
4
4
|
readonly id = "git-history-secrets";
|
|
5
|
-
readonly version = "1.0.
|
|
5
|
+
readonly version = "1.0.1";
|
|
6
6
|
constructor(maxCommits?: number);
|
|
7
7
|
analyze(context: AnalyzerContext): Promise<AnalyzerResult>;
|
|
8
8
|
}
|
|
@@ -14,6 +14,15 @@ function fingerprint(value) {
|
|
|
14
14
|
.update(value)
|
|
15
15
|
.digest('hex');
|
|
16
16
|
}
|
|
17
|
+
function isTestFile(file) {
|
|
18
|
+
if (!file) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return (file.startsWith('tests/') ||
|
|
22
|
+
file.includes('/tests/') ||
|
|
23
|
+
file.includes('/__tests__/') ||
|
|
24
|
+
/\.(test|spec)\.[cm]?[jt]sx?$/.test(file));
|
|
25
|
+
}
|
|
17
26
|
async function gitLog(root, maxCommits, signal) {
|
|
18
27
|
return new Promise((resolve, reject) => {
|
|
19
28
|
const child = spawn('git', [
|
|
@@ -62,10 +71,10 @@ async function gitLog(root, maxCommits, signal) {
|
|
|
62
71
|
});
|
|
63
72
|
}
|
|
64
73
|
function sections(output) {
|
|
65
|
-
|
|
74
|
+
return output
|
|
66
75
|
.split('__TOOLIP_COMMIT__')
|
|
67
|
-
.filter(Boolean)
|
|
68
|
-
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.map((section) => {
|
|
69
78
|
const newline = section.indexOf('\n');
|
|
70
79
|
const header = newline === -1
|
|
71
80
|
? section
|
|
@@ -83,16 +92,31 @@ function sections(output) {
|
|
|
83
92
|
});
|
|
84
93
|
}
|
|
85
94
|
function addedLines(body) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
const output = [];
|
|
96
|
+
let currentFile;
|
|
97
|
+
for (const line of body.split('\n')) {
|
|
98
|
+
if (line.startsWith('+++ b/')) {
|
|
99
|
+
currentFile = line.slice('+++ b/'.length);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (line.startsWith('+++ /dev/null')) {
|
|
103
|
+
currentFile = undefined;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (line.startsWith('+') &&
|
|
107
|
+
!line.startsWith('+++')) {
|
|
108
|
+
output.push({
|
|
109
|
+
file: currentFile,
|
|
110
|
+
content: line.slice(1)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return output;
|
|
91
115
|
}
|
|
92
116
|
export class GitHistorySecretAnalyzer {
|
|
93
117
|
maxCommits;
|
|
94
118
|
id = 'git-history-secrets';
|
|
95
|
-
version = '1.0.
|
|
119
|
+
version = '1.0.1';
|
|
96
120
|
constructor(maxCommits = 1000) {
|
|
97
121
|
this.maxCommits = maxCommits;
|
|
98
122
|
}
|
|
@@ -103,42 +127,62 @@ export class GitHistorySecretAnalyzer {
|
|
|
103
127
|
const seen = new Set();
|
|
104
128
|
const commitSections = sections(output);
|
|
105
129
|
for (const section of commitSections) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
seen.add(key);
|
|
118
|
-
findings.push({
|
|
119
|
-
id: key,
|
|
120
|
-
ruleId: pattern.id,
|
|
121
|
-
title: pattern.title,
|
|
122
|
-
category: 'git-history-secret',
|
|
123
|
-
severity: pattern.severity,
|
|
124
|
-
confidence: 'high',
|
|
125
|
-
message: `A secret-like value was introduced in commit ${section.commit}.`,
|
|
126
|
-
source: 'git-history',
|
|
127
|
-
evidence: [
|
|
128
|
-
{
|
|
129
|
-
summary: redact(value),
|
|
130
|
-
fingerprint: secretFingerprint
|
|
131
|
-
}
|
|
132
|
-
],
|
|
133
|
-
remediation: {
|
|
134
|
-
summary: 'Revoke or rotate the credential immediately, then remove it from repository history using an approved history-rewrite process.'
|
|
135
|
-
},
|
|
136
|
-
metadata: {
|
|
137
|
-
commit: section.commit,
|
|
138
|
-
author: section.author,
|
|
139
|
-
date: section.date
|
|
130
|
+
for (const line of addedLines(section.body)) {
|
|
131
|
+
for (const pattern of historicalSecretPatterns) {
|
|
132
|
+
pattern.regex.lastIndex = 0;
|
|
133
|
+
for (const match of line.content.matchAll(pattern.regex)) {
|
|
134
|
+
const value = match[0];
|
|
135
|
+
const secretFingerprint = fingerprint(value);
|
|
136
|
+
const key = `${pattern.id}:${section.commit}:` +
|
|
137
|
+
`${line.file ?? 'unknown'}:` +
|
|
138
|
+
secretFingerprint;
|
|
139
|
+
if (seen.has(key)) {
|
|
140
|
+
continue;
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
+
seen.add(key);
|
|
143
|
+
const testFixture = isTestFile(line.file);
|
|
144
|
+
findings.push({
|
|
145
|
+
id: key,
|
|
146
|
+
ruleId: pattern.id,
|
|
147
|
+
title: testFixture
|
|
148
|
+
? `Potential historical test fixture: ${pattern.title}`
|
|
149
|
+
: pattern.title,
|
|
150
|
+
category: 'git-history-secret',
|
|
151
|
+
severity: testFixture
|
|
152
|
+
? 'low'
|
|
153
|
+
: pattern.severity,
|
|
154
|
+
confidence: testFixture
|
|
155
|
+
? 'medium'
|
|
156
|
+
: 'high',
|
|
157
|
+
message: testFixture
|
|
158
|
+
? `A secret-like value was introduced in test file ${line.file ?? 'unknown'} in commit ${section.commit}. Confirm that it is synthetic fixture data.`
|
|
159
|
+
: `A secret-like value was introduced in commit ${section.commit}.`,
|
|
160
|
+
source: 'git-history',
|
|
161
|
+
location: line.file
|
|
162
|
+
? {
|
|
163
|
+
file: line.file
|
|
164
|
+
}
|
|
165
|
+
: undefined,
|
|
166
|
+
evidence: [
|
|
167
|
+
{
|
|
168
|
+
summary: redact(value),
|
|
169
|
+
fingerprint: secretFingerprint
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
remediation: {
|
|
173
|
+
summary: testFixture
|
|
174
|
+
? 'Confirm that the value is synthetic test data. Replace realistic credential fixtures with clearly fake placeholders where possible.'
|
|
175
|
+
: 'Revoke or rotate the credential immediately, then remove it from repository history using an approved history-rewrite process.'
|
|
176
|
+
},
|
|
177
|
+
metadata: {
|
|
178
|
+
commit: section.commit,
|
|
179
|
+
author: section.author,
|
|
180
|
+
date: section.date,
|
|
181
|
+
file: line.file,
|
|
182
|
+
testFixture
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
142
186
|
}
|
|
143
187
|
}
|
|
144
188
|
}
|
|
@@ -149,6 +193,7 @@ export class GitHistorySecretAnalyzer {
|
|
|
149
193
|
metadata: {
|
|
150
194
|
commitsScanned: commitSections.length,
|
|
151
195
|
findings: findings.length,
|
|
196
|
+
testFixtures: findings.filter((finding) => finding.metadata?.testFixture === true).length,
|
|
152
197
|
maxCommits: this.maxCommits
|
|
153
198
|
}
|
|
154
199
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../../src/analyzers/git-history/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACN,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,OAAO,EACL,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../../src/analyzers/git-history/analyzer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolip",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "A TypeScript-powered developer security companion CLI for supply chain security, dependency intelligence, secret detection, security auditing, encrypted local secrets management, Git security checks, and secure development education.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|