wize-dev-kit 0.5.0 → 0.7.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 (36) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/package.json +1 -1
  3. package/src/security-overlay/_shared/allowlist.js +154 -0
  4. package/src/security-overlay/_shared/backlog.js +180 -0
  5. package/src/security-overlay/_shared/cli-runner.js +87 -0
  6. package/src/security-overlay/_shared/cvss.js +108 -0
  7. package/src/security-overlay/_shared/detect.js +125 -0
  8. package/src/security-overlay/_shared/install-script.js +205 -0
  9. package/src/security-overlay/_shared/invoke-phase.js +86 -0
  10. package/src/security-overlay/_shared/owasp.js +56 -0
  11. package/src/security-overlay/_shared/partial.js +225 -0
  12. package/src/security-overlay/_shared/preflight.js +175 -0
  13. package/src/security-overlay/_shared/scope-gate.js +172 -0
  14. package/src/security-overlay/_shared/scope-parser.js +120 -0
  15. package/src/security-overlay/agents/red-teamer/agent.yaml +51 -0
  16. package/src/security-overlay/agents/red-teamer/persona.md +43 -0
  17. package/src/security-overlay/data/common.txt +115 -0
  18. package/src/security-overlay/data/owasp-top10.json +15 -0
  19. package/src/security-overlay/data/tool-allowlist.json +31 -0
  20. package/src/security-overlay/skills/wize-sec-enumerate/scripts/run-enumerate.js +180 -0
  21. package/src/security-overlay/skills/wize-sec-enumerate/skill.md +32 -0
  22. package/src/security-overlay/skills/wize-sec-exploit/data/common.txt +117 -0
  23. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-ffuf.js +147 -0
  24. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-nikto.js +145 -0
  25. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-nuclei.js +176 -0
  26. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-sqlmap.js +139 -0
  27. package/src/security-overlay/skills/wize-sec-pentest/scripts/run-pipeline.js +167 -0
  28. package/src/security-overlay/skills/wize-sec-pentest/skill.md +52 -0
  29. package/src/security-overlay/skills/wize-sec-recon/scripts/run-gitleaks.js +139 -0
  30. package/src/security-overlay/skills/wize-sec-recon/scripts/run-osv.js +227 -0
  31. package/src/security-overlay/skills/wize-sec-recon/scripts/run-recon.js +162 -0
  32. package/src/security-overlay/skills/wize-sec-recon/skill.md +35 -0
  33. package/src/security-overlay/skills/wize-sec-report/scripts/render-report.js +1033 -0
  34. package/tools/installer/onboarding.js +1 -0
  35. package/tools/installer/render-shared.js +5 -1
  36. package/tools/installer/wize-cli.js +8 -1
@@ -0,0 +1,162 @@
1
+ 'use strict';
2
+
3
+ // run-recon.js — the nmap portion of the wize-sec-recon skill.
4
+ // SAST (gitleaks, osv/grype) is implemented in E05 and lives in
5
+ // scripts/run-sast.js (sibling). The orchestrator (wize-sec-pentest) and
6
+ // any caller can invoke either script directly; this file only handles
7
+ // recon.
8
+
9
+ const path = require('node:path');
10
+ const { execFileSync } = require('node:child_process');
11
+
12
+ const { assertTargetInScope, ScopeError } = require('../../../_shared/scope-gate.js');
13
+ const { filterArgs } = require('../../../_shared/allowlist.js');
14
+ const { writePartial } = require('../../../_shared/partial.js');
15
+
16
+ // Default argument list for nmap. filterArgs() will drop anything not in
17
+ // the tool-allowlist, so this list is intentionally explicit and minimal.
18
+ function defaultArgs(active) {
19
+ const args = ['-Pn', '-T4'];
20
+ if (active) args.push('-sV');
21
+ else args.push('-sn'); // passive: ping scan only — no port scan, no service detection.
22
+ return args;
23
+ }
24
+
25
+ // Parse a greppable nmap stdout into a markdown list. We only care about
26
+ // lines that look like `PORT/PROTO SERVICE VERSION`. Ports whose service
27
+ // nmap could not fingerprint (`?`, unknown, tcpwrapped, or empty version)
28
+ // are flagged for manual investigation — an unidentified open port is a
29
+ // medium-priority unknown, not just inventory.
30
+ function parseNmapGreppable(stdout) {
31
+ const lines = String(stdout || '').split('\n');
32
+ const out = [];
33
+ for (const line of lines) {
34
+ const m = line.match(/^(\d+\/[a-z]+)\s+(\S+)\s+(.*)$/);
35
+ if (!m) continue;
36
+ const port = m[1];
37
+ const service = m[2];
38
+ const version = m[3].trim();
39
+ const unidentified = /\?$/.test(service) || /^(unknown|tcpwrapped)$/i.test(service) || version === '';
40
+ if (unidentified) {
41
+ out.push(`- **${port}** \`${service}\` — ⚠️ serviço não identificado. **Investigar:** \`lsof -i :${port.split('/')[0]}\` · \`docker ps\` · \`ss -tulpn | grep ${port.split('/')[0]}\``);
42
+ } else {
43
+ out.push(`- **${port}** \`${service}\` — ${version}`);
44
+ }
45
+ }
46
+ return out.join('\n');
47
+ }
48
+
49
+ // runRecon({ securityDir, scope, target, active, execFn?, detectFn? }) ->
50
+ // { ok, partialStatus, mode }
51
+ // dependencies are injectable for tests.
52
+ async function runRecon(opts = {}) {
53
+ const sec = opts.securityDir;
54
+ const scope = opts.scope;
55
+ const target = opts.target;
56
+ const active = opts.active === true;
57
+
58
+ const execFn = opts.execFn || ((bin, args, opt) => {
59
+ return execFileSync(bin, args, { encoding: 'utf8', timeout: 60_000 });
60
+ });
61
+ const detectFn = opts.detectFn || require('../../../_shared/detect.js').detectTools;
62
+
63
+ // Gate — propagates ScopeError if scope is invalid.
64
+ const tools = detectFn(['nmap'], { cacheDir: sec });
65
+ const nmapTool = tools.nmap || { present: false };
66
+
67
+ // 1. nmap missing -> degraded partial, exit 0.
68
+ if (!nmapTool.present) {
69
+ writePartial({
70
+ securityDir: sec,
71
+ phase: 'recon',
72
+ mode: active ? 'active' : 'passive',
73
+ scope,
74
+ status: 'incomplete',
75
+ tools,
76
+ sections: {
77
+ degraded_checks: 'nmap ausente — instale nmap e re-rode a fase para resultados completos.'
78
+ }
79
+ });
80
+ return { ok: true, partialStatus: 'incomplete', mode: active ? 'active' : 'passive' };
81
+ }
82
+
83
+ // 2. target out of scope -> degraded partial, ok=false (gate refused).
84
+ const inScope = assertTargetInScope(scope, { host: target }, { refusalsDir: sec });
85
+ if (!inScope) {
86
+ writePartial({
87
+ securityDir: sec,
88
+ phase: 'recon',
89
+ mode: active ? 'active' : 'passive',
90
+ scope,
91
+ status: 'incomplete',
92
+ tools,
93
+ sections: {
94
+ degraded_checks: `target ${target} recusado pelo gate (host not in allowlist) — ver .wize/security/.refusals.log`
95
+ }
96
+ });
97
+ return { ok: false, partialStatus: 'incomplete', mode: active ? 'active' : 'passive' };
98
+ }
99
+
100
+ // 3. happy path: filterArgs + execFile.
101
+ const args = filterArgs('nmap', [...defaultArgs(active), target]);
102
+ const out = execFn('nmap', args, { timeout: 60_000 });
103
+ const portsText = parseNmapGreppable(out && out.stdout ? out.stdout : out);
104
+ const body = portsText || '_(nmap returned no parseable ports)_';
105
+
106
+ writePartial({
107
+ securityDir: sec,
108
+ phase: 'recon',
109
+ mode: active ? 'active' : 'passive',
110
+ scope,
111
+ status: 'complete',
112
+ tools,
113
+ sections: { open_ports: body }
114
+ });
115
+ return { ok: true, partialStatus: 'complete', mode: active ? 'active' : 'passive' };
116
+ }
117
+
118
+ // --- CLI entrypoint ------------------------------------------------------
119
+
120
+ function parseArgv(argv) {
121
+ const out = { active: false, securityDir: null, scopePath: null, target: null };
122
+ for (let i = 0; i < argv.length; i++) {
123
+ const a = argv[i];
124
+ if (a === '--active') out.active = true;
125
+ else if (a === '--target' && argv[i + 1]) { out.target = argv[i + 1]; i++; }
126
+ else if (a.startsWith('--target=')) out.target = a.slice('--target='.length);
127
+ else if (a === '--scope' && argv[i + 1]) { out.scopePath = argv[i + 1]; i++; }
128
+ else if (a.startsWith('--scope=')) out.scopePath = a.slice('--scope='.length);
129
+ else if (a === '--securityDir' && argv[i + 1]) { out.securityDir = argv[i + 1]; i++; }
130
+ else if (a.startsWith('--securityDir=')) out.securityDir = a.slice('--securityDir='.length);
131
+ }
132
+ if (!out.securityDir) out.securityDir = path.join(process.cwd(), '.wize', 'security');
133
+ if (!out.scopePath) out.scopePath = path.join(process.cwd(), '.wize', 'security', 'scope.md');
134
+ if (!out.target) {
135
+ // Default to scope.md dast_target.url host if available.
136
+ out.target = 'localhost';
137
+ }
138
+ return out;
139
+ }
140
+
141
+ async function main() {
142
+ const args = parseArgv(process.argv.slice(2));
143
+ const { loadScope } = require('../../../_shared/scope-gate.js');
144
+ const scope = loadScope(args.scopePath);
145
+ const r = await runRecon({
146
+ securityDir: args.securityDir,
147
+ scope,
148
+ target: args.target,
149
+ active: args.active
150
+ });
151
+ console.log(`recon: partial_status=${r.partialStatus} mode=${r.mode}`);
152
+ process.exit(r.ok ? 0 : 1);
153
+ }
154
+
155
+ if (require.main === module) {
156
+ main().catch(err => {
157
+ console.error('✖ wize-sec-recon:', err && err.message ? err.message : err);
158
+ process.exit(2);
159
+ });
160
+ }
161
+
162
+ module.exports = { runRecon, defaultArgs, parseNmapGreppable };
@@ -0,0 +1,35 @@
1
+ ---
2
+ code: wize-sec-recon
3
+ name: wize-sec-recon
4
+ overlay: security
5
+ module: security-overlay
6
+ owner: red-teamer
7
+ status: ready
8
+ ---
9
+
10
+ # wize-sec-recon — Recon (nmap)
11
+
12
+ Runs nmap against the targets in the `scope.md` allowlist and writes `recon.md`. **Default passive** (ping scan only); `--active` enables `-sV` service detection.
13
+
14
+ ## Usage
15
+
16
+ ```bash
17
+ /wize-sec-recon
18
+ /wize-sec-recon --active
19
+ /wize-sec-recon --target=staging.example.internal
20
+ ```
21
+
22
+ ## Behavior
23
+
24
+ - Loads `.wize/security/scope.md` first; aborts loudly on invalid scope (HASH_MISMATCH / MISSING_FIELDS).
25
+ - Detects nmap via `command -v`. If absent, writes a `partial_status: incomplete` recon.md with a `degraded_checks` section and exits 0 — the pipeline continues.
26
+ - Calls `assertTargetInScope` for the target. Out-of-scope targets produce an `incomplete` partial and a refusal entry in `.refusals.log`; nmap is **not** invoked.
27
+ - Active vs passive flag set is recorded in the partial's `mode:` frontmatter.
28
+ - The SAST portion of recon (gitleaks, osv/grype) is implemented in a sibling script `scripts/run-sast.js` and is invoked separately or by the orchestrator — see E05.
29
+
30
+ ## Output
31
+
32
+ - `.wize/security/recon.md` — partial with `## open_ports` (or `## degraded_checks` on missing tool / out-of-scope target).
33
+ - `.wize/security/.refusals.log` — appended on out-of-scope targets.
34
+
35
+ Exits 0 on success or graceful degradation; 1 when the gate refused the target; 2 on scope error.