logicstamp-context 0.2.6 → 0.3.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/LLM_CONTEXT.md +2 -2
- package/README.md +79 -36
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +36 -10
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/ignore.d.ts +16 -0
- package/dist/cli/commands/ignore.d.ts.map +1 -0
- package/dist/cli/commands/ignore.js +61 -0
- package/dist/cli/commands/ignore.js.map +1 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +83 -9
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/security.d.ts +37 -0
- package/dist/cli/commands/security.d.ts.map +1 -0
- package/dist/cli/commands/security.js +304 -0
- package/dist/cli/commands/security.js.map +1 -0
- package/dist/cli/handlers/ignoreHandler.d.ts +5 -0
- package/dist/cli/handlers/ignoreHandler.d.ts.map +1 -0
- package/dist/cli/handlers/ignoreHandler.js +23 -0
- package/dist/cli/handlers/ignoreHandler.js.map +1 -0
- package/dist/cli/handlers/securityHandler.d.ts +5 -0
- package/dist/cli/handlers/securityHandler.d.ts.map +1 -0
- package/dist/cli/handlers/securityHandler.js +41 -0
- package/dist/cli/handlers/securityHandler.js.map +1 -0
- package/dist/cli/parser/argumentParser.d.ts +9 -0
- package/dist/cli/parser/argumentParser.d.ts.map +1 -1
- package/dist/cli/parser/argumentParser.js +50 -0
- package/dist/cli/parser/argumentParser.js.map +1 -1
- package/dist/cli/parser/helpText.d.ts +3 -0
- package/dist/cli/parser/helpText.d.ts.map +1 -1
- package/dist/cli/parser/helpText.js +492 -348
- package/dist/cli/parser/helpText.js.map +1 -1
- package/dist/cli/stamp.js +61 -1
- package/dist/cli/stamp.js.map +1 -1
- package/dist/core/pack/builder.d.ts.map +1 -1
- package/dist/core/pack/builder.js +25 -5
- package/dist/core/pack/builder.js.map +1 -1
- package/dist/core/pack/loader.d.ts +14 -0
- package/dist/core/pack/loader.d.ts.map +1 -1
- package/dist/core/pack/loader.js +86 -2
- package/dist/core/pack/loader.js.map +1 -1
- package/dist/core/pack.d.ts.map +1 -1
- package/dist/core/pack.js +15 -2
- package/dist/core/pack.js.map +1 -1
- package/dist/utils/codeSanitizer.d.ts +24 -0
- package/dist/utils/codeSanitizer.d.ts.map +1 -0
- package/dist/utils/codeSanitizer.js +234 -0
- package/dist/utils/codeSanitizer.js.map +1 -0
- package/dist/utils/gitignore.d.ts +30 -2
- package/dist/utils/gitignore.d.ts.map +1 -1
- package/dist/utils/gitignore.js +132 -20
- package/dist/utils/gitignore.js.map +1 -1
- package/dist/utils/secretDetector.d.ts +21 -0
- package/dist/utils/secretDetector.d.ts.map +1 -0
- package/dist/utils/secretDetector.js +145 -0
- package/dist/utils/secretDetector.js.map +1 -0
- package/dist/utils/stampignore.d.ts +49 -0
- package/dist/utils/stampignore.d.ts.map +1 -0
- package/dist/utils/stampignore.js +211 -0
- package/dist/utils/stampignore.js.map +1 -0
- package/package.json +1 -1
- package/schema/logicstamp.context.schema.json +1 -1
|
@@ -5,6 +5,7 @@ import { resolve } from 'node:path';
|
|
|
5
5
|
import { ensureGitignorePatterns, readGitignore, hasLogicStampPatterns } from '../../utils/gitignore.js';
|
|
6
6
|
import { updateConfig } from '../../utils/config.js';
|
|
7
7
|
import { readPackageLLMContext, writeLLMContext, llmContextExists } from '../../utils/llmContext.js';
|
|
8
|
+
import { securityScanCommand } from './security.js';
|
|
8
9
|
/**
|
|
9
10
|
* Check if running in interactive TTY
|
|
10
11
|
*/
|
|
@@ -32,11 +33,18 @@ async function promptYesNo(question) {
|
|
|
32
33
|
*/
|
|
33
34
|
export async function init(options = {}) {
|
|
34
35
|
const targetDir = resolve(options.targetDir || process.cwd());
|
|
36
|
+
// Security scan runs by default unless --no-secure is set
|
|
37
|
+
// When security scan runs, automatically enable --yes (no prompts)
|
|
38
|
+
const shouldRunSecurity = !options.noSecure;
|
|
39
|
+
const autoYes = shouldRunSecurity || options.yes;
|
|
40
|
+
// Track what was done for summary (only used when security scan runs)
|
|
41
|
+
let gitignoreAdded = false;
|
|
42
|
+
let llmContextGenerated = false;
|
|
35
43
|
console.log('🚀 Initializing LogicStamp...\n');
|
|
36
44
|
// Setup .gitignore (always prompt unless skipGitignore flag)
|
|
37
45
|
if (!options.skipGitignore) {
|
|
38
46
|
try {
|
|
39
|
-
// Check if patterns already exist
|
|
47
|
+
// Check if patterns already exist (for display purposes)
|
|
40
48
|
const gitignoreContent = await readGitignore(targetDir);
|
|
41
49
|
const alreadyHasPatterns = hasLogicStampPatterns(gitignoreContent);
|
|
42
50
|
if (!alreadyHasPatterns) {
|
|
@@ -47,8 +55,9 @@ export async function init(options = {}) {
|
|
|
47
55
|
console.log(' - *.uif.json');
|
|
48
56
|
console.log(' - logicstamp.manifest.json');
|
|
49
57
|
console.log(' - .logicstamp/');
|
|
58
|
+
console.log(' - stamp_security_report.json (🔒 SECURITY: contains sensitive secret locations)');
|
|
50
59
|
let shouldAdd = true; // Default to "yes" in non-interactive mode
|
|
51
|
-
if (isTTY()) {
|
|
60
|
+
if (isTTY() && !autoYes) {
|
|
52
61
|
// Interactive prompt (local dev convenience)
|
|
53
62
|
shouldAdd = await promptYesNo('\nAdd recommended patterns to .gitignore? [Y/n] ');
|
|
54
63
|
}
|
|
@@ -57,19 +66,31 @@ export async function init(options = {}) {
|
|
|
57
66
|
if (created) {
|
|
58
67
|
console.log('✅ Created .gitignore with LogicStamp patterns');
|
|
59
68
|
await updateConfig(targetDir, { gitignorePreference: 'added' });
|
|
69
|
+
gitignoreAdded = true;
|
|
60
70
|
}
|
|
61
71
|
else if (added) {
|
|
62
72
|
console.log('✅ Added LogicStamp patterns to existing .gitignore');
|
|
63
73
|
await updateConfig(targetDir, { gitignorePreference: 'added' });
|
|
74
|
+
gitignoreAdded = true;
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
else {
|
|
67
78
|
console.log('📝 Skipping .gitignore setup');
|
|
79
|
+
console.log('⚠️ Note: If you run `stamp security scan`, it will automatically add `stamp_security_report.json` to `.gitignore` to protect sensitive findings.');
|
|
68
80
|
await updateConfig(targetDir, { gitignorePreference: 'skipped' });
|
|
69
81
|
}
|
|
70
82
|
}
|
|
71
83
|
else {
|
|
72
|
-
|
|
84
|
+
// Even if hasLogicStampPatterns() returns true, ensureGitignorePatterns()
|
|
85
|
+
// will check for missing patterns and update if needed (idempotent patch mode)
|
|
86
|
+
const { added } = await ensureGitignorePatterns(targetDir);
|
|
87
|
+
if (added) {
|
|
88
|
+
console.log('✅ Updated existing LogicStamp section in .gitignore');
|
|
89
|
+
gitignoreAdded = true;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
console.log('ℹ️ .gitignore already contains all LogicStamp patterns');
|
|
93
|
+
}
|
|
73
94
|
// Still save preference in case config doesn't exist
|
|
74
95
|
await updateConfig(targetDir, { gitignorePreference: 'added' });
|
|
75
96
|
}
|
|
@@ -93,7 +114,7 @@ export async function init(options = {}) {
|
|
|
93
114
|
if (content) {
|
|
94
115
|
console.log('\n💡 LogicStamp can generate LLM_CONTEXT.md to help AI assistants understand your project structure.');
|
|
95
116
|
let shouldAdd = true; // Default to "yes" in non-interactive mode
|
|
96
|
-
if (isTTY()) {
|
|
117
|
+
if (isTTY() && !autoYes) {
|
|
97
118
|
// Interactive prompt (local dev convenience)
|
|
98
119
|
shouldAdd = await promptYesNo('Generate LLM_CONTEXT.md in project root? [Y/n] ');
|
|
99
120
|
}
|
|
@@ -101,6 +122,7 @@ export async function init(options = {}) {
|
|
|
101
122
|
await writeLLMContext(targetDir, content);
|
|
102
123
|
console.log('✅ Created LLM_CONTEXT.md');
|
|
103
124
|
await updateConfig(targetDir, { llmContextPreference: 'added' });
|
|
125
|
+
llmContextGenerated = true;
|
|
104
126
|
}
|
|
105
127
|
else {
|
|
106
128
|
console.log('📝 Skipping LLM_CONTEXT.md creation');
|
|
@@ -133,7 +155,7 @@ Add instructions for how to get started with this project.
|
|
|
133
155
|
This file is generated by LogicStamp Context. Customize it to fit your project's needs.
|
|
134
156
|
`;
|
|
135
157
|
let shouldAdd = true; // Default to "yes" in non-interactive mode
|
|
136
|
-
if (isTTY()) {
|
|
158
|
+
if (isTTY() && !autoYes) {
|
|
137
159
|
// Interactive prompt (local dev convenience)
|
|
138
160
|
shouldAdd = await promptYesNo('Generate LLM_CONTEXT.md in project root? [Y/n] ');
|
|
139
161
|
}
|
|
@@ -141,6 +163,7 @@ This file is generated by LogicStamp Context. Customize it to fit your project's
|
|
|
141
163
|
await writeLLMContext(targetDir, defaultContent);
|
|
142
164
|
console.log('✅ Created LLM_CONTEXT.md with default template');
|
|
143
165
|
await updateConfig(targetDir, { llmContextPreference: 'added' });
|
|
166
|
+
llmContextGenerated = true;
|
|
144
167
|
}
|
|
145
168
|
else {
|
|
146
169
|
console.log('📝 Skipping LLM_CONTEXT.md creation');
|
|
@@ -152,9 +175,60 @@ This file is generated by LogicStamp Context. Customize it to fit your project's
|
|
|
152
175
|
catch (error) {
|
|
153
176
|
console.error('\n⚠️ Failed to create LLM_CONTEXT.md:', error instanceof Error ? error.message : String(error));
|
|
154
177
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
178
|
+
// Run security scan after init (default behavior, unless --no-secure is set)
|
|
179
|
+
if (shouldRunSecurity) {
|
|
180
|
+
console.log('\n🔒 Running security scan...\n');
|
|
181
|
+
try {
|
|
182
|
+
const scanResult = await securityScanCommand({
|
|
183
|
+
entry: targetDir,
|
|
184
|
+
quiet: false,
|
|
185
|
+
noExit: true,
|
|
186
|
+
});
|
|
187
|
+
// Print combined summary
|
|
188
|
+
console.log('\n📊 Initialization complete.');
|
|
189
|
+
// Summary of init actions
|
|
190
|
+
if (!options.skipGitignore) {
|
|
191
|
+
if (gitignoreAdded) {
|
|
192
|
+
console.log('✔ Added LogicStamp patterns to .gitignore');
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// Check if it was already there
|
|
196
|
+
const gitignoreContent = await readGitignore(targetDir);
|
|
197
|
+
if (hasLogicStampPatterns(gitignoreContent)) {
|
|
198
|
+
console.log('✔ LogicStamp patterns already in .gitignore');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (llmContextGenerated) {
|
|
203
|
+
console.log('✔ Generated LLM_CONTEXT.md');
|
|
204
|
+
}
|
|
205
|
+
else if (await llmContextExists(targetDir)) {
|
|
206
|
+
console.log('✔ LLM_CONTEXT.md already exists');
|
|
207
|
+
}
|
|
208
|
+
// Summary of security scan
|
|
209
|
+
if (scanResult && typeof scanResult === 'object' && 'report' in scanResult) {
|
|
210
|
+
const { report } = scanResult;
|
|
211
|
+
console.log(`✔ Security scan: ${report.filesScanned} files scanned, ${report.secretsFound} secrets found`);
|
|
212
|
+
if (report.secretsFound > 0) {
|
|
213
|
+
console.log(`✔ Report written to stamp_security_report.json`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
console.log(`✔ No secrets detected`);
|
|
218
|
+
console.log(`✔ Report written to stamp_security_report.json`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error('\n⚠️ Security scan failed:', error instanceof Error ? error.message : String(error));
|
|
224
|
+
// Don't exit with error - init succeeded, scan failed
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
console.log('\n✨ LogicStamp initialization complete!');
|
|
229
|
+
console.log('\nNext steps:');
|
|
230
|
+
console.log(' • Run `stamp context` to generate context files');
|
|
231
|
+
console.log(' • Run `stamp context --help` for more options');
|
|
232
|
+
}
|
|
159
233
|
}
|
|
160
234
|
//# sourceMappingURL=init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACzG,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security scan command - Scans for secrets and generates report
|
|
3
|
+
*/
|
|
4
|
+
import { type SecretMatch } from '../../utils/secretDetector.js';
|
|
5
|
+
export interface SecurityScanOptions {
|
|
6
|
+
entry?: string;
|
|
7
|
+
out?: string;
|
|
8
|
+
quiet?: boolean;
|
|
9
|
+
/** If true, return result instead of calling process.exit */
|
|
10
|
+
noExit?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface SecurityReport {
|
|
13
|
+
type: 'LogicStampSecurityReport';
|
|
14
|
+
schemaVersion: '0.1';
|
|
15
|
+
createdAt: string;
|
|
16
|
+
projectRoot: string;
|
|
17
|
+
filesScanned: number;
|
|
18
|
+
secretsFound: number;
|
|
19
|
+
matches: SecretMatch[];
|
|
20
|
+
filesWithSecrets: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface SecurityHardResetOptions {
|
|
23
|
+
entry?: string;
|
|
24
|
+
out?: string;
|
|
25
|
+
force?: boolean;
|
|
26
|
+
quiet?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Hard reset command - deletes security report file
|
|
30
|
+
*/
|
|
31
|
+
export declare function securityHardResetCommand(options: SecurityHardResetOptions): Promise<void>;
|
|
32
|
+
export interface SecurityScanResult {
|
|
33
|
+
secretsFound: boolean;
|
|
34
|
+
report: SecurityReport;
|
|
35
|
+
}
|
|
36
|
+
export declare function securityScanCommand(options: SecurityScanOptions): Promise<void | SecurityScanResult>;
|
|
37
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/security.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,EAA4C,KAAK,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAM3G,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,0BAA0B,CAAC;IACjC,aAAa,EAAE,KAAK,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAsBD,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C/F;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,GAAG,kBAAkB,CAAC,CAyP1G"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security scan command - Scans for secrets and generates report
|
|
3
|
+
*/
|
|
4
|
+
import { resolve, dirname, join, relative } from 'node:path';
|
|
5
|
+
import { writeFile, mkdir, unlink, stat } from 'node:fs/promises';
|
|
6
|
+
import { createInterface } from 'node:readline';
|
|
7
|
+
import { stdin, stdout } from 'node:process';
|
|
8
|
+
import { globFiles, readFileWithText, getRelativePath } from '../../utils/fsx.js';
|
|
9
|
+
import { scanFileForSecrets, filterFalsePositives } from '../../utils/secretDetector.js';
|
|
10
|
+
import { STAMPIGNORE_FILENAME } from '../../utils/stampignore.js';
|
|
11
|
+
import { ensureGitignorePatterns, ensurePatternInGitignore } from '../../utils/gitignore.js';
|
|
12
|
+
import { debugError } from '../../utils/debug.js';
|
|
13
|
+
import { displayPath } from './context/fileWriter.js';
|
|
14
|
+
/**
|
|
15
|
+
* Security scan command
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Prompt user for yes/no confirmation
|
|
19
|
+
*/
|
|
20
|
+
async function promptYesNo(question) {
|
|
21
|
+
const rl = createInterface({
|
|
22
|
+
input: stdin,
|
|
23
|
+
output: stdout,
|
|
24
|
+
});
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
rl.question(`${question} (y/N): `, (answer) => {
|
|
27
|
+
rl.close();
|
|
28
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Hard reset command - deletes security report file
|
|
34
|
+
*/
|
|
35
|
+
export async function securityHardResetCommand(options) {
|
|
36
|
+
const projectRoot = resolve(options.entry || '.');
|
|
37
|
+
const outputPath = options.out || 'stamp_security_report.json';
|
|
38
|
+
const outputFile = outputPath.endsWith('.json') ? outputPath : join(outputPath, 'stamp_security_report.json');
|
|
39
|
+
const reportPath = outputFile;
|
|
40
|
+
let shouldReset = options.force;
|
|
41
|
+
if (!shouldReset) {
|
|
42
|
+
// Prompt for confirmation
|
|
43
|
+
shouldReset = await promptYesNo(`⚠️ This will delete ${displayPath(reportPath)}. Continue?`);
|
|
44
|
+
}
|
|
45
|
+
if (shouldReset) {
|
|
46
|
+
// Delete report file
|
|
47
|
+
let reportDeleted = false;
|
|
48
|
+
try {
|
|
49
|
+
await unlink(reportPath);
|
|
50
|
+
reportDeleted = true;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const err = error;
|
|
54
|
+
if (err.code !== 'ENOENT') {
|
|
55
|
+
// Only error if file exists but couldn't be deleted
|
|
56
|
+
throw new Error(`Failed to delete report file: ${err.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!options.quiet) {
|
|
60
|
+
if (reportDeleted) {
|
|
61
|
+
console.log(`\n✅ Reset complete:`);
|
|
62
|
+
console.log(` Deleted ${displayPath(reportPath)}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(`\nℹ️ No report file to reset (file doesn't exist)`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
if (!options.quiet) {
|
|
71
|
+
console.log(`\n❌ Reset cancelled`);
|
|
72
|
+
}
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export async function securityScanCommand(options) {
|
|
77
|
+
const projectRoot = resolve(options.entry || '.');
|
|
78
|
+
const outputPath = options.out || 'stamp_security_report.json';
|
|
79
|
+
const outputDir = outputPath.endsWith('.json') ? dirname(outputPath) : outputPath;
|
|
80
|
+
const outputFile = outputPath.endsWith('.json') ? outputPath : join(outputPath, 'stamp_security_report.json');
|
|
81
|
+
if (!options.quiet) {
|
|
82
|
+
console.log(`🔒 Scanning for secrets in ${displayPath(projectRoot)}...`);
|
|
83
|
+
}
|
|
84
|
+
// Resolve output file relative to project root if it's a relative path
|
|
85
|
+
const resolvedOutputFile = outputFile.startsWith('/') || outputFile.match(/^[A-Z]:/)
|
|
86
|
+
? outputFile
|
|
87
|
+
: join(projectRoot, outputFile);
|
|
88
|
+
// Find all files to scan (TypeScript, JavaScript, and JSON files)
|
|
89
|
+
let files = await globFiles(projectRoot, '.ts,.tsx,.js,.jsx,.json');
|
|
90
|
+
// Exclude the report file and .stampignore from scanning (they may contain secrets)
|
|
91
|
+
// Use absolute path comparison to be safe
|
|
92
|
+
const reportFileAbs = resolve(resolvedOutputFile);
|
|
93
|
+
const stampignoreFileAbs = join(projectRoot, STAMPIGNORE_FILENAME);
|
|
94
|
+
files = files.filter(file => {
|
|
95
|
+
const fileAbs = resolve(file);
|
|
96
|
+
return fileAbs !== reportFileAbs && fileAbs !== stampignoreFileAbs;
|
|
97
|
+
});
|
|
98
|
+
if (files.length === 0) {
|
|
99
|
+
if (!options.quiet) {
|
|
100
|
+
console.log(' No files found to scan');
|
|
101
|
+
}
|
|
102
|
+
// Still create an empty report if noExit is true (called from init)
|
|
103
|
+
if (options.noExit) {
|
|
104
|
+
const emptyReport = {
|
|
105
|
+
type: 'LogicStampSecurityReport',
|
|
106
|
+
schemaVersion: '0.1',
|
|
107
|
+
createdAt: new Date().toISOString(),
|
|
108
|
+
projectRoot,
|
|
109
|
+
filesScanned: 0,
|
|
110
|
+
secretsFound: 0,
|
|
111
|
+
matches: [], // Already empty, no paths to convert
|
|
112
|
+
filesWithSecrets: [], // Already empty, no paths to convert
|
|
113
|
+
};
|
|
114
|
+
// Resolve output file relative to project root if it's a relative path
|
|
115
|
+
const resolvedOutputFile = outputFile.startsWith('/') || outputFile.match(/^[A-Z]:/)
|
|
116
|
+
? outputFile
|
|
117
|
+
: join(projectRoot, outputFile);
|
|
118
|
+
const resolvedOutputDir = dirname(resolvedOutputFile);
|
|
119
|
+
try {
|
|
120
|
+
await mkdir(resolvedOutputDir, { recursive: true });
|
|
121
|
+
await writeFile(resolvedOutputFile, JSON.stringify(emptyReport, null, 2), 'utf8');
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const err = error;
|
|
125
|
+
debugError('security', 'securityScanCommand', {
|
|
126
|
+
outputFile: resolvedOutputFile,
|
|
127
|
+
message: err.message,
|
|
128
|
+
code: err.code,
|
|
129
|
+
});
|
|
130
|
+
throw new Error(`Failed to write security report: ${err.message}`);
|
|
131
|
+
}
|
|
132
|
+
// Automatically ensure report file is in .gitignore to prevent accidental commits
|
|
133
|
+
try {
|
|
134
|
+
const reportPathRelative = relative(projectRoot, resolvedOutputFile).replace(/\\/g, '/');
|
|
135
|
+
const isDefaultPath = outputPath === 'stamp_security_report.json' ||
|
|
136
|
+
(outputPath.endsWith('.json') && resolvedOutputFile.endsWith('stamp_security_report.json'));
|
|
137
|
+
if (isDefaultPath) {
|
|
138
|
+
// Default path - ensure all LogicStamp patterns are in .gitignore
|
|
139
|
+
await ensureGitignorePatterns(projectRoot);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Custom path - ensure this specific file is in .gitignore
|
|
143
|
+
await ensurePatternInGitignore(projectRoot, reportPathRelative);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
// Non-fatal: log warning but don't fail the scan
|
|
148
|
+
if (!options.quiet) {
|
|
149
|
+
const err = error;
|
|
150
|
+
console.warn(`\n⚠️ Warning: Could not update .gitignore: ${err.message}`);
|
|
151
|
+
console.warn(` Please manually add the report file to .gitignore to prevent accidental commits.`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!options.quiet) {
|
|
155
|
+
console.log(`\n✅ No secrets detected`);
|
|
156
|
+
console.log(`📝 Report written to: ${displayPath(resolvedOutputFile)}`);
|
|
157
|
+
}
|
|
158
|
+
return { secretsFound: false, report: emptyReport };
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (!options.quiet) {
|
|
163
|
+
console.log(` Scanning ${files.length} files...`);
|
|
164
|
+
}
|
|
165
|
+
// Scan each file for secrets
|
|
166
|
+
const allMatches = [];
|
|
167
|
+
const filesWithSecrets = new Set();
|
|
168
|
+
// Maximum file size to scan (10MB) - prevents DoS on huge files
|
|
169
|
+
const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
170
|
+
for (const file of files) {
|
|
171
|
+
try {
|
|
172
|
+
// Check file size before reading
|
|
173
|
+
const fileStats = await stat(file);
|
|
174
|
+
if (fileStats.size > MAX_FILE_SIZE) {
|
|
175
|
+
if (!options.quiet) {
|
|
176
|
+
console.warn(` ⚠️ Skipped ${file}: file too large (${Math.round(fileStats.size / 1024 / 1024)}MB > 10MB)`);
|
|
177
|
+
}
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const { text } = await readFileWithText(file);
|
|
181
|
+
const matches = scanFileForSecrets(file, text);
|
|
182
|
+
const filteredMatches = filterFalsePositives(matches);
|
|
183
|
+
if (filteredMatches.length > 0) {
|
|
184
|
+
allMatches.push(...filteredMatches);
|
|
185
|
+
filesWithSecrets.add(file);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
// Skip files that can't be read (binary, permissions, etc.)
|
|
190
|
+
if (!options.quiet) {
|
|
191
|
+
console.warn(` ⚠️ Skipped ${file}: ${error.message}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Generate report - convert absolute paths to relative before serializing
|
|
196
|
+
const report = {
|
|
197
|
+
type: 'LogicStampSecurityReport',
|
|
198
|
+
schemaVersion: '0.1',
|
|
199
|
+
createdAt: new Date().toISOString(),
|
|
200
|
+
projectRoot,
|
|
201
|
+
filesScanned: files.length,
|
|
202
|
+
secretsFound: allMatches.length,
|
|
203
|
+
matches: allMatches.map(match => ({
|
|
204
|
+
...match,
|
|
205
|
+
file: getRelativePath(projectRoot, match.file),
|
|
206
|
+
})),
|
|
207
|
+
filesWithSecrets: Array.from(filesWithSecrets)
|
|
208
|
+
.map(file => getRelativePath(projectRoot, file))
|
|
209
|
+
.sort(),
|
|
210
|
+
};
|
|
211
|
+
// Write report
|
|
212
|
+
const resolvedOutputDir = dirname(resolvedOutputFile);
|
|
213
|
+
try {
|
|
214
|
+
await mkdir(resolvedOutputDir, { recursive: true });
|
|
215
|
+
await writeFile(resolvedOutputFile, JSON.stringify(report, null, 2), 'utf8');
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
const err = error;
|
|
219
|
+
debugError('security', 'securityScanCommand', {
|
|
220
|
+
outputFile: resolvedOutputFile,
|
|
221
|
+
message: err.message,
|
|
222
|
+
code: err.code,
|
|
223
|
+
});
|
|
224
|
+
throw new Error(`Failed to write security report: ${err.message}`);
|
|
225
|
+
}
|
|
226
|
+
// Automatically ensure report file is in .gitignore to prevent accidental commits
|
|
227
|
+
// The report contains sensitive information (locations of secrets)
|
|
228
|
+
try {
|
|
229
|
+
const reportPathRelative = relative(projectRoot, resolvedOutputFile).replace(/\\/g, '/');
|
|
230
|
+
const isDefaultPath = outputPath === 'stamp_security_report.json' ||
|
|
231
|
+
(outputPath.endsWith('.json') && resolvedOutputFile.endsWith('stamp_security_report.json'));
|
|
232
|
+
if (isDefaultPath) {
|
|
233
|
+
// Default path - ensure all LogicStamp patterns are in .gitignore
|
|
234
|
+
await ensureGitignorePatterns(projectRoot);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// Custom path - ensure this specific file is in .gitignore
|
|
238
|
+
await ensurePatternInGitignore(projectRoot, reportPathRelative);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
// Non-fatal: log warning but don't fail the scan
|
|
243
|
+
if (!options.quiet) {
|
|
244
|
+
const err = error;
|
|
245
|
+
console.warn(`\n⚠️ Warning: Could not update .gitignore: ${err.message}`);
|
|
246
|
+
console.warn(` Please manually add the report file to .gitignore to prevent accidental commits.`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Display results
|
|
250
|
+
if (!options.quiet) {
|
|
251
|
+
console.log(`\n📊 Security Scan Results:`);
|
|
252
|
+
console.log(` Files scanned: ${files.length}`);
|
|
253
|
+
console.log(` Secrets found: ${allMatches.length}`);
|
|
254
|
+
console.log(` Files with secrets: ${filesWithSecrets.size}`);
|
|
255
|
+
if (allMatches.length > 0) {
|
|
256
|
+
console.log(`\n⚠️ Secrets detected in the following files:`);
|
|
257
|
+
// Group by file
|
|
258
|
+
const matchesByFile = new Map();
|
|
259
|
+
for (const match of allMatches) {
|
|
260
|
+
if (!matchesByFile.has(match.file)) {
|
|
261
|
+
matchesByFile.set(match.file, []);
|
|
262
|
+
}
|
|
263
|
+
matchesByFile.get(match.file).push(match);
|
|
264
|
+
}
|
|
265
|
+
for (const [file, matches] of matchesByFile.entries()) {
|
|
266
|
+
console.log(`\n ${displayPath(file)}`);
|
|
267
|
+
for (const match of matches.slice(0, 5)) { // Show first 5 matches per file
|
|
268
|
+
console.log(` Line ${match.line}: ${match.type} (${match.severity})`);
|
|
269
|
+
console.log(` ${match.snippet}`);
|
|
270
|
+
}
|
|
271
|
+
if (matches.length > 5) {
|
|
272
|
+
console.log(` ... and ${matches.length - 5} more`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
console.log(`\n📝 Report written to: ${displayPath(resolvedOutputFile)}`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
console.log(`\n✅ No secrets detected`);
|
|
279
|
+
console.log(`📝 Report written to: ${displayPath(outputFile)}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// Quiet mode: just output JSON stats
|
|
284
|
+
console.log(JSON.stringify({
|
|
285
|
+
filesScanned: files.length,
|
|
286
|
+
secretsFound: allMatches.length,
|
|
287
|
+
filesWithSecrets: filesWithSecrets.size,
|
|
288
|
+
reportPath: resolvedOutputFile,
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
// Exit with error code if secrets found (unless noExit is true)
|
|
292
|
+
if (allMatches.length > 0) {
|
|
293
|
+
if (options.noExit) {
|
|
294
|
+
return { secretsFound: true, report };
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (options.noExit) {
|
|
301
|
+
return { secretsFound: false, report };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../../src/cli/commands/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignoreHandler.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/ignoreHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handler for ignore command
|
|
3
|
+
*/
|
|
4
|
+
import { ignoreCommand } from '../commands/ignore.js';
|
|
5
|
+
import { parseIgnoreArgs } from '../parser/argumentParser.js';
|
|
6
|
+
import { getIgnoreHelp } from '../parser/helpText.js';
|
|
7
|
+
import { printFoxIcon } from './initHandler.js';
|
|
8
|
+
export async function handleIgnore(args) {
|
|
9
|
+
printFoxIcon();
|
|
10
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
11
|
+
console.log(getIgnoreHelp());
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
const options = parseIgnoreArgs(args);
|
|
15
|
+
try {
|
|
16
|
+
await ignoreCommand(options);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error('❌ Failed to add paths to .stampignore:', error.message);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=ignoreHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignoreHandler.js","sourceRoot":"","sources":["../../../src/cli/handlers/ignoreHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAsB,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAc;IAC/C,YAAY,EAAE,CAAC;IAEf,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"securityHandler.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/securityHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCtE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handler for security scan command
|
|
3
|
+
*/
|
|
4
|
+
import { securityScanCommand } from '../commands/security.js';
|
|
5
|
+
import { getSecurityScanHelp } from '../parser/helpText.js';
|
|
6
|
+
import { printFoxIcon } from './initHandler.js';
|
|
7
|
+
export async function handleSecurityScan(args) {
|
|
8
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
9
|
+
printFoxIcon();
|
|
10
|
+
console.log(getSecurityScanHelp());
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
const options = {
|
|
14
|
+
entry: undefined,
|
|
15
|
+
out: undefined,
|
|
16
|
+
quiet: args.includes('--quiet') || args.includes('-q'),
|
|
17
|
+
};
|
|
18
|
+
// Parse arguments
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === '--quiet' || arg === '-q') {
|
|
22
|
+
options.quiet = true;
|
|
23
|
+
}
|
|
24
|
+
else if (arg === '--out' || arg === '-o') {
|
|
25
|
+
options.out = args[i + 1];
|
|
26
|
+
i++;
|
|
27
|
+
}
|
|
28
|
+
else if (!arg.startsWith('-') && !options.entry) {
|
|
29
|
+
options.entry = arg;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
await securityScanCommand(options);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error('❌ Security scan failed:', error.message);
|
|
37
|
+
console.error(error.stack);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=securityHandler.js.map
|