ship-safe 3.0.0 → 3.2.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/README.md +626 -459
- package/cli/bin/ship-safe.js +200 -139
- package/cli/commands/agent.js +606 -0
- package/cli/commands/deps.js +447 -0
- package/cli/commands/fix.js +3 -3
- package/cli/commands/init.js +86 -3
- package/cli/commands/mcp.js +2 -2
- package/cli/commands/remediate.js +646 -0
- package/cli/commands/rotate.js +571 -0
- package/cli/commands/scan.js +64 -23
- package/cli/commands/score.js +446 -0
- package/cli/index.js +4 -1
- package/cli/utils/entropy.js +6 -0
- package/cli/utils/output.js +42 -2
- package/cli/utils/patterns.js +393 -1
- package/package.json +64 -63
package/cli/bin/ship-safe.js
CHANGED
|
@@ -1,139 +1,200 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Ship Safe CLI
|
|
5
|
-
* =============
|
|
6
|
-
*
|
|
7
|
-
* Security toolkit for vibe coders and indie hackers.
|
|
8
|
-
*
|
|
9
|
-
* USAGE:
|
|
10
|
-
* npx ship-safe scan [path] Scan for secrets in your codebase
|
|
11
|
-
* npx ship-safe checklist Run the launch-day security checklist
|
|
12
|
-
* npx ship-safe init Initialize security configs in your project
|
|
13
|
-
* npx ship-safe fix Generate .env.example from found secrets
|
|
14
|
-
* npx ship-safe guard Install pre-push git hook
|
|
15
|
-
* npx ship-safe --help Show all commands
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { program } from 'commander';
|
|
19
|
-
import chalk from 'chalk';
|
|
20
|
-
import { readFileSync } from 'fs';
|
|
21
|
-
import { fileURLToPath } from 'url';
|
|
22
|
-
import { dirname, join } from 'path';
|
|
23
|
-
import { scanCommand } from '../commands/scan.js';
|
|
24
|
-
import { checklistCommand } from '../commands/checklist.js';
|
|
25
|
-
import { initCommand } from '../commands/init.js';
|
|
26
|
-
import { fixCommand } from '../commands/fix.js';
|
|
27
|
-
import { guardCommand } from '../commands/guard.js';
|
|
28
|
-
import { mcpCommand } from '../commands/mcp.js';
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
${chalk.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.
|
|
67
|
-
.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// -----------------------------------------------------------------------------
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.
|
|
89
|
-
.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
.
|
|
101
|
-
.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
.
|
|
109
|
-
.
|
|
110
|
-
.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
.
|
|
118
|
-
.
|
|
119
|
-
.action(
|
|
120
|
-
|
|
121
|
-
// -----------------------------------------------------------------------------
|
|
122
|
-
//
|
|
123
|
-
// -----------------------------------------------------------------------------
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ship Safe CLI
|
|
5
|
+
* =============
|
|
6
|
+
*
|
|
7
|
+
* Security toolkit for vibe coders and indie hackers.
|
|
8
|
+
*
|
|
9
|
+
* USAGE:
|
|
10
|
+
* npx ship-safe scan [path] Scan for secrets in your codebase
|
|
11
|
+
* npx ship-safe checklist Run the launch-day security checklist
|
|
12
|
+
* npx ship-safe init Initialize security configs in your project
|
|
13
|
+
* npx ship-safe fix Generate .env.example from found secrets
|
|
14
|
+
* npx ship-safe guard Install pre-push git hook
|
|
15
|
+
* npx ship-safe --help Show all commands
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { program } from 'commander';
|
|
19
|
+
import chalk from 'chalk';
|
|
20
|
+
import { readFileSync } from 'fs';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
import { dirname, join } from 'path';
|
|
23
|
+
import { scanCommand } from '../commands/scan.js';
|
|
24
|
+
import { checklistCommand } from '../commands/checklist.js';
|
|
25
|
+
import { initCommand } from '../commands/init.js';
|
|
26
|
+
import { fixCommand } from '../commands/fix.js';
|
|
27
|
+
import { guardCommand } from '../commands/guard.js';
|
|
28
|
+
import { mcpCommand } from '../commands/mcp.js';
|
|
29
|
+
import { remediateCommand } from '../commands/remediate.js';
|
|
30
|
+
import { rotateCommand } from '../commands/rotate.js';
|
|
31
|
+
import { agentCommand } from '../commands/agent.js';
|
|
32
|
+
import { depsCommand } from '../commands/deps.js';
|
|
33
|
+
import { scoreCommand } from '../commands/score.js';
|
|
34
|
+
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// CLI CONFIGURATION
|
|
37
|
+
// =============================================================================
|
|
38
|
+
|
|
39
|
+
const DEFAULT_MODEL = 'claude-haiku-4-5-20251001';
|
|
40
|
+
|
|
41
|
+
// Read version from package.json
|
|
42
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
43
|
+
const __dirname = dirname(__filename);
|
|
44
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf8'));
|
|
45
|
+
const VERSION = packageJson.version;
|
|
46
|
+
|
|
47
|
+
// Banner shown on help
|
|
48
|
+
const banner = `
|
|
49
|
+
${chalk.cyan('███████╗██╗ ██╗██╗██████╗ ███████╗ █████╗ ███████╗███████╗')}
|
|
50
|
+
${chalk.cyan('██╔════╝██║ ██║██║██╔══██╗ ██╔════╝██╔══██╗██╔════╝██╔════╝')}
|
|
51
|
+
${chalk.cyan('███████╗███████║██║██████╔╝ ███████╗███████║█████╗ █████╗ ')}
|
|
52
|
+
${chalk.cyan('╚════██║██╔══██║██║██╔═══╝ ╚════██║██╔══██║██╔══╝ ██╔══╝ ')}
|
|
53
|
+
${chalk.cyan('███████║██║ ██║██║██║ ███████║██║ ██║██║ ███████╗')}
|
|
54
|
+
${chalk.cyan('╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝')}
|
|
55
|
+
|
|
56
|
+
${chalk.gray('Security toolkit for vibe coders. Secure your MVP in 5 minutes.')}
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
// =============================================================================
|
|
60
|
+
// PROGRAM SETUP
|
|
61
|
+
// =============================================================================
|
|
62
|
+
|
|
63
|
+
program
|
|
64
|
+
.name('ship-safe')
|
|
65
|
+
.description('Security toolkit for vibe coders and indie hackers')
|
|
66
|
+
.version(VERSION)
|
|
67
|
+
.addHelpText('before', banner);
|
|
68
|
+
|
|
69
|
+
// -----------------------------------------------------------------------------
|
|
70
|
+
// SCAN COMMAND
|
|
71
|
+
// -----------------------------------------------------------------------------
|
|
72
|
+
program
|
|
73
|
+
.command('scan [path]')
|
|
74
|
+
.description('Scan your codebase for leaked secrets (API keys, passwords, etc.)')
|
|
75
|
+
.option('-v, --verbose', 'Show all files being scanned')
|
|
76
|
+
.option('--no-color', 'Disable colored output')
|
|
77
|
+
.option('--json', 'Output results as JSON (useful for CI)')
|
|
78
|
+
.option('--sarif', 'Output results in SARIF format (for GitHub Code Scanning)')
|
|
79
|
+
.option('--include-tests', 'Also scan test files (excluded by default to reduce false positives)')
|
|
80
|
+
.action(scanCommand);
|
|
81
|
+
|
|
82
|
+
// -----------------------------------------------------------------------------
|
|
83
|
+
// CHECKLIST COMMAND
|
|
84
|
+
// -----------------------------------------------------------------------------
|
|
85
|
+
program
|
|
86
|
+
.command('checklist')
|
|
87
|
+
.description('Run through the launch-day security checklist interactively')
|
|
88
|
+
.option('--no-interactive', 'Print checklist without prompts')
|
|
89
|
+
.action(checklistCommand);
|
|
90
|
+
|
|
91
|
+
// -----------------------------------------------------------------------------
|
|
92
|
+
// INIT COMMAND
|
|
93
|
+
// -----------------------------------------------------------------------------
|
|
94
|
+
program
|
|
95
|
+
.command('init')
|
|
96
|
+
.description('Initialize security configs in your project')
|
|
97
|
+
.option('-f, --force', 'Overwrite existing files')
|
|
98
|
+
.option('--gitignore', 'Only copy .gitignore')
|
|
99
|
+
.option('--headers', 'Only copy security headers config')
|
|
100
|
+
.option('--agents', 'Only add security rules to AI agent instruction files (CLAUDE.md, .cursor/rules/, .windsurfrules, copilot-instructions.md)')
|
|
101
|
+
.action(initCommand);
|
|
102
|
+
|
|
103
|
+
// -----------------------------------------------------------------------------
|
|
104
|
+
// FIX COMMAND
|
|
105
|
+
// -----------------------------------------------------------------------------
|
|
106
|
+
program
|
|
107
|
+
.command('fix')
|
|
108
|
+
.description('Scan for secrets and generate a .env.example with placeholder values')
|
|
109
|
+
.option('--dry-run', 'Preview generated .env.example without writing it')
|
|
110
|
+
.action(fixCommand);
|
|
111
|
+
|
|
112
|
+
// -----------------------------------------------------------------------------
|
|
113
|
+
// GUARD COMMAND
|
|
114
|
+
// -----------------------------------------------------------------------------
|
|
115
|
+
program
|
|
116
|
+
.command('guard [action]')
|
|
117
|
+
.description('Install a git hook to block pushes if secrets are found')
|
|
118
|
+
.option('--pre-commit', 'Install as pre-commit hook instead of pre-push')
|
|
119
|
+
.action(guardCommand);
|
|
120
|
+
|
|
121
|
+
// -----------------------------------------------------------------------------
|
|
122
|
+
// MCP SERVER COMMAND
|
|
123
|
+
// -----------------------------------------------------------------------------
|
|
124
|
+
program
|
|
125
|
+
.command('mcp')
|
|
126
|
+
.description('Start ship-safe as an MCP server (for Claude Desktop, Cursor, Windsurf, etc.)')
|
|
127
|
+
.action(mcpCommand);
|
|
128
|
+
|
|
129
|
+
// -----------------------------------------------------------------------------
|
|
130
|
+
// REMEDIATE COMMAND
|
|
131
|
+
// -----------------------------------------------------------------------------
|
|
132
|
+
program
|
|
133
|
+
.command('remediate [path]')
|
|
134
|
+
.description('Auto-fix hardcoded secrets: rewrite source code + write .env + update .gitignore')
|
|
135
|
+
.option('--dry-run', 'Preview changes without writing any files')
|
|
136
|
+
.option('--yes', 'Apply all fixes without prompting (for CI)')
|
|
137
|
+
.option('--stage', 'Also run git add on modified files after fixing')
|
|
138
|
+
.action(remediateCommand);
|
|
139
|
+
|
|
140
|
+
// -----------------------------------------------------------------------------
|
|
141
|
+
// ROTATE COMMAND
|
|
142
|
+
// -----------------------------------------------------------------------------
|
|
143
|
+
program
|
|
144
|
+
.command('rotate [path]')
|
|
145
|
+
.description('Revoke and rotate exposed secrets — opens provider dashboards with step-by-step guide')
|
|
146
|
+
.option('--provider <name>', 'Only rotate secrets for a specific provider (e.g. github, stripe, openai)')
|
|
147
|
+
.action(rotateCommand);
|
|
148
|
+
|
|
149
|
+
// -----------------------------------------------------------------------------
|
|
150
|
+
// AGENT COMMAND
|
|
151
|
+
// -----------------------------------------------------------------------------
|
|
152
|
+
program
|
|
153
|
+
.command('agent [path]')
|
|
154
|
+
.description('AI-powered security audit: scan, classify with Claude, auto-remediate confirmed secrets')
|
|
155
|
+
.option('--dry-run', 'Show classification and plan without writing any files')
|
|
156
|
+
.option('--model <model>', `Claude model to use (default: ${DEFAULT_MODEL})`)
|
|
157
|
+
.action(agentCommand);
|
|
158
|
+
|
|
159
|
+
// -----------------------------------------------------------------------------
|
|
160
|
+
// DEPS COMMAND
|
|
161
|
+
// -----------------------------------------------------------------------------
|
|
162
|
+
program
|
|
163
|
+
.command('deps [path]')
|
|
164
|
+
.description('Audit dependencies for known CVEs (npm, yarn, pnpm, pip-audit, bundler-audit)')
|
|
165
|
+
.option('--fix', 'Run the package manager fix command after auditing')
|
|
166
|
+
.action(depsCommand);
|
|
167
|
+
|
|
168
|
+
// -----------------------------------------------------------------------------
|
|
169
|
+
// SCORE COMMAND
|
|
170
|
+
// -----------------------------------------------------------------------------
|
|
171
|
+
program
|
|
172
|
+
.command('score [path]')
|
|
173
|
+
.description('Compute a 0-100 security health score for your project')
|
|
174
|
+
.option('--no-deps', 'Skip dependency audit')
|
|
175
|
+
.action(scoreCommand);
|
|
176
|
+
|
|
177
|
+
// -----------------------------------------------------------------------------
|
|
178
|
+
// PARSE AND RUN
|
|
179
|
+
// -----------------------------------------------------------------------------
|
|
180
|
+
|
|
181
|
+
// Show help if no command provided
|
|
182
|
+
if (process.argv.length === 2) {
|
|
183
|
+
console.log(banner);
|
|
184
|
+
console.log(chalk.yellow('\nQuick start:\n'));
|
|
185
|
+
console.log(chalk.white(' npx ship-safe agent . ') + chalk.gray('# AI audit: scan + classify + auto-fix'));
|
|
186
|
+
console.log(chalk.white(' npx ship-safe scan . ') + chalk.gray('# Scan for secrets'));
|
|
187
|
+
console.log(chalk.white(' npx ship-safe remediate . ') + chalk.gray('# Auto-fix: rewrite code + write .env'));
|
|
188
|
+
console.log(chalk.white(' npx ship-safe rotate . ') + chalk.gray('# Revoke exposed keys (provider guides)'));
|
|
189
|
+
console.log(chalk.white(' npx ship-safe fix ') + chalk.gray('# Generate .env.example from secrets'));
|
|
190
|
+
console.log(chalk.white(' npx ship-safe guard ') + chalk.gray('# Block git push if secrets found'));
|
|
191
|
+
console.log(chalk.white(' npx ship-safe checklist ') + chalk.gray('# Run security checklist'));
|
|
192
|
+
console.log(chalk.white(' npx ship-safe deps . ') + chalk.gray('# Audit dependencies for CVEs'));
|
|
193
|
+
console.log(chalk.white(' npx ship-safe score . ') + chalk.gray('# Security health score (0-100)'));
|
|
194
|
+
console.log(chalk.white(' npx ship-safe init ') + chalk.gray('# Add security configs to your project'));
|
|
195
|
+
console.log(chalk.white('\n npx ship-safe --help ') + chalk.gray('# Show all options'));
|
|
196
|
+
console.log();
|
|
197
|
+
process.exit(0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
program.parse();
|