ship-safe 6.1.1 → 6.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.
Files changed (47) hide show
  1. package/README.md +735 -641
  2. package/cli/agents/api-fuzzer.js +345 -345
  3. package/cli/agents/auth-bypass-agent.js +348 -348
  4. package/cli/agents/base-agent.js +272 -272
  5. package/cli/agents/cicd-scanner.js +236 -201
  6. package/cli/agents/config-auditor.js +521 -521
  7. package/cli/agents/deep-analyzer.js +6 -2
  8. package/cli/agents/git-history-scanner.js +170 -170
  9. package/cli/agents/html-reporter.js +568 -568
  10. package/cli/agents/index.js +84 -84
  11. package/cli/agents/injection-tester.js +500 -500
  12. package/cli/agents/llm-redteam.js +251 -251
  13. package/cli/agents/mobile-scanner.js +231 -231
  14. package/cli/agents/orchestrator.js +322 -322
  15. package/cli/agents/pii-compliance-agent.js +301 -301
  16. package/cli/agents/scoring-engine.js +248 -248
  17. package/cli/agents/supabase-rls-agent.js +154 -154
  18. package/cli/agents/supply-chain-agent.js +650 -507
  19. package/cli/bin/ship-safe.js +452 -426
  20. package/cli/commands/agent.js +608 -608
  21. package/cli/commands/audit.js +986 -980
  22. package/cli/commands/baseline.js +193 -193
  23. package/cli/commands/ci.js +342 -342
  24. package/cli/commands/deps.js +516 -516
  25. package/cli/commands/doctor.js +159 -159
  26. package/cli/commands/fix.js +218 -218
  27. package/cli/commands/hooks.js +268 -0
  28. package/cli/commands/init.js +407 -407
  29. package/cli/commands/mcp.js +304 -304
  30. package/cli/commands/red-team.js +7 -1
  31. package/cli/commands/remediate.js +798 -798
  32. package/cli/commands/rotate.js +571 -571
  33. package/cli/commands/scan.js +569 -569
  34. package/cli/commands/score.js +449 -449
  35. package/cli/commands/watch.js +281 -281
  36. package/cli/hooks/patterns.js +313 -0
  37. package/cli/hooks/post-tool-use.js +140 -0
  38. package/cli/hooks/pre-tool-use.js +186 -0
  39. package/cli/index.js +73 -69
  40. package/cli/providers/llm-provider.js +397 -287
  41. package/cli/utils/autofix-rules.js +74 -74
  42. package/cli/utils/cache-manager.js +311 -311
  43. package/cli/utils/output.js +230 -230
  44. package/cli/utils/patterns.js +1121 -1121
  45. package/cli/utils/pdf-generator.js +94 -94
  46. package/package.json +69 -69
  47. package/configs/supabase/rls-templates.sql +0 -242
@@ -1,94 +1,94 @@
1
- /**
2
- * PDF Generator
3
- * ==============
4
- *
5
- * Zero-dependency PDF generation via Chrome/Chromium headless mode.
6
- * Falls back to generating a print-optimized HTML file if Chrome is not found.
7
- */
8
-
9
- import fs from 'fs';
10
- import path from 'path';
11
- import { execFileSync } from 'child_process';
12
-
13
- /**
14
- * Well-known Chrome/Chromium paths by platform.
15
- */
16
- function findChrome() {
17
- const candidates = process.platform === 'win32'
18
- ? [
19
- process.env.CHROME_PATH,
20
- 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
21
- 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
22
- process.env.LOCALAPPDATA && path.join(process.env.LOCALAPPDATA, 'Google\\Chrome\\Application\\chrome.exe'),
23
- ]
24
- : process.platform === 'darwin'
25
- ? [
26
- process.env.CHROME_PATH,
27
- '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
28
- '/Applications/Chromium.app/Contents/MacOS/Chromium',
29
- ]
30
- : [
31
- process.env.CHROME_PATH,
32
- '/usr/bin/google-chrome',
33
- '/usr/bin/google-chrome-stable',
34
- '/usr/bin/chromium',
35
- '/usr/bin/chromium-browser',
36
- '/snap/bin/chromium',
37
- ];
38
-
39
- for (const c of candidates) {
40
- if (c && fs.existsSync(c)) return c;
41
- }
42
- return null;
43
- }
44
-
45
- /**
46
- * Check if Chrome is available.
47
- */
48
- export function isChromeAvailable() {
49
- return findChrome() !== null;
50
- }
51
-
52
- /**
53
- * Generate PDF from an HTML file using Chrome headless.
54
- * Returns the output path, or null if Chrome is not available.
55
- */
56
- export function generatePDF(htmlPath, outputPath) {
57
- const chrome = findChrome();
58
- if (!chrome) return null;
59
-
60
- try {
61
- const args = [
62
- '--headless',
63
- '--disable-gpu',
64
- '--no-sandbox',
65
- `--print-to-pdf=${outputPath}`,
66
- '--print-to-pdf-no-header',
67
- htmlPath,
68
- ];
69
- execFileSync(chrome, args, { timeout: 30000, stdio: 'pipe' }); // ship-safe-ignore — execFileSync with fixed chrome binary path; no user input in command
70
- return outputPath;
71
- } catch {
72
- return null;
73
- }
74
- }
75
-
76
- /**
77
- * Generate a print-optimized HTML file as PDF fallback.
78
- */
79
- export function generatePrintHTML(htmlPath, outputPath) {
80
- let html = fs.readFileSync(htmlPath, 'utf-8');
81
- // Add print-optimized styles
82
- const printCSS = `
83
- <style media="print">
84
- body { background: #fff !important; color: #1e293b !important; }
85
- .score-card, .stat, .summary-card, .toc { background: #f8fafc !important; border: 1px solid #e2e8f0 !important; }
86
- table, th, td { border: 1px solid #e2e8f0 !important; }
87
- code { background: #f1f5f9 !important; color: #0f172a !important; }
88
- pre { background: #f1f5f9 !important; }
89
- a { color: #0369a1 !important; }
90
- </style>`;
91
- html = html.replace('</head>', printCSS + '\n</head>');
92
- fs.writeFileSync(outputPath, html);
93
- return outputPath;
94
- }
1
+ /**
2
+ * PDF Generator
3
+ * ==============
4
+ *
5
+ * Zero-dependency PDF generation via Chrome/Chromium headless mode.
6
+ * Falls back to generating a print-optimized HTML file if Chrome is not found.
7
+ */
8
+
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ import { execFileSync } from 'child_process';
12
+
13
+ /**
14
+ * Well-known Chrome/Chromium paths by platform.
15
+ */
16
+ function findChrome() {
17
+ const candidates = process.platform === 'win32'
18
+ ? [
19
+ process.env.CHROME_PATH,
20
+ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
21
+ 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
22
+ process.env.LOCALAPPDATA && path.join(process.env.LOCALAPPDATA, 'Google\\Chrome\\Application\\chrome.exe'),
23
+ ]
24
+ : process.platform === 'darwin'
25
+ ? [
26
+ process.env.CHROME_PATH,
27
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
28
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
29
+ ]
30
+ : [
31
+ process.env.CHROME_PATH,
32
+ '/usr/bin/google-chrome',
33
+ '/usr/bin/google-chrome-stable',
34
+ '/usr/bin/chromium',
35
+ '/usr/bin/chromium-browser',
36
+ '/snap/bin/chromium',
37
+ ];
38
+
39
+ for (const c of candidates) {
40
+ if (c && fs.existsSync(c)) return c;
41
+ }
42
+ return null;
43
+ }
44
+
45
+ /**
46
+ * Check if Chrome is available.
47
+ */
48
+ export function isChromeAvailable() {
49
+ return findChrome() !== null;
50
+ }
51
+
52
+ /**
53
+ * Generate PDF from an HTML file using Chrome headless.
54
+ * Returns the output path, or null if Chrome is not available.
55
+ */
56
+ export function generatePDF(htmlPath, outputPath) {
57
+ const chrome = findChrome();
58
+ if (!chrome) return null;
59
+
60
+ try {
61
+ const args = [
62
+ '--headless',
63
+ '--disable-gpu',
64
+ '--no-sandbox',
65
+ `--print-to-pdf=${outputPath}`,
66
+ '--print-to-pdf-no-header',
67
+ htmlPath,
68
+ ];
69
+ execFileSync(chrome, args, { timeout: 30000, stdio: 'pipe' }); // ship-safe-ignore — execFileSync with fixed chrome binary path; no user input in command
70
+ return outputPath;
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Generate a print-optimized HTML file as PDF fallback.
78
+ */
79
+ export function generatePrintHTML(htmlPath, outputPath) {
80
+ let html = fs.readFileSync(htmlPath, 'utf-8');
81
+ // Add print-optimized styles
82
+ const printCSS = `
83
+ <style media="print">
84
+ body { background: #fff !important; color: #1e293b !important; }
85
+ .score-card, .stat, .summary-card, .toc { background: #f8fafc !important; border: 1px solid #e2e8f0 !important; }
86
+ table, th, td { border: 1px solid #e2e8f0 !important; }
87
+ code { background: #f1f5f9 !important; color: #0f172a !important; }
88
+ pre { background: #f1f5f9 !important; }
89
+ a { color: #0369a1 !important; }
90
+ </style>`;
91
+ html = html.replace('</head>', printCSS + '\n</head>');
92
+ fs.writeFileSync(outputPath, html);
93
+ return outputPath;
94
+ }
package/package.json CHANGED
@@ -1,69 +1,69 @@
1
- {
2
- "name": "ship-safe",
3
- "version": "6.1.1",
4
- "description": "AI-powered multi-agent security platform. 18 agents scan 80+ attack classes with LLM-powered deep analysis. Red team your code before attackers do.",
5
- "main": "cli/index.js",
6
- "bin": {
7
- "ship-safe": "cli/bin/ship-safe.js"
8
- },
9
- "type": "module",
10
- "scripts": {
11
- "test": "node --test cli/__tests__/*.test.js",
12
- "lint": "eslint cli/",
13
- "ship-safe": "node cli/bin/ship-safe.js"
14
- },
15
- "keywords": [
16
- "security",
17
- "secrets",
18
- "scanner",
19
- "sast",
20
- "devsecops",
21
- "red-team",
22
- "penetration-testing",
23
- "vulnerability-scanner",
24
- "sbom",
25
- "owasp",
26
- "sql-injection",
27
- "xss",
28
- "ssrf",
29
- "supply-chain",
30
- "llm-security",
31
- "prompt-injection",
32
- "api-security",
33
- "docker-security",
34
- "kubernetes",
35
- "cicd-security",
36
- "mobile-security",
37
- "jwt",
38
- "cors",
39
- "cli"
40
- ],
41
- "author": "ship-safe contributors",
42
- "license": "MIT",
43
- "repository": {
44
- "type": "git",
45
- "url": "git+https://github.com/asamassekou10/ship-safe.git"
46
- },
47
- "bugs": {
48
- "url": "https://github.com/asamassekou10/ship-safe/issues"
49
- },
50
- "homepage": "https://github.com/asamassekou10/ship-safe#readme",
51
- "engines": {
52
- "node": ">=18.0.0"
53
- },
54
- "files": [
55
- "cli/",
56
- "!cli/__tests__/",
57
- "checklists/",
58
- "configs/",
59
- "snippets/",
60
- "ai-defense/"
61
- ],
62
- "dependencies": {
63
- "chalk": "^5.3.0",
64
- "commander": "^12.1.0",
65
- "fast-glob": "^3.3.3",
66
- "ora": "^8.0.1",
67
- "write-file-atomic": "^7.0.0"
68
- }
69
- }
1
+ {
2
+ "name": "ship-safe",
3
+ "version": "6.2.0",
4
+ "description": "AI-powered multi-agent security platform. 18 agents scan 80+ attack classes with LLM-powered deep analysis. Red team your code before attackers do.",
5
+ "main": "cli/index.js",
6
+ "bin": {
7
+ "ship-safe": "cli/bin/ship-safe.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "test": "node --test cli/__tests__/*.test.js",
12
+ "lint": "eslint cli/",
13
+ "ship-safe": "node cli/bin/ship-safe.js"
14
+ },
15
+ "keywords": [
16
+ "security",
17
+ "secrets",
18
+ "scanner",
19
+ "sast",
20
+ "devsecops",
21
+ "red-team",
22
+ "penetration-testing",
23
+ "vulnerability-scanner",
24
+ "sbom",
25
+ "owasp",
26
+ "sql-injection",
27
+ "xss",
28
+ "ssrf",
29
+ "supply-chain",
30
+ "llm-security",
31
+ "prompt-injection",
32
+ "api-security",
33
+ "docker-security",
34
+ "kubernetes",
35
+ "cicd-security",
36
+ "mobile-security",
37
+ "jwt",
38
+ "cors",
39
+ "cli"
40
+ ],
41
+ "author": "ship-safe contributors",
42
+ "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/asamassekou10/ship-safe.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/asamassekou10/ship-safe/issues"
49
+ },
50
+ "homepage": "https://github.com/asamassekou10/ship-safe#readme",
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ },
54
+ "files": [
55
+ "cli/",
56
+ "!cli/__tests__/",
57
+ "checklists/",
58
+ "configs/",
59
+ "snippets/",
60
+ "ai-defense/"
61
+ ],
62
+ "dependencies": {
63
+ "chalk": "^5.3.0",
64
+ "commander": "^12.1.0",
65
+ "fast-glob": "^3.3.3",
66
+ "ora": "^8.0.1",
67
+ "write-file-atomic": "^7.0.0"
68
+ }
69
+ }
@@ -1,242 +0,0 @@
1
- -- =============================================================================
2
- -- SUPABASE ROW LEVEL SECURITY (RLS) TEMPLATES
3
- -- =============================================================================
4
- --
5
- -- Copy-paste these policies to secure your Supabase tables.
6
- --
7
- -- WHY RLS MATTERS:
8
- -- Without RLS, anyone with your anon key can read/write ALL data.
9
- -- 83% of exposed Supabase databases have RLS misconfigurations.
10
- -- Source: https://byteiota.com/supabase-security-flaw-170-apps-exposed-by-missing-rls/
11
- --
12
- -- HOW TO USE:
13
- -- 1. Enable RLS on your table: ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
14
- -- 2. Copy the relevant policy below
15
- -- 3. Replace 'your_table' with your actual table name
16
- -- 4. Test with different user contexts
17
- --
18
- -- =============================================================================
19
-
20
-
21
- -- =============================================================================
22
- -- STEP 1: ALWAYS ENABLE RLS FIRST
23
- -- =============================================================================
24
-
25
- -- Enable RLS on a table (REQUIRED before adding policies)
26
- ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
27
-
28
- -- Force RLS for table owners too (recommended for security)
29
- ALTER TABLE your_table FORCE ROW LEVEL SECURITY;
30
-
31
-
32
- -- =============================================================================
33
- -- PATTERN 1: USER OWNS THEIR DATA
34
- -- =============================================================================
35
- -- Use when: Each user should only see/edit their own records
36
- -- Example tables: profiles, settings, user_preferences
37
-
38
- -- Users can only SELECT their own rows
39
- CREATE POLICY "Users can view own data"
40
- ON your_table
41
- FOR SELECT
42
- USING (auth.uid() = user_id);
43
-
44
- -- Users can only INSERT rows with their own user_id
45
- CREATE POLICY "Users can insert own data"
46
- ON your_table
47
- FOR INSERT
48
- WITH CHECK (auth.uid() = user_id);
49
-
50
- -- Users can only UPDATE their own rows
51
- CREATE POLICY "Users can update own data"
52
- ON your_table
53
- FOR UPDATE
54
- USING (auth.uid() = user_id)
55
- WITH CHECK (auth.uid() = user_id);
56
-
57
- -- Users can only DELETE their own rows
58
- CREATE POLICY "Users can delete own data"
59
- ON your_table
60
- FOR DELETE
61
- USING (auth.uid() = user_id);
62
-
63
- -- COMBINED: All operations for own data (simpler but less granular)
64
- CREATE POLICY "Users manage own data"
65
- ON your_table
66
- FOR ALL
67
- USING (auth.uid() = user_id)
68
- WITH CHECK (auth.uid() = user_id);
69
-
70
-
71
- -- =============================================================================
72
- -- PATTERN 2: ORGANIZATION/TEAM BASED ACCESS
73
- -- =============================================================================
74
- -- Use when: Users belong to orgs and should see all org data
75
- -- Example tables: projects, documents, team_settings
76
-
77
- -- First, create a helper function to get user's org
78
- CREATE OR REPLACE FUNCTION get_user_org_id()
79
- RETURNS UUID AS $$
80
- SELECT org_id FROM profiles WHERE id = auth.uid()
81
- $$ LANGUAGE SQL SECURITY DEFINER;
82
-
83
- -- Users can view all data in their organization
84
- CREATE POLICY "Org members can view org data"
85
- ON your_table
86
- FOR SELECT
87
- USING (org_id = get_user_org_id());
88
-
89
- -- Users can insert data into their organization
90
- CREATE POLICY "Org members can insert org data"
91
- ON your_table
92
- FOR INSERT
93
- WITH CHECK (org_id = get_user_org_id());
94
-
95
- -- Only allow updates to org data
96
- CREATE POLICY "Org members can update org data"
97
- ON your_table
98
- FOR UPDATE
99
- USING (org_id = get_user_org_id())
100
- WITH CHECK (org_id = get_user_org_id());
101
-
102
-
103
- -- =============================================================================
104
- -- PATTERN 3: ROLE-BASED ACCESS CONTROL (RBAC)
105
- -- =============================================================================
106
- -- Use when: Different users have different permission levels
107
- -- Example: admin, editor, viewer roles
108
-
109
- -- Helper function to check user role
110
- CREATE OR REPLACE FUNCTION get_user_role()
111
- RETURNS TEXT AS $$
112
- SELECT role FROM profiles WHERE id = auth.uid()
113
- $$ LANGUAGE SQL SECURITY DEFINER;
114
-
115
- -- Anyone authenticated can view (public within app)
116
- CREATE POLICY "Authenticated users can view"
117
- ON your_table
118
- FOR SELECT
119
- USING (auth.role() = 'authenticated');
120
-
121
- -- Only admins and editors can insert
122
- CREATE POLICY "Admins and editors can insert"
123
- ON your_table
124
- FOR INSERT
125
- WITH CHECK (get_user_role() IN ('admin', 'editor'));
126
-
127
- -- Only admins can delete
128
- CREATE POLICY "Only admins can delete"
129
- ON your_table
130
- FOR DELETE
131
- USING (get_user_role() = 'admin');
132
-
133
-
134
- -- =============================================================================
135
- -- PATTERN 4: PUBLIC READ, AUTHENTICATED WRITE
136
- -- =============================================================================
137
- -- Use when: Content is public but only logged-in users can contribute
138
- -- Example tables: blog_posts, comments, public_profiles
139
-
140
- -- Anyone can read (including anonymous)
141
- CREATE POLICY "Public read access"
142
- ON your_table
143
- FOR SELECT
144
- USING (true);
145
-
146
- -- Only authenticated users can insert
147
- CREATE POLICY "Authenticated users can insert"
148
- ON your_table
149
- FOR INSERT
150
- WITH CHECK (auth.role() = 'authenticated');
151
-
152
- -- Users can only update their own posts
153
- CREATE POLICY "Users can update own posts"
154
- ON your_table
155
- FOR UPDATE
156
- USING (auth.uid() = author_id)
157
- WITH CHECK (auth.uid() = author_id);
158
-
159
-
160
- -- =============================================================================
161
- -- PATTERN 5: PRIVATE BY DEFAULT (Explicit sharing)
162
- -- =============================================================================
163
- -- Use when: Data is private unless explicitly shared
164
- -- Example tables: documents, files with sharing
165
-
166
- -- Owner can always access
167
- CREATE POLICY "Owner full access"
168
- ON documents
169
- FOR ALL
170
- USING (auth.uid() = owner_id)
171
- WITH CHECK (auth.uid() = owner_id);
172
-
173
- -- Shared users can view (requires a shares table)
174
- CREATE POLICY "Shared users can view"
175
- ON documents
176
- FOR SELECT
177
- USING (
178
- auth.uid() = owner_id
179
- OR
180
- EXISTS (
181
- SELECT 1 FROM document_shares
182
- WHERE document_shares.document_id = documents.id
183
- AND document_shares.user_id = auth.uid()
184
- )
185
- );
186
-
187
-
188
- -- =============================================================================
189
- -- PATTERN 6: TIME-BASED ACCESS
190
- -- =============================================================================
191
- -- Use when: Content has publish dates or expiration
192
- -- Example tables: scheduled_posts, limited_offers
193
-
194
- -- Only show published content
195
- CREATE POLICY "Show only published content"
196
- ON posts
197
- FOR SELECT
198
- USING (
199
- published_at IS NOT NULL
200
- AND published_at <= NOW()
201
- AND (expires_at IS NULL OR expires_at > NOW())
202
- );
203
-
204
- -- Authors can always see their drafts
205
- CREATE POLICY "Authors see own drafts"
206
- ON posts
207
- FOR SELECT
208
- USING (auth.uid() = author_id);
209
-
210
-
211
- -- =============================================================================
212
- -- ANTI-PATTERNS: DON'T DO THIS
213
- -- =============================================================================
214
-
215
- -- BAD: Allows anyone to read everything
216
- -- CREATE POLICY "bad_policy" ON users FOR SELECT USING (true);
217
-
218
- -- BAD: No WITH CHECK means users could insert data for other users
219
- -- CREATE POLICY "bad_insert" ON posts FOR INSERT WITH CHECK (true);
220
-
221
- -- BAD: Missing USING clause on UPDATE allows updating any row
222
- -- CREATE POLICY "bad_update" ON posts FOR UPDATE WITH CHECK (auth.uid() = user_id);
223
-
224
-
225
- -- =============================================================================
226
- -- TESTING YOUR POLICIES
227
- -- =============================================================================
228
-
229
- -- Test as a specific user (in SQL editor)
230
- -- SET request.jwt.claim.sub = 'user-uuid-here';
231
- -- SELECT * FROM your_table;
232
-
233
- -- Check existing policies on a table
234
- SELECT * FROM pg_policies WHERE tablename = 'your_table';
235
-
236
- -- List all tables without RLS enabled (DANGER!)
237
- SELECT schemaname, tablename
238
- FROM pg_tables
239
- WHERE schemaname = 'public'
240
- AND tablename NOT IN (
241
- SELECT tablename FROM pg_policies
242
- );