swarmhack-cli 0.1.0 → 0.1.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.
package/README.md CHANGED
@@ -1,34 +1,73 @@
1
- # @prancer/swarmhack
1
+ # swarmhack-cli
2
2
 
3
3
  Neural swarm-based penetration testing framework.
4
4
 
5
+ ## What's New in v0.2.0
6
+
7
+ - **Runtime Modes**: Choose between `local` (direct execution) or `docker` (containerized) mode
8
+ - **OCSF 1.1.0 Reports**: Industry-standard vulnerability reports with optimized JSON structure
9
+ - **Prancer Portal Integration**: Secure authentication with Prancer Portal
10
+ - **Bundled Configuration**: Default config file included - no manual setup required
11
+ - **Multi-Platform Support**: Linux, macOS, and Windows binaries
12
+
5
13
  ## Installation
6
14
 
7
15
  ```bash
8
- npm install -g @prancer/swarmhack
16
+ npm install -g swarmhack-cli
9
17
  ```
10
18
 
11
19
  Or use npx:
12
20
 
13
21
  ```bash
14
- npx @prancer/swarmhack --help
22
+ npx swarmhack-cli --help
15
23
  ```
16
24
 
25
+ ## Configuration
26
+
27
+ SwarmHack includes a default configuration file (`config/swarmhack.yaml`) that is automatically used when running commands. You can override it by:
28
+
29
+ 1. **Using your own config file:**
30
+ ```bash
31
+ swarmhack spawn --config /path/to/your/config.yaml --target "http://example.com"
32
+ ```
33
+
34
+ 2. **Creating a local config in your project:**
35
+ Place `config/swarmhack.yaml` in your project root - it will be automatically detected.
36
+
37
+ 3. **Customizing the bundled config:**
38
+ Copy the bundled config to your project and modify it:
39
+ ```bash
40
+ cp $(npm root -g)/swarmhack-cli/config/swarmhack.yaml ./config/
41
+ ```
42
+
17
43
  ## CLI Usage
18
44
 
19
45
  ```bash
20
- # Run SQL injection scan
46
+ # Run SQL injection scan (local mode - default)
21
47
  swarmhack spawn --agents sqli \
22
48
  --target "http://example.com" \
23
49
  --customer "your-customer" \
24
50
  --token "your-token"
25
51
 
52
+ # Run in Docker mode (isolated execution)
53
+ swarmhack spawn --agents sqli \
54
+ --target "http://example.com" \
55
+ --runtime docker \
56
+ --docker-image "swarmhack/pentest:latest"
57
+
26
58
  # Run multiple agents
27
59
  swarmhack spawn --agents sqli,xss,csrf \
28
60
  --target "http://example.com" \
29
61
  --customer "your-customer" \
30
62
  --token "your-token"
31
63
 
64
+ # Run in Docker with custom image and volumes
65
+ swarmhack spawn --agents sqli \
66
+ --target "http://example.com" \
67
+ --runtime docker \
68
+ --docker-image "myregistry/swarmhack:v1.0" \
69
+ --docker-volume "/host/reports:/app/reports"
70
+
32
71
  # List available agents
33
72
  swarmhack agents list
34
73
 
@@ -36,10 +75,47 @@ swarmhack agents list
36
75
  swarmhack doctor
37
76
  ```
38
77
 
78
+ ## Runtime Modes
79
+
80
+ SwarmHack supports two runtime modes:
81
+
82
+ | Mode | Description | Use Case |
83
+ |------|-------------|----------|
84
+ | `local` | Run directly on host system | Development, CI/CD with pre-installed tools |
85
+ | `docker` | Run inside Docker containers | Production, isolated execution, portable |
86
+
87
+ ### CLI Runtime Options
88
+
89
+ | Option | Description |
90
+ |--------|-------------|
91
+ | `--runtime` | Runtime mode: `local` (default) or `docker` |
92
+ | `--docker-image` | Docker image to use (overrides config) |
93
+ | `--docker-container` | Custom container name |
94
+ | `--docker-volume` | Additional volumes (can be repeated) |
95
+ | `--docker-env` | Environment variables (format: KEY=VALUE) |
96
+
97
+ ### Config File Runtime Options
98
+
99
+ ```yaml
100
+ # In config/swarmhack.yaml
101
+ runtime:
102
+ mode: docker # or "local"
103
+ docker_image: swarmhack/pentest:latest
104
+ docker_auto_remove: true
105
+ docker_volumes:
106
+ - /host/reports:/app/reports
107
+ docker_env:
108
+ CUSTOM_VAR: value
109
+ docker_network: bridge
110
+ docker_resources:
111
+ memory: 1g
112
+ cpus: "1"
113
+ ```
114
+
39
115
  ## Node.js API
40
116
 
41
117
  ```javascript
42
- const swarmhack = require('@prancer/swarmhack');
118
+ const swarmhack = require('swarmhack-cli');
43
119
 
44
120
  // Run a scan
45
121
  const results = await swarmhack.scan({
@@ -93,11 +169,56 @@ docker run --rm \
93
169
  | `auth_bypass` | Authentication bypass |
94
170
  | `cmdi` | Command injection |
95
171
 
172
+ ## OCSF Reports
173
+
174
+ SwarmHack generates reports in [OCSF 1.1.0](https://schema.ocsf.io/) format, the industry standard for security findings:
175
+
176
+ ```json
177
+ {
178
+ "scan_info": {
179
+ "scanner": { "name": "SwarmHack", "vendor": "Prancer" },
180
+ "customer": "your-customer",
181
+ "target": "http://example.com",
182
+ "duration_formatted": "3m 11s",
183
+ "summary": { "findings_count": 5, "crown_jewels_count": 12 }
184
+ },
185
+ "class_name": "Vulnerability Finding",
186
+ "class_uid": 6001,
187
+ "findings": [...]
188
+ }
189
+ ```
190
+
191
+ ## Authentication
192
+
193
+ SwarmHack requires Prancer Portal authentication:
194
+
195
+ ```bash
196
+ swarmhack spawn \
197
+ --target "http://example.com" \
198
+ --agents sqli,xss \
199
+ --customer "your-customer" \
200
+ --token "your-32-char-token"
201
+ ```
202
+
203
+ Get your token from [Prancer Portal](https://portal.prancer.io) → Settings → Access Tokens.
204
+
96
205
  ## Requirements
97
206
 
98
207
  - Node.js 16+
99
208
  - Prancer Portal account (for `--token` and `--customer`)
100
209
 
210
+ ## Changelog
211
+
212
+ ### v0.2.0
213
+ - Added runtime mode selection (local/docker)
214
+ - Added OCSF 1.1.0 report generation
215
+ - Added Prancer Portal authentication
216
+ - Bundled default configuration file
217
+ - Multi-platform binary support
218
+
219
+ ### v0.1.0
220
+ - Initial release
221
+
101
222
  ## License
102
223
 
103
224
  MIT
package/bin/swarmhack.js CHANGED
@@ -65,9 +65,37 @@ Or use Docker instead:
65
65
  // Get binary path
66
66
  const binaryPath = getBinaryPath();
67
67
 
68
+ // Get config path - bundled with npm package
69
+ function getConfigPath() {
70
+ // Check if user already specified --config
71
+ const args = process.argv.slice(2);
72
+ if (args.includes('--config') || args.includes('-c')) {
73
+ return null; // User specified their own config
74
+ }
75
+
76
+ // Check for local config first (user's project)
77
+ const localConfig = path.join(process.cwd(), 'config', 'swarmhack.yaml');
78
+ if (fs.existsSync(localConfig)) {
79
+ return localConfig;
80
+ }
81
+
82
+ // Use bundled config from npm package
83
+ const bundledConfig = path.join(__dirname, '..', 'config', 'swarmhack.yaml');
84
+ if (fs.existsSync(bundledConfig)) {
85
+ return bundledConfig;
86
+ }
87
+
88
+ return null;
89
+ }
90
+
68
91
  // Spawn the binary with all arguments
69
92
  const args = process.argv.slice(2);
70
- const child = spawn(binaryPath, args, {
93
+ const configPath = getConfigPath();
94
+
95
+ // Add config flag if we have a bundled config and user didn't specify one
96
+ const finalArgs = configPath ? ['--config', configPath, ...args] : args;
97
+
98
+ const child = spawn(binaryPath, finalArgs, {
71
99
  stdio: 'inherit',
72
100
  env: {
73
101
  ...process.env,
@@ -0,0 +1,445 @@
1
+ # ========== RUNTIME ENVIRONMENT CONFIGURATION ==========
2
+ # Controls whether SwarmHack runs locally or inside Docker containers
3
+ runtime:
4
+ # Runtime mode: "local" or "docker"
5
+ # - local: Run directly on the host system (default, requires tools installed)
6
+ # - docker: Run inside Docker containers (portable, isolated)
7
+ mode: local
8
+
9
+ # Docker image to use when mode is "docker"
10
+ docker_image: swarmhack/pentest:latest
11
+
12
+ # Docker container name prefix
13
+ docker_container_prefix: swarmhack
14
+
15
+ # Auto-remove containers after execution
16
+ docker_auto_remove: true
17
+
18
+ # Additional Docker volumes (format: /host/path:/container/path)
19
+ docker_volumes: []
20
+
21
+ # Additional environment variables for Docker containers
22
+ docker_env: {}
23
+
24
+ # Docker network mode (bridge, host, none, or custom network name)
25
+ docker_network: bridge
26
+
27
+ # Pull policy: always, missing, never
28
+ docker_pull_policy: missing
29
+
30
+ # Docker socket path
31
+ docker_socket: /var/run/docker.sock
32
+
33
+ # Resource limits for Docker containers
34
+ docker_resources:
35
+ memory: 1g
36
+ cpus: "1"
37
+
38
+ queen:
39
+ topology: hierarchical # CHANGED: mesh → hierarchical for parent-child agent coordination
40
+ max_agents: 50
41
+ consensus_threshold: 0.67
42
+ spawn_strategy: dynamic
43
+
44
+ # ========== AUTHENTICATION DETECTION CONFIGURATION ==========
45
+ # BUG #11 FIX: Generic authentication detection patterns (NO HARDCODING)
46
+ authentication:
47
+ # Patterns indicating FAILED authentication (redirect to these = invalid session)
48
+ failed_auth_indicators:
49
+ - "/login"
50
+ - "/signin"
51
+ - "/auth"
52
+ - "/authenticate"
53
+ - "?login"
54
+ - "?signin"
55
+
56
+ # Patterns indicating SUCCESSFUL authentication (content contains these = valid session)
57
+ successful_auth_indicators:
58
+ - "logout"
59
+ - "sign out"
60
+ - "log out"
61
+ - "account"
62
+ - "dashboard"
63
+ - "profile"
64
+ - "settings"
65
+
66
+ # Negative indicators (if content has these, NOT authenticated)
67
+ negative_auth_indicators:
68
+ - "please log in"
69
+ - "please sign in"
70
+ - "authentication required"
71
+ - "please login"
72
+ - "login to continue"
73
+ - "<input[^>]*name=['\"]username"
74
+ - "<input[^>]*name=['\"]password"
75
+ - "<input[^>]*type=['\"]password"
76
+
77
+ # Cookie name patterns (regex)
78
+ session_cookie_patterns:
79
+ - ".*SESSIONID.*"
80
+ - ".*SID.*"
81
+ - ".*session.*"
82
+ - ".*token.*"
83
+ - ".*auth.*"
84
+
85
+ # Max redirects to follow
86
+ max_redirect_hops: 3
87
+
88
+ # Content-based authentication scoring
89
+ auth_score_threshold: 2
90
+
91
+ # ========== CREDENTIAL SYNTHESIS CONFIGURATION ==========
92
+ # BUG #11 FIX PHASE 2B: Generate potential credentials when SQLi yields 0 valid sessions
93
+ credential_synthesis:
94
+ enabled: true
95
+
96
+ # Default credentials by technology
97
+ default_credentials:
98
+ altoromutual:
99
+ - username: "admin"
100
+ password: "admin"
101
+ - username: "jsmith"
102
+ password: "demo1234"
103
+ demo_apps:
104
+ - username: "admin"
105
+ password: "password"
106
+ - username: "test"
107
+ password: "test"
108
+
109
+ # Common patterns
110
+ common_patterns:
111
+ - "admin:admin"
112
+ - "admin:password"
113
+ - "test:test"
114
+ - "demo:demo"
115
+ - "user:user"
116
+
117
+ # Field name mappings
118
+ field_mappings:
119
+ username_fields: ["uid", "username", "user", "login", "email"]
120
+ password_fields: ["passw", "password", "pass", "pwd"]
121
+
122
+ # Confidence scores
123
+ confidence:
124
+ form_inferred: 0.5
125
+ default_creds: 0.8 # BUG #11 FIX: Increased from 0.6 to 0.8 to ensure default credentials pass filtering
126
+ common_patterns: 0.3
127
+ vuln_context: 0.7
128
+
129
+ agents:
130
+ sqli:
131
+ enabled: true
132
+ databases: [mysql, postgresql, mssql, oracle, mongodb, sqlite] # ENHANCED: Added mssql, oracle, mongodb, sqlite
133
+ attack_types: [boolean, error, union, time, blind, stacked] # ENHANCED: Added union, time, blind, stacked
134
+ attack_mode: balanced
135
+ pentest_mode: true # Depth-first: stop after first SQLi, exploit deep (DB/tables/data extraction)
136
+ xss:
137
+ enabled: true
138
+ contexts: [html, javascript, attribute, url, css, json] # ENHANCED: Added javascript, attribute, url, css, json
139
+ attack_types: [reflected, stored, dom, blind] # ENHANCED: Added stored, dom, blind
140
+ attack_mode: balanced
141
+ pentest_mode: true # Depth-first: stop after first XSS, exploit deep (session hijack/cookie theft)
142
+ csrf:
143
+ enabled: true
144
+ attack_types: [form_submission, json_request, xml_request, multipart, ajax] # ENHANCED: Added json_request, xml_request, multipart, ajax
145
+ attack_mode: balanced
146
+ idor:
147
+ enabled: true
148
+ attack_types: [sequential, uuid, hash, encoded] # ENHANCED: Added uuid, hash, encoded
149
+ attack_mode: balanced
150
+ auth_bypass:
151
+ enabled: true
152
+ attack_types: [brute_force, sql_injection, logic_flaw, default_creds, credential_stuffing, session_hijack, jwt_manipulation] # ENHANCED: Added sql_injection, logic_flaw, default_creds, credential_stuffing, session_hijack, jwt_manipulation
153
+ attack_mode: balanced
154
+ cmdi:
155
+ enabled: true
156
+ attack_types: [time_based, output_based, error_based, blind]
157
+ operating_systems: [linux, windows, unix]
158
+ max_payloads: 100
159
+ time_delay: 5
160
+ attack_mode: balanced
161
+ crawler:
162
+ enabled: true
163
+ report_info_findings: false # Suppress API endpoint/tech fingerprint info findings
164
+ max_depth: 3
165
+ max_pages: 1000
166
+ requests_per_second: 10.0
167
+
168
+ memory:
169
+ agentdb:
170
+ vector_size: 384
171
+ hnsw_m: 16
172
+ hnsw_ef_construction: 200
173
+ quantization_enabled: false
174
+ persistence_path: .agentdb/vectors.db
175
+ use_real_embeddings: true
176
+ embedding_model: sentence-transformers/all-MiniLM-L6-v2
177
+ reasoningbank:
178
+ distillation_frequency: 100
179
+ min_trajectories: 50
180
+ confidence_threshold: 0.7
181
+ persistence_path: .reasoningbank/trajectories.db
182
+
183
+ pretraining:
184
+ enabled: false
185
+ data_directory: data/pretraining
186
+ quality_threshold: 80
187
+ enable_deduplication: true
188
+ enable_cognitive_tagging: true
189
+
190
+ evasion:
191
+ enable_firewall_evasion: false
192
+ enable_waf_bypass: false
193
+ enable_neural_generation: false
194
+ enable_autonomous_learning: false
195
+ timing_mode: sneaky
196
+ fragmentation_mtu: 1500
197
+ max_adaptation_attempts: 3
198
+
199
+ neural:
200
+ enable_neural_generation: false
201
+ enable_autonomous_learning: false
202
+ learning_rate: 0.01
203
+ mutation_count: 10
204
+
205
+ kill_chain:
206
+ phases: [recon, discovery, exploitation]
207
+
208
+ containers:
209
+ image: swarmhack/unified-pentest:latest
210
+ pool_size: 10
211
+ idle_timeout_seconds: 300
212
+ startup_timeout_seconds: 30
213
+
214
+ targets:
215
+ urls: []
216
+ domains: []
217
+ ip_ranges: []
218
+ exclusions: []
219
+
220
+ crown_jewels:
221
+ # ENHANCED: Comprehensive crown jewel detection patterns (4 → 60+ patterns)
222
+ patterns:
223
+ # Credentials & Passwords
224
+ - password
225
+ - passwd
226
+ - pwd
227
+ - pass
228
+ - credential
229
+ - credentials
230
+ - login
231
+ - username
232
+ - user_name
233
+
234
+ # API Keys & Secrets
235
+ - api_key
236
+ - apikey
237
+ - api-key
238
+ - api_secret
239
+ - secret
240
+ - secret_key
241
+ - client_secret
242
+ - app_secret
243
+
244
+ # Tokens & Authentication
245
+ - token
246
+ - access_token
247
+ - refresh_token
248
+ - auth_token
249
+ - bearer
250
+ - jwt
251
+ - session
252
+ - session_id
253
+ - cookie
254
+ - auth_cookie
255
+
256
+ # Private Keys & Certificates
257
+ - private_key
258
+ - privatekey
259
+ - private-key
260
+ - public_key
261
+ - certificate
262
+ - cert
263
+ - encryption_key
264
+ - signing_key
265
+ - ssh_key
266
+
267
+ # Database Connections
268
+ - connection_string
269
+ - db_password
270
+ - database_url
271
+ - database_password
272
+ - mongodb_uri
273
+ - redis_password
274
+ - postgres_password
275
+ - mysql_password
276
+
277
+ # Cloud Provider Credentials
278
+ - aws_access_key
279
+ - aws_secret_key
280
+ - aws_access_key_id
281
+ - aws_secret_access_key
282
+ - s3_bucket
283
+ - iam_role
284
+ - azure_key
285
+ - gcp_key
286
+ - google_api_key
287
+
288
+ # Payment Information
289
+ - credit_card
290
+ - creditcard
291
+ - card_number
292
+ - cvv
293
+ - card_cvv
294
+ - stripe_key
295
+ - paypal
296
+ - payment_token
297
+
298
+ # Personal Identifiable Information (PII)
299
+ - ssn
300
+ - social_security
301
+ - tax_id
302
+ - passport
303
+ - driver_license
304
+ - national_id
305
+ - phone_number
306
+ - email_address
307
+
308
+ # OAuth & Third-party
309
+ - oauth_token
310
+ - oauth_secret
311
+ - client_id
312
+ - client_credentials
313
+ - webhook_secret
314
+ - github_token
315
+ - gitlab_token
316
+
317
+ confidence_threshold: 0.8
318
+ max_extractions: 10000 # ENHANCED: Increased from 1000 to 10000 for comprehensive extraction
319
+
320
+ logging:
321
+ level: info
322
+ format: json
323
+ output_path: logs/swarmhack.log
324
+
325
+ rate_limiting:
326
+ requests_per_second: 10
327
+ burst_size: 20
328
+ algorithm: token_bucket
329
+ retry:
330
+ max_retries: 5
331
+ backoff_base_ms: 1000
332
+ max_backoff_ms: 16000
333
+ jitter_ms: 100
334
+
335
+ # ========== HYBRID MODE CONFIGURATION ==========
336
+ # Orchestrates Kill Chain → Extract Crown Jewels → AEL Amplification workflow
337
+ hybrid_mode:
338
+ # Enable hybrid mode (3-phase workflow)
339
+ enabled: true
340
+
341
+ # Minimum jewels required to trigger AEL phase (if fewer, return Kill Chain results only)
342
+ min_jewels_for_ael: 1
343
+
344
+ # Minimum confidence for extracting jewels from vulnerabilities
345
+ jewel_extraction_confidence_threshold: 0.7
346
+
347
+ # Target amplification factor (logging/metrics only, not enforced)
348
+ amplification_target: 5.0
349
+
350
+ # Vulnerability categories to extract crown jewels from
351
+ extraction_categories:
352
+ - sqli
353
+ - auth_bypass
354
+ - xss
355
+ - idor
356
+ - lfi
357
+ - rce
358
+
359
+ # Kill Chain phase timeout (seconds)
360
+ kill_chain_timeout_secs: 900
361
+
362
+ # AEL phase timeout (seconds)
363
+ ael_phase_timeout_secs: 1200
364
+
365
+ # Enable jewel type conversion (KC jewels → AEL jewels)
366
+ enable_type_conversion: true
367
+
368
+ # Conversion strictness (lenient|moderate|strict)
369
+ conversion_strictness: moderate
370
+
371
+ # Parallel execution for phases
372
+ enable_parallel_execution: true
373
+
374
+ # Deduplicate jewels between phases
375
+ deduplicate_jewels: true
376
+
377
+ # Merge strategy for final results (union|kill_chain_priority|ael_priority)
378
+ result_merge_strategy: union
379
+
380
+ # Report both individual phase results
381
+ report_phase_breakdown: true
382
+
383
+ # ========== EXTRACTION CONFIGURATION ==========
384
+ # SQL Injection Data Extraction System (enabled for testphp.vulnweb.com test)
385
+ extraction:
386
+ enabled: true
387
+
388
+ # Authorized targets for extraction (security control)
389
+ authorized_targets:
390
+ - "testphp.vulnweb.com"
391
+ - "*.vulnweb.com"
392
+
393
+ # Require explicit authorization flag
394
+ require_explicit_authorization: false
395
+
396
+ # Union-based extraction
397
+ union:
398
+ enabled: true
399
+ max_columns: 50
400
+ timeout_seconds: 30
401
+ max_rows: 1000
402
+
403
+ # Error-based extraction
404
+ error:
405
+ enabled: true
406
+ max_extractions: 100
407
+ databases: [mysql, postgresql, mssql]
408
+ timeout_seconds: 20
409
+
410
+ # Blind extraction
411
+ blind:
412
+ enabled: true
413
+ charset: "abcdefghijklmnopqrstuvwxyz0123456789_@.-"
414
+ max_length: 100
415
+ timeout_seconds: 60
416
+ binary_search: true
417
+
418
+ # Performance controls
419
+ max_concurrent_extractions: 3
420
+ total_timeout_seconds: 300
421
+
422
+ # Audit logging
423
+ audit:
424
+ enabled: true
425
+ log_path: logs/extraction_audit.log
426
+ include_data: true
427
+
428
+ # ========== OCSF REPORT OPTIMIZATION ==========
429
+ # Phase 1: Quick wins for report size reduction
430
+ reporting:
431
+ ocsf:
432
+ # Response body truncation (bytes, 0 = no truncation)
433
+ max_response_body_bytes: 500
434
+
435
+ # Verification steps limit (0 = no limit)
436
+ max_verification_steps: 3
437
+
438
+ # Deduplicate similar findings (Phase 2)
439
+ deduplicate_findings: true
440
+
441
+ # Include form fields in per-finding details
442
+ include_form_fields_per_finding: false
443
+
444
+ # Keep only security-relevant HTTP headers
445
+ security_headers_only: true
package/index.js CHANGED
@@ -31,10 +31,30 @@ function getBinaryPath() {
31
31
  throw new Error(`SwarmHack binary not found for ${platform}-${arch}`);
32
32
  }
33
33
 
34
+ /**
35
+ * Get path to bundled config file
36
+ */
37
+ function getConfigPath() {
38
+ // Check for local config first (user's project)
39
+ const localConfig = path.join(process.cwd(), 'config', 'swarmhack.yaml');
40
+ if (fs.existsSync(localConfig)) {
41
+ return localConfig;
42
+ }
43
+
44
+ // Use bundled config from npm package
45
+ const bundledConfig = path.join(__dirname, 'config', 'swarmhack.yaml');
46
+ if (fs.existsSync(bundledConfig)) {
47
+ return bundledConfig;
48
+ }
49
+
50
+ return null;
51
+ }
52
+
34
53
  /**
35
54
  * Run SwarmHack with arguments
36
55
  * @param {string[]} args - Command line arguments
37
56
  * @param {object} options - Spawn options
57
+ * @param {boolean} options.useConfig - Whether to use bundled config (default: true)
38
58
  * @returns {Promise<{code: number, stdout: string, stderr: string}>}
39
59
  */
40
60
  function run(args = [], options = {}) {
@@ -43,7 +63,16 @@ function run(args = [], options = {}) {
43
63
  const stdout = [];
44
64
  const stderr = [];
45
65
 
46
- const child = spawn(binaryPath, args, {
66
+ // Add config flag if not already specified and useConfig is true (default)
67
+ let finalArgs = args;
68
+ if (options.useConfig !== false && !args.includes('--config') && !args.includes('-c')) {
69
+ const configPath = getConfigPath();
70
+ if (configPath) {
71
+ finalArgs = ['--config', configPath, ...args];
72
+ }
73
+ }
74
+
75
+ const child = spawn(binaryPath, finalArgs, {
47
76
  ...options,
48
77
  env: { ...process.env, ...options.env },
49
78
  });
@@ -134,4 +163,5 @@ module.exports = {
134
163
  version,
135
164
  doctor,
136
165
  getBinaryPath,
166
+ getConfigPath,
137
167
  };
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarmhack-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "SwarmHack - Neural swarm-based penetration testing framework",
5
5
  "author": "Prancer <support@prancer.io>",
6
6
  "license": "MIT",
@@ -25,6 +25,8 @@
25
25
  "files": [
26
26
  "bin/",
27
27
  "scripts/",
28
+ "native/",
29
+ "config/",
28
30
  "index.js",
29
31
  "README.md"
30
32
  ],
@@ -78,6 +78,23 @@ async function main() {
78
78
  const platformKey = getPlatformKey();
79
79
  const remoteBinary = PLATFORM_MAP[platformKey];
80
80
 
81
+ const nativeDir = path.join(__dirname, '..', 'native', platformKey);
82
+ const binaryPath = path.join(nativeDir, getBinaryName());
83
+
84
+ // Skip if already exists (bundled in package)
85
+ if (fs.existsSync(binaryPath)) {
86
+ // Make sure it's executable
87
+ if (os.platform() !== 'win32') {
88
+ try {
89
+ fs.chmodSync(binaryPath, 0o755);
90
+ } catch (e) {
91
+ // Ignore permission errors
92
+ }
93
+ }
94
+ console.log(`✓ SwarmHack binary ready: ${binaryPath}`);
95
+ return;
96
+ }
97
+
81
98
  if (!remoteBinary) {
82
99
  console.log(`
83
100
  ╔════════════════════════════════════════════════════════════╗
@@ -98,15 +115,6 @@ async function main() {
98
115
  return;
99
116
  }
100
117
 
101
- const nativeDir = path.join(__dirname, '..', 'native', platformKey);
102
- const binaryPath = path.join(nativeDir, getBinaryName());
103
-
104
- // Skip if already exists
105
- if (fs.existsSync(binaryPath)) {
106
- console.log(`SwarmHack binary already exists: ${binaryPath}`);
107
- return;
108
- }
109
-
110
118
  // Create directory
111
119
  fs.mkdirSync(nativeDir, { recursive: true });
112
120