ship-safe 1.0.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.
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Secret Detection Patterns
3
+ * =========================
4
+ *
5
+ * These regex patterns detect common secret formats.
6
+ * Each pattern includes:
7
+ * - name: Human-readable identifier
8
+ * - pattern: Regular expression
9
+ * - severity: 'critical' | 'high' | 'medium'
10
+ * - description: Why this matters
11
+ *
12
+ * MAINTENANCE NOTES:
13
+ * - Patterns should have low false-positive rates
14
+ * - Test new patterns against real codebases before adding
15
+ * - Order doesn't matter (all patterns are checked)
16
+ */
17
+
18
+ export const SECRET_PATTERNS = [
19
+ // =========================================================================
20
+ // CRITICAL: These are almost always real secrets
21
+ // =========================================================================
22
+ {
23
+ name: 'AWS Access Key ID',
24
+ pattern: /AKIA[0-9A-Z]{16}/g,
25
+ severity: 'critical',
26
+ description: 'AWS Access Keys can access your entire AWS account. Rotate immediately if exposed.'
27
+ },
28
+ {
29
+ name: 'AWS Secret Access Key',
30
+ pattern: /(?:aws_secret_access_key|aws_secret_key)[\s]*[=:][\s]*["']?([A-Za-z0-9/+=]{40})["']?/gi,
31
+ severity: 'critical',
32
+ description: 'AWS Secret Keys paired with Access Keys grant full AWS access.'
33
+ },
34
+ {
35
+ name: 'GitHub Personal Access Token',
36
+ pattern: /ghp_[a-zA-Z0-9]{36}/g,
37
+ severity: 'critical',
38
+ description: 'GitHub PATs can access repositories, create commits, and manage settings.'
39
+ },
40
+ {
41
+ name: 'GitHub OAuth Token',
42
+ pattern: /gho_[a-zA-Z0-9]{36}/g,
43
+ severity: 'critical',
44
+ description: 'GitHub OAuth tokens grant authorized application access.'
45
+ },
46
+ {
47
+ name: 'GitHub App Token',
48
+ pattern: /ghu_[a-zA-Z0-9]{36}|ghs_[a-zA-Z0-9]{36}/g,
49
+ severity: 'critical',
50
+ description: 'GitHub App tokens have installation-level access to repositories.'
51
+ },
52
+ {
53
+ name: 'Stripe Live Secret Key',
54
+ pattern: /sk_live_[a-zA-Z0-9]{24,}/g,
55
+ severity: 'critical',
56
+ description: 'Stripe live keys can process real payments and access customer data.'
57
+ },
58
+ {
59
+ name: 'Stripe Live Publishable Key',
60
+ pattern: /pk_live_[a-zA-Z0-9]{24,}/g,
61
+ severity: 'high',
62
+ description: 'Stripe publishable keys are less sensitive but should not be in server code.'
63
+ },
64
+ {
65
+ name: 'Private Key Block',
66
+ pattern: /-----BEGIN\s+(RSA\s+|EC\s+|DSA\s+|OPENSSH\s+)?PRIVATE\s+KEY-----/g,
67
+ severity: 'critical',
68
+ description: 'Private keys enable impersonation and decryption. Never commit these.'
69
+ },
70
+
71
+ // =========================================================================
72
+ // HIGH: Very likely to be secrets
73
+ // =========================================================================
74
+ {
75
+ name: 'OpenAI API Key',
76
+ pattern: /sk-[a-zA-Z0-9]{20,}/g,
77
+ severity: 'high',
78
+ description: 'OpenAI keys can rack up API charges and access your usage history.'
79
+ },
80
+ {
81
+ name: 'Anthropic API Key',
82
+ pattern: /sk-ant-[a-zA-Z0-9-]{32,}/g,
83
+ severity: 'high',
84
+ description: 'Anthropic API keys grant access to Claude and your usage quota.'
85
+ },
86
+ {
87
+ name: 'Slack Token',
88
+ pattern: /xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*/g,
89
+ severity: 'high',
90
+ description: 'Slack tokens can read messages, post content, and access workspace data.'
91
+ },
92
+ {
93
+ name: 'Slack Webhook',
94
+ pattern: /https:\/\/hooks\.slack\.com\/services\/T[a-zA-Z0-9_]+\/B[a-zA-Z0-9_]+\/[a-zA-Z0-9_]+/g,
95
+ severity: 'high',
96
+ description: 'Slack webhooks allow posting messages to channels.'
97
+ },
98
+ {
99
+ name: 'Discord Webhook',
100
+ pattern: /https:\/\/discord(?:app)?\.com\/api\/webhooks\/[0-9]+\/[a-zA-Z0-9_-]+/g,
101
+ severity: 'high',
102
+ description: 'Discord webhooks allow posting messages to channels.'
103
+ },
104
+ {
105
+ name: 'Discord Bot Token',
106
+ pattern: /[MN][A-Za-z\d]{23,}\.[\w-]{6}\.[\w-]{27}/g,
107
+ severity: 'high',
108
+ description: 'Discord bot tokens grant full control over your bot.'
109
+ },
110
+ {
111
+ name: 'Twilio API Key',
112
+ pattern: /SK[a-f0-9]{32}/g,
113
+ severity: 'high',
114
+ description: 'Twilio keys can send SMS/calls and access account data.'
115
+ },
116
+ {
117
+ name: 'SendGrid API Key',
118
+ pattern: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g,
119
+ severity: 'high',
120
+ description: 'SendGrid keys can send emails from your account.'
121
+ },
122
+ {
123
+ name: 'Mailgun API Key',
124
+ pattern: /key-[a-zA-Z0-9]{32}/g,
125
+ severity: 'high',
126
+ description: 'Mailgun keys can send emails and access logs.'
127
+ },
128
+ {
129
+ name: 'Firebase/Google Service Account',
130
+ pattern: /"type":\s*"service_account"/g,
131
+ severity: 'high',
132
+ description: 'Service account JSON files grant broad GCP/Firebase access.'
133
+ },
134
+ {
135
+ name: 'Supabase Service Role Key',
136
+ pattern: /eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g,
137
+ severity: 'high',
138
+ description: 'Supabase service role keys bypass Row Level Security. Keep server-side only.'
139
+ },
140
+ {
141
+ name: 'Vercel Token',
142
+ pattern: /vercel_[a-zA-Z0-9]{24}/gi,
143
+ severity: 'high',
144
+ description: 'Vercel tokens can deploy and manage your projects.'
145
+ },
146
+ {
147
+ name: 'NPM Token',
148
+ pattern: /npm_[a-zA-Z0-9]{36}/g,
149
+ severity: 'high',
150
+ description: 'NPM tokens can publish packages under your account.'
151
+ },
152
+ {
153
+ name: 'Heroku API Key',
154
+ pattern: /[hH]eroku.*[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/g,
155
+ severity: 'high',
156
+ description: 'Heroku API keys can manage apps and dynos.'
157
+ },
158
+ {
159
+ name: 'DigitalOcean Token',
160
+ pattern: /dop_v1_[a-f0-9]{64}/g,
161
+ severity: 'high',
162
+ description: 'DigitalOcean tokens can manage droplets and resources.'
163
+ },
164
+
165
+ // =========================================================================
166
+ // MEDIUM: Likely secrets, but may have false positives
167
+ // =========================================================================
168
+ {
169
+ name: 'Generic API Key',
170
+ pattern: /["']?(?:api[_-]?key|apikey)["']?\s*[:=]\s*["']([a-zA-Z0-9_\-]{16,})["']/gi,
171
+ severity: 'medium',
172
+ description: 'Hardcoded API keys should be moved to environment variables.'
173
+ },
174
+ {
175
+ name: 'Generic Secret',
176
+ pattern: /["']?(?:secret|secret[_-]?key)["']?\s*[:=]\s*["']([a-zA-Z0-9_\-]{16,})["']/gi,
177
+ severity: 'medium',
178
+ description: 'Hardcoded secrets should be moved to environment variables.'
179
+ },
180
+ {
181
+ name: 'Password Assignment',
182
+ pattern: /["']?password["']?\s*[:=]\s*["']([^"']{8,})["']/gi,
183
+ severity: 'medium',
184
+ description: 'Hardcoded passwords are a critical vulnerability.'
185
+ },
186
+ {
187
+ name: 'Database URL with Credentials',
188
+ pattern: /(mongodb|postgres|postgresql|mysql|redis):\/\/[^:]+:[^@]+@[^\s"']+/gi,
189
+ severity: 'medium',
190
+ description: 'Database URLs with embedded passwords expose your database.'
191
+ },
192
+ {
193
+ name: 'Bearer Token',
194
+ pattern: /["']Bearer\s+[a-zA-Z0-9_\-\.=]{20,}["']/gi,
195
+ severity: 'medium',
196
+ description: 'Hardcoded bearer tokens should not be in source code.'
197
+ },
198
+ {
199
+ name: 'JWT Token',
200
+ pattern: /["']?jwt["']?\s*[:=]\s*["']?(eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*)["']?/gi,
201
+ severity: 'medium',
202
+ description: 'JWTs in source code may be test tokens, but verify they\'re not production.'
203
+ },
204
+ {
205
+ name: 'Basic Auth Header',
206
+ pattern: /["']Basic\s+[A-Za-z0-9+/=]{10,}["']/gi,
207
+ severity: 'medium',
208
+ description: 'Basic auth headers contain base64-encoded credentials.'
209
+ }
210
+ ];
211
+
212
+ // =============================================================================
213
+ // FILES AND DIRECTORIES TO SKIP
214
+ // =============================================================================
215
+
216
+ export const SKIP_DIRS = new Set([
217
+ 'node_modules',
218
+ '.git',
219
+ 'venv',
220
+ 'env',
221
+ '.venv',
222
+ '__pycache__',
223
+ '.next',
224
+ '.nuxt',
225
+ 'dist',
226
+ 'build',
227
+ 'out',
228
+ '.output',
229
+ 'coverage',
230
+ '.nyc_output',
231
+ 'vendor',
232
+ '.bundle',
233
+ '.cache',
234
+ '.parcel-cache',
235
+ '.turbo',
236
+ 'bower_components',
237
+ 'jspm_packages',
238
+ '.vercel',
239
+ '.netlify',
240
+ '.serverless'
241
+ ]);
242
+
243
+ export const SKIP_EXTENSIONS = new Set([
244
+ // Images
245
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.webp', '.bmp', '.tiff',
246
+ // Fonts
247
+ '.woff', '.woff2', '.ttf', '.eot', '.otf',
248
+ // Media
249
+ '.mp3', '.mp4', '.wav', '.avi', '.mov', '.webm', '.ogg',
250
+ // Archives
251
+ '.zip', '.tar', '.gz', '.rar', '.7z', '.bz2',
252
+ // Documents
253
+ '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
254
+ // Lock files (usually very large and auto-generated)
255
+ '.lock',
256
+ // Minified files
257
+ '.min.js', '.min.css',
258
+ // Binaries
259
+ '.exe', '.dll', '.so', '.dylib', '.bin', '.o', '.a',
260
+ // Maps
261
+ '.map'
262
+ ]);
263
+
264
+ // Maximum file size to scan (1MB)
265
+ export const MAX_FILE_SIZE = 1_000_000;
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Ship Safe - Next.js Security Headers Configuration
3
+ * ===================================================
4
+ *
5
+ * Drop this into your next.config.js to add essential security headers.
6
+ *
7
+ * WHY THESE HEADERS MATTER:
8
+ * Without security headers, your app is vulnerable to:
9
+ * - Clickjacking (your site loaded in malicious iframes)
10
+ * - XSS attacks (malicious scripts injected into your pages)
11
+ * - MIME sniffing (browsers misinterpreting file types)
12
+ * - Protocol downgrade attacks (HTTPS -> HTTP)
13
+ *
14
+ * HOW TO USE:
15
+ * 1. Copy this file to your Next.js project root
16
+ * 2. Import and spread into your next.config.js (see example at bottom)
17
+ *
18
+ * TEST YOUR HEADERS:
19
+ * After deploying, check your score at: https://securityheaders.com
20
+ */
21
+
22
+ const securityHeaders = [
23
+ // ==========================================================================
24
+ // CLICKJACKING PROTECTION
25
+ // ==========================================================================
26
+ {
27
+ key: 'X-Frame-Options',
28
+ value: 'DENY'
29
+ // WHAT: Prevents your site from being embedded in iframes
30
+ // WHY: Attackers could overlay invisible buttons on your site (clickjacking)
31
+ // OPTIONS:
32
+ // 'DENY' - Never allow framing (most secure)
33
+ // 'SAMEORIGIN' - Only allow framing by your own site
34
+ // NOTE: Use 'SAMEORIGIN' if you need iframes for your own features
35
+ },
36
+
37
+ // ==========================================================================
38
+ // XSS PROTECTION
39
+ // ==========================================================================
40
+ {
41
+ key: 'X-XSS-Protection',
42
+ value: '1; mode=block'
43
+ // WHAT: Enables browser's built-in XSS filter
44
+ // WHY: Adds a layer of defense against reflected XSS attacks
45
+ // NOTE: Modern browsers use CSP instead, but this helps older browsers
46
+ },
47
+ {
48
+ key: 'X-Content-Type-Options',
49
+ value: 'nosniff'
50
+ // WHAT: Prevents browsers from MIME-sniffing (guessing file types)
51
+ // WHY: Attackers could trick browsers into executing malicious content
52
+ // by serving scripts with incorrect MIME types
53
+ },
54
+
55
+ // ==========================================================================
56
+ // HTTPS ENFORCEMENT
57
+ // ==========================================================================
58
+ {
59
+ key: 'Strict-Transport-Security',
60
+ value: 'max-age=31536000; includeSubDomains; preload'
61
+ // WHAT: Forces browsers to always use HTTPS for your site
62
+ // WHY: Prevents protocol downgrade attacks and cookie hijacking
63
+ // BREAKDOWN:
64
+ // max-age=31536000 - Remember for 1 year (in seconds)
65
+ // includeSubDomains - Apply to all subdomains too
66
+ // preload - Allow inclusion in browser's HSTS preload list
67
+ // WARNING: Only enable 'preload' if you're CERTAIN all subdomains support HTTPS
68
+ },
69
+
70
+ // ==========================================================================
71
+ // REFERRER POLICY
72
+ // ==========================================================================
73
+ {
74
+ key: 'Referrer-Policy',
75
+ value: 'strict-origin-when-cross-origin'
76
+ // WHAT: Controls how much referrer info is sent to other sites
77
+ // WHY: Prevents leaking sensitive URLs (with tokens, user IDs, etc.)
78
+ // THIS SETTING: Send origin only (not full URL) for cross-origin requests
79
+ // OPTIONS:
80
+ // 'no-referrer' - Never send referrer (most private, may break analytics)
81
+ // 'strict-origin' - Only send origin, never on HTTP downgrade
82
+ // 'strict-origin-when-cross-origin' - Full URL same-site, origin cross-site
83
+ },
84
+
85
+ // ==========================================================================
86
+ // PERMISSIONS POLICY (formerly Feature-Policy)
87
+ // ==========================================================================
88
+ {
89
+ key: 'Permissions-Policy',
90
+ value: 'camera=(), microphone=(), geolocation=(), interest-cohort=()'
91
+ // WHAT: Disables browser features you don't need
92
+ // WHY: Reduces attack surface; malicious scripts can't access these APIs
93
+ // THIS SETTING: Disables camera, mic, location, and FLoC tracking
94
+ // CUSTOMIZE: If you need camera/mic (e.g., for video chat), update this:
95
+ // camera=(self) - Allow camera only from your own origin
96
+ // microphone=(self "https://trusted-site.com") - Allow from specific origins
97
+ },
98
+
99
+ // ==========================================================================
100
+ // CONTENT SECURITY POLICY (CSP)
101
+ // ==========================================================================
102
+ // CSP is your most powerful defense against XSS attacks.
103
+ // It tells the browser exactly which resources are allowed to load.
104
+ //
105
+ // WARNING: CSP can break your site if misconfigured!
106
+ // Start with 'Content-Security-Policy-Report-Only' to test without blocking.
107
+ {
108
+ key: 'Content-Security-Policy',
109
+ value: [
110
+ // DEFAULT: Block everything not explicitly allowed
111
+ "default-src 'self'",
112
+
113
+ // SCRIPTS: Only from your domain + inline scripts (needed for Next.js)
114
+ // NOTE: 'unsafe-inline' is needed for Next.js. For maximum security,
115
+ // use nonces instead (requires custom server setup)
116
+ "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
117
+
118
+ // STYLES: Your domain + inline styles (needed for most CSS-in-JS)
119
+ "style-src 'self' 'unsafe-inline'",
120
+
121
+ // IMAGES: Your domain + data URIs + common CDNs
122
+ // ADD your image CDN here if needed (e.g., images.unsplash.com)
123
+ "img-src 'self' data: blob: https:",
124
+
125
+ // FONTS: Your domain + Google Fonts
126
+ "font-src 'self' https://fonts.gstatic.com",
127
+
128
+ // CONNECTIONS (fetch, WebSocket, etc.): Your domain + your API
129
+ // ADD your API domains here
130
+ "connect-src 'self' https://api.openai.com https://api.anthropic.com",
131
+
132
+ // FRAMES: Block all iframes by default
133
+ // Change to 'self' if you need iframes from your own domain
134
+ "frame-src 'none'",
135
+
136
+ // PREVENT your site from being framed
137
+ "frame-ancestors 'none'",
138
+
139
+ // FORMS: Only submit to your own domain
140
+ "form-action 'self'",
141
+
142
+ // BASE URI: Prevent base tag injection
143
+ "base-uri 'self'",
144
+
145
+ // UPGRADE insecure requests to HTTPS
146
+ "upgrade-insecure-requests",
147
+ ].join('; ')
148
+ //
149
+ // DEBUGGING CSP:
150
+ // 1. Open browser DevTools > Console
151
+ // 2. Look for "Refused to load..." errors
152
+ // 3. Add the blocked domain to the appropriate directive
153
+ //
154
+ // COMMON ADDITIONS:
155
+ // - Google Analytics: Add to script-src and connect-src
156
+ // script-src: https://www.googletagmanager.com
157
+ // connect-src: https://www.google-analytics.com
158
+ // - Stripe:
159
+ // script-src: https://js.stripe.com
160
+ // frame-src: https://js.stripe.com
161
+ },
162
+ ];
163
+
164
+ /**
165
+ * Export the headers configuration for next.config.js
166
+ *
167
+ * USAGE IN next.config.js:
168
+ *
169
+ * const { securityHeadersConfig } = require('./nextjs-security-headers');
170
+ *
171
+ * module.exports = {
172
+ * ...securityHeadersConfig,
173
+ * // your other config options...
174
+ * };
175
+ *
176
+ * OR for ES modules (next.config.mjs):
177
+ *
178
+ * import { securityHeadersConfig } from './nextjs-security-headers.js';
179
+ *
180
+ * export default {
181
+ * ...securityHeadersConfig,
182
+ * // your other config options...
183
+ * };
184
+ */
185
+ const securityHeadersConfig = {
186
+ async headers() {
187
+ return [
188
+ {
189
+ // Apply to all routes
190
+ source: '/:path*',
191
+ headers: securityHeaders,
192
+ },
193
+ ];
194
+ },
195
+ };
196
+
197
+ // =============================================================================
198
+ // COMPLETE EXAMPLE: next.config.js
199
+ // =============================================================================
200
+ /*
201
+ // next.config.js (CommonJS)
202
+ const { securityHeadersConfig } = require('./nextjs-security-headers');
203
+
204
+ module.exports = {
205
+ ...securityHeadersConfig,
206
+ reactStrictMode: true,
207
+ // ... your other config
208
+ };
209
+
210
+ // OR next.config.mjs (ES Modules)
211
+ import { securityHeadersConfig } from './nextjs-security-headers.js';
212
+
213
+ export default {
214
+ ...securityHeadersConfig,
215
+ reactStrictMode: true,
216
+ // ... your other config
217
+ };
218
+ */
219
+
220
+ module.exports = { securityHeaders, securityHeadersConfig };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "ship-safe",
3
+ "version": "1.0.0",
4
+ "description": "Security toolkit for vibe coders and indie hackers. Secure your MVP in 5 minutes.",
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",
12
+ "lint": "eslint cli/",
13
+ "ship-safe": "node cli/bin/ship-safe.js"
14
+ },
15
+ "keywords": [
16
+ "security",
17
+ "secrets",
18
+ "scanner",
19
+ "devops",
20
+ "devsecops",
21
+ "api-keys",
22
+ "gitignore",
23
+ "indie-hacker",
24
+ "vibe-coding",
25
+ "mvp",
26
+ "cli"
27
+ ],
28
+ "author": "",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/asamassekou10/ship-safe.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/asamassekou10/ship-safe/issues"
36
+ },
37
+ "homepage": "https://github.com/asamassekou10/ship-safe#readme",
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
41
+ "files": [
42
+ "cli/",
43
+ "checklists/",
44
+ "configs/",
45
+ "snippets/",
46
+ "ai-defense/"
47
+ ],
48
+ "dependencies": {
49
+ "chalk": "^5.3.0",
50
+ "commander": "^12.1.0",
51
+ "glob": "^10.3.10",
52
+ "ora": "^8.0.1"
53
+ }
54
+ }
@@ -0,0 +1,58 @@
1
+ # Security Snippets
2
+
3
+ **Copy-paste code blocks for common security patterns.**
4
+
5
+ This folder contains drop-in code snippets for securing your application. Each snippet is heavily commented to explain *why* it works.
6
+
7
+ ---
8
+
9
+ ## Coming Soon
10
+
11
+ - **Rate Limiting**
12
+ - Express.js middleware
13
+ - Next.js API route wrapper
14
+ - Upstash Redis implementation
15
+
16
+ - **Authentication**
17
+ - Secure session configuration
18
+ - JWT validation middleware
19
+ - OAuth state parameter handling
20
+
21
+ - **Input Validation**
22
+ - Zod schemas for common patterns
23
+ - SQL injection prevention
24
+ - XSS sanitization
25
+
26
+ - **API Security**
27
+ - CORS configuration
28
+ - API key validation
29
+ - Webhook signature verification (Stripe, GitHub)
30
+
31
+ ---
32
+
33
+ ## Contributing
34
+
35
+ Have a security snippet that saved your app? Add it here!
36
+
37
+ 1. Create a new file: `snippets/your-snippet-name.{js,ts,py}`
38
+ 2. Add extensive comments explaining:
39
+ - What attack this prevents
40
+ - How to integrate it
41
+ - Common gotchas
42
+ 3. Open a PR
43
+
44
+ ---
45
+
46
+ ## Usage Pattern
47
+
48
+ Each snippet follows this format:
49
+
50
+ ```
51
+ // =============================================================================
52
+ // WHAT: Brief description
53
+ // WHY: What attack/vulnerability this prevents
54
+ // HOW: Integration instructions
55
+ // =============================================================================
56
+
57
+ [actual code with inline comments]
58
+ ```