wize-dev-kit 0.14.0 → 0.16.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 (226) hide show
  1. package/ARCH.md +24 -77
  2. package/CHANGELOG.md +24 -0
  3. package/DECISIONS.md +1 -27
  4. package/README.md +7 -2
  5. package/ROSTER.md +3 -11
  6. package/adapters/README.md +7 -7
  7. package/adapters/antigravity/README.md +5 -5
  8. package/adapters/claude-code/README.md +1 -1
  9. package/adapters/codex/README.md +5 -5
  10. package/adapters/codex/adapter.yaml +1 -1
  11. package/adapters/codex/render.js +1 -1
  12. package/adapters/continue/README.md +5 -5
  13. package/adapters/cursor/README.md +2 -2
  14. package/adapters/generic/README.md +1 -1
  15. package/adapters/kimi-code/README.md +5 -5
  16. package/adapters/kimi-code/render.js +2 -2
  17. package/adapters/opencode/README.md +3 -3
  18. package/adapters/opencode/render.js +1 -27
  19. package/adapters/windsurf/README.md +3 -3
  20. package/package.json +1 -1
  21. package/schemas/agent.schema.json +2 -2
  22. package/schemas/workflow.schema.json +1 -1
  23. package/src/app-overlay/wize-app-release-channels/workflow.md +0 -2
  24. package/src/app-overlay/wize-app-scaffold/workflow.md +0 -2
  25. package/src/app-overlay/wize-app-store-listing/workflow.md +0 -2
  26. package/src/builder-skills/wize-create-agent/workflow.md +0 -2
  27. package/src/builder-skills/wize-create-skill/workflow.md +0 -2
  28. package/src/builder-skills/wize-create-workflow/workflow.md +0 -2
  29. package/src/core-skills/module.yaml +3 -0
  30. package/src/core-skills/wize-advanced-elicitation/skill.md +0 -2
  31. package/src/core-skills/wize-brainstorming/skill.md +0 -2
  32. package/src/core-skills/wize-eli5/skill.md +72 -0
  33. package/src/core-skills/wize-review-adversarial/skill.md +0 -3
  34. package/src/core-skills/wize-shard-doc/skill.md +0 -2
  35. package/src/method-skills/1-analysis/wize-agent-analyst/agent.yaml +0 -3
  36. package/src/method-skills/1-analysis/wize-document-project/workflow.md +20 -213
  37. package/src/method-skills/1-analysis/wize-prfaq/workflow.md +11 -152
  38. package/src/method-skills/1-analysis/wize-product-brief/workflow.md +19 -92
  39. package/src/method-skills/1-analysis/wize-research/workflow.md +12 -39
  40. package/src/method-skills/1-analysis/wize-trigger-map/workflow.md +16 -82
  41. package/src/method-skills/2-plan-workflows/wize-create-prd/workflow.md +23 -135
  42. package/src/method-skills/2-plan-workflows/wize-ux-design/workflow.md +28 -134
  43. package/src/method-skills/2-plan-workflows/wize-ux-scenarios/workflow.md +15 -93
  44. package/src/method-skills/2-plan-workflows/wize-validate-prd/workflow.md +12 -108
  45. package/src/method-skills/3-solutioning/wize-check-implementation-readiness/workflow.md +11 -103
  46. package/src/method-skills/3-solutioning/wize-create-architecture/workflow.md +48 -55
  47. package/src/method-skills/3-solutioning/wize-create-epics-and-stories/workflow.md +15 -154
  48. package/src/method-skills/3-solutioning/wize-design-system/workflow.md +22 -184
  49. package/src/method-skills/3-solutioning/wize-nfr-principles/workflow.md +17 -145
  50. package/src/method-skills/3-solutioning/wize-tech-vision/workflow.md +22 -130
  51. package/src/method-skills/4-implementation/wize-agent-dev/persona.md +0 -12
  52. package/src/method-skills/4-implementation/wize-code-review/workflow.md +12 -54
  53. package/src/method-skills/4-implementation/wize-create-story/workflow.md +10 -154
  54. package/src/method-skills/4-implementation/wize-dev-story/workflow.md +17 -185
  55. package/src/method-skills/4-implementation/wize-quick-dev/workflow.md +18 -136
  56. package/src/method-skills/4-implementation/wize-retrospective/workflow.md +10 -114
  57. package/src/method-skills/4-implementation/wize-sprint-planning/workflow.md +11 -78
  58. package/src/method-skills/4-implementation/wize-sprint-status/workflow.md +11 -45
  59. package/src/method-skills/module.yaml +0 -28
  60. package/src/orchestrator-skills/module.yaml +1 -7
  61. package/src/orchestrator-skills/wize-help/skill.md +67 -227
  62. package/src/orchestrator-skills/wize-onboarding/workflow.md +14 -78
  63. package/src/orchestrator-skills/wize-orchestrator/agent.yaml +0 -2
  64. package/src/orchestrator-skills/wize-orchestrator/persona.md +3 -44
  65. package/src/orchestrator-skills/wize-party-mode/workflow.md +0 -2
  66. package/src/tea-skills/wize-tea-design/workflow.md +13 -107
  67. package/src/tea-skills/wize-tea-gate/workflow.md +25 -118
  68. package/src/tea-skills/wize-tea-nfr/workflow.md +14 -107
  69. package/src/tea-skills/wize-tea-review/workflow.md +13 -123
  70. package/src/tea-skills/wize-tea-risk/workflow.md +10 -113
  71. package/src/tea-skills/wize-tea-trace/workflow.md +12 -86
  72. package/src/web-overlay/wize-web-deploy/workflow.md +0 -2
  73. package/src/web-overlay/wize-web-scaffold/workflow.md +0 -2
  74. package/src/web-overlay/wize-web-seo-audit/workflow.md +0 -2
  75. package/tools/check-eli5-all-adapters.js +50 -0
  76. package/tools/installer/onboarding.js +20 -14
  77. package/tools/installer/render-shared.js +14 -158
  78. package/tools/installer/validators/run-all.js +2 -3
  79. package/tools/installer/wize-cli.js +70 -499
  80. package/AGENTS.md +0 -37
  81. package/README.es.md +0 -294
  82. package/README.pt-BR.md +0 -292
  83. package/docs/harnesses/antigravity.md +0 -20
  84. package/docs/harnesses/antigravity.pt-BR.md +0 -20
  85. package/docs/harnesses/claude-code.md +0 -23
  86. package/docs/harnesses/claude-code.pt-BR.md +0 -23
  87. package/docs/harnesses/codex.md +0 -21
  88. package/docs/harnesses/codex.pt-BR.md +0 -21
  89. package/docs/harnesses/continue.md +0 -21
  90. package/docs/harnesses/continue.pt-BR.md +0 -21
  91. package/docs/harnesses/cursor.md +0 -22
  92. package/docs/harnesses/cursor.pt-BR.md +0 -22
  93. package/docs/harnesses/generic.md +0 -20
  94. package/docs/harnesses/generic.pt-BR.md +0 -20
  95. package/docs/harnesses/kimi-code.md +0 -19
  96. package/docs/harnesses/kimi-code.pt-BR.md +0 -19
  97. package/docs/harnesses/opencode.md +0 -31
  98. package/docs/harnesses/opencode.pt-BR.md +0 -31
  99. package/docs/harnesses/windsurf.md +0 -22
  100. package/docs/harnesses/windsurf.pt-BR.md +0 -22
  101. package/src/core-skills/wize-customize/skill.md +0 -116
  102. package/src/core-skills/wize-editorial-review-prose/skill.md +0 -94
  103. package/src/core-skills/wize-editorial-review-structure/skill.md +0 -99
  104. package/src/core-skills/wize-grill/skill.md +0 -77
  105. package/src/core-skills/wize-index-docs/skill.md +0 -119
  106. package/src/core-skills/wize-pre-pr-check/skill.md +0 -134
  107. package/src/core-skills/wize-review-edge-case-hunter/skill.md +0 -115
  108. package/src/core-skills/wize-spec/assets/headless-schemas.md +0 -39
  109. package/src/core-skills/wize-spec/assets/spec-template.md +0 -40
  110. package/src/core-skills/wize-spec/customize.toml +0 -20
  111. package/src/core-skills/wize-spec/skill.md +0 -112
  112. package/src/method-skills/1-analysis/wize-document-project/documentation-requirements.csv +0 -12
  113. package/src/method-skills/1-analysis/wize-document-project/templates/api-contracts-template.md +0 -38
  114. package/src/method-skills/1-analysis/wize-document-project/templates/architecture-template.md +0 -54
  115. package/src/method-skills/1-analysis/wize-document-project/templates/component-inventory-template.md +0 -40
  116. package/src/method-skills/1-analysis/wize-document-project/templates/contribution-guide-template.md +0 -34
  117. package/src/method-skills/1-analysis/wize-document-project/templates/data-models-template.md +0 -36
  118. package/src/method-skills/1-analysis/wize-document-project/templates/deep-dive-template.md +0 -312
  119. package/src/method-skills/1-analysis/wize-document-project/templates/deployment-guide-template.md +0 -42
  120. package/src/method-skills/1-analysis/wize-document-project/templates/development-guide-template.md +0 -61
  121. package/src/method-skills/1-analysis/wize-document-project/templates/index-template.md +0 -185
  122. package/src/method-skills/1-analysis/wize-document-project/templates/project-overview-template.md +0 -110
  123. package/src/method-skills/1-analysis/wize-document-project/templates/project-scan-report-schema.json +0 -159
  124. package/src/method-skills/1-analysis/wize-document-project/templates/source-tree-template.md +0 -142
  125. package/src/method-skills/1-analysis/wize-domain-research/customize.toml +0 -14
  126. package/src/method-skills/1-analysis/wize-domain-research/domain-steps/step-01-init.md +0 -49
  127. package/src/method-skills/1-analysis/wize-domain-research/domain-steps/step-02-domain-analysis.md +0 -39
  128. package/src/method-skills/1-analysis/wize-domain-research/domain-steps/step-03-competitive-landscape.md +0 -39
  129. package/src/method-skills/1-analysis/wize-domain-research/domain-steps/step-04-regulatory-focus.md +0 -39
  130. package/src/method-skills/1-analysis/wize-domain-research/domain-steps/step-05-technical-trends.md +0 -39
  131. package/src/method-skills/1-analysis/wize-domain-research/domain-steps/step-06-research-synthesis.md +0 -43
  132. package/src/method-skills/1-analysis/wize-domain-research/research.template.md +0 -31
  133. package/src/method-skills/1-analysis/wize-domain-research/workflow.md +0 -58
  134. package/src/method-skills/1-analysis/wize-market-research/customize.toml +0 -14
  135. package/src/method-skills/1-analysis/wize-market-research/research.template.md +0 -31
  136. package/src/method-skills/1-analysis/wize-market-research/steps/step-01-init.md +0 -57
  137. package/src/method-skills/1-analysis/wize-market-research/steps/step-02-customer-behavior.md +0 -39
  138. package/src/method-skills/1-analysis/wize-market-research/steps/step-03-customer-pain-points.md +0 -37
  139. package/src/method-skills/1-analysis/wize-market-research/steps/step-04-customer-decisions.md +0 -39
  140. package/src/method-skills/1-analysis/wize-market-research/steps/step-05-competitive-analysis.md +0 -37
  141. package/src/method-skills/1-analysis/wize-market-research/steps/step-06-research-completion.md +0 -47
  142. package/src/method-skills/1-analysis/wize-market-research/workflow.md +0 -66
  143. package/src/method-skills/1-analysis/wize-refresh-knowledge/workflow.md +0 -129
  144. package/src/method-skills/1-analysis/wize-technical-research/customize.toml +0 -14
  145. package/src/method-skills/1-analysis/wize-technical-research/research.template.md +0 -31
  146. package/src/method-skills/1-analysis/wize-technical-research/technical-steps/step-01-init.md +0 -49
  147. package/src/method-skills/1-analysis/wize-technical-research/technical-steps/step-02-technical-overview.md +0 -45
  148. package/src/method-skills/1-analysis/wize-technical-research/technical-steps/step-03-integration-patterns.md +0 -39
  149. package/src/method-skills/1-analysis/wize-technical-research/technical-steps/step-04-architectural-patterns.md +0 -39
  150. package/src/method-skills/1-analysis/wize-technical-research/technical-steps/step-05-implementation-research.md +0 -42
  151. package/src/method-skills/1-analysis/wize-technical-research/technical-steps/step-06-research-synthesis.md +0 -46
  152. package/src/method-skills/1-analysis/wize-technical-research/workflow.md +0 -60
  153. package/src/method-skills/2-plan-workflows/wize-edit-prd/workflow.md +0 -110
  154. package/src/method-skills/3-solutioning/wize-create-architecture/architecture-decision-template.md +0 -41
  155. package/src/method-skills/3-solutioning/wize-create-architecture/customize.toml +0 -20
  156. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-01-init.md +0 -95
  157. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-01b-continue.md +0 -32
  158. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-02-context.md +0 -126
  159. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-03-starter.md +0 -110
  160. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-04-decisions.md +0 -129
  161. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-05-patterns.md +0 -109
  162. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-06-structure.md +0 -97
  163. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-07-validation.md +0 -124
  164. package/src/method-skills/3-solutioning/wize-create-architecture/steps/step-08-complete.md +0 -59
  165. package/src/method-skills/3-solutioning/wize-project-context/workflow.md +0 -120
  166. package/src/method-skills/4-implementation/wize-changelog/workflow.md +0 -184
  167. package/src/method-skills/4-implementation/wize-checkpoint-preview/workflow.md +0 -117
  168. package/src/method-skills/4-implementation/wize-code-review/customize.toml +0 -21
  169. package/src/method-skills/4-implementation/wize-code-review/steps/step-01-gather-context.md +0 -64
  170. package/src/method-skills/4-implementation/wize-code-review/steps/step-02-review.md +0 -40
  171. package/src/method-skills/4-implementation/wize-code-review/steps/step-03-triage.md +0 -43
  172. package/src/method-skills/4-implementation/wize-code-review/steps/step-04-present.md +0 -100
  173. package/src/method-skills/4-implementation/wize-correct-course/workflow.md +0 -93
  174. package/src/method-skills/4-implementation/wize-investigate/workflow.md +0 -123
  175. package/src/method-skills/4-implementation/wize-release/workflow.md +0 -162
  176. package/src/orchestrator-skills/wize/skill.md +0 -164
  177. package/src/orchestrator-skills/wize-check/skill.md +0 -98
  178. package/src/security-overlay/_shared/allowlist.js +0 -154
  179. package/src/security-overlay/_shared/backlog.js +0 -169
  180. package/src/security-overlay/_shared/cli-runner.js +0 -87
  181. package/src/security-overlay/_shared/cvss.js +0 -108
  182. package/src/security-overlay/_shared/detect.js +0 -125
  183. package/src/security-overlay/_shared/install-script.js +0 -205
  184. package/src/security-overlay/_shared/invoke-phase.js +0 -86
  185. package/src/security-overlay/_shared/owasp.js +0 -56
  186. package/src/security-overlay/_shared/partial.js +0 -225
  187. package/src/security-overlay/_shared/preflight.js +0 -175
  188. package/src/security-overlay/_shared/scope-gate.js +0 -172
  189. package/src/security-overlay/_shared/scope-parser.js +0 -147
  190. package/src/security-overlay/agents/red-teamer/agent.yaml +0 -54
  191. package/src/security-overlay/agents/red-teamer/persona.md +0 -49
  192. package/src/security-overlay/data/common.txt +0 -115
  193. package/src/security-overlay/data/owasp-top10.json +0 -15
  194. package/src/security-overlay/data/tool-allowlist.json +0 -31
  195. package/src/security-overlay/skills/wize-sec-enumerate/scripts/run-enumerate.js +0 -180
  196. package/src/security-overlay/skills/wize-sec-enumerate/skill.md +0 -34
  197. package/src/security-overlay/skills/wize-sec-exploit/data/common.txt +0 -117
  198. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-ffuf.js +0 -147
  199. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-nikto.js +0 -145
  200. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-nuclei.js +0 -176
  201. package/src/security-overlay/skills/wize-sec-exploit/scripts/run-sqlmap.js +0 -139
  202. package/src/security-overlay/skills/wize-sec-pentest/scripts/run-pipeline.js +0 -184
  203. package/src/security-overlay/skills/wize-sec-pentest/skill.md +0 -54
  204. package/src/security-overlay/skills/wize-sec-recon/scripts/run-gitleaks.js +0 -139
  205. package/src/security-overlay/skills/wize-sec-recon/scripts/run-osv.js +0 -227
  206. package/src/security-overlay/skills/wize-sec-recon/scripts/run-recon.js +0 -162
  207. package/src/security-overlay/skills/wize-sec-recon/skill.md +0 -37
  208. package/src/security-overlay/skills/wize-sec-report/scripts/render-report.js +0 -1033
  209. package/src/security-overlay/skills/wize-sec-scope/scripts/generate-scope.js +0 -106
  210. package/src/security-overlay/skills/wize-sec-scope/skill.md +0 -52
  211. package/src/tea-skills/wize-qa-generate-e2e-tests/workflow.md +0 -121
  212. package/tools/installer/baseline.js +0 -128
  213. package/tools/installer/commands/agent.js +0 -197
  214. package/tools/installer/commands/doctor.js +0 -319
  215. package/tools/installer/commands/document-project.js +0 -93
  216. package/tools/installer/commands/sync.js +0 -45
  217. package/tools/installer/commands/update.js +0 -172
  218. package/tools/installer/document-project/batch-scanner.js +0 -93
  219. package/tools/installer/document-project/classify.js +0 -170
  220. package/tools/installer/document-project/modes/deep-dive.js +0 -196
  221. package/tools/installer/document-project/modes/full-rescan.js +0 -15
  222. package/tools/installer/document-project/modes/initial-scan.js +0 -100
  223. package/tools/installer/document-project/modes/quick.js +0 -211
  224. package/tools/installer/document-project/render-index.js +0 -101
  225. package/tools/installer/document-project/state.js +0 -110
  226. package/tools/installer/version-check.js +0 -117
@@ -1,117 +0,0 @@
1
- admin
2
- api
3
- app
4
- auth
5
- backup
6
- blog
7
- cart
8
- catalog
9
- cms
10
- config
11
- console
12
- contact
13
- dashboard
14
- data
15
- db
16
- debug
17
- default
18
- demo
19
- dev
20
- docs
21
- download
22
- editor
23
- email
24
- error
25
- example
26
- export
27
- feed
28
- file
29
- files
30
- forum
31
- gallery
32
- help
33
- home
34
- images
35
- img
36
- import
37
- index
38
- info
39
- internal
40
- js
41
- json
42
- lib
43
- login
44
- logout
45
- mail
46
- manage
47
- member
48
- message
49
- metrics
50
- mobile
51
- new
52
- news
53
- node
54
- notes
55
- old
56
- order
57
- page
58
- pages
59
- panel
60
- password
61
- pdf
62
- photo
63
- php
64
- ping
65
- plugins
66
- portal
67
- post
68
- posts
69
- private
70
- profile
71
- public
72
- readme
73
- register
74
- report
75
- reports
76
- reset
77
- robots.txt
78
- rss
79
- search
80
- secure
81
- server
82
- service
83
- settings
84
- setup
85
- shop
86
- sitemap
87
- sitemap.xml
88
- staff
89
- static
90
- stats
91
- status
92
- store
93
- style.css
94
- styles
95
- subscribe
96
- support
97
- swagger
98
- system
99
- temp
100
- test
101
- tests
102
- tmp
103
- tools
104
- tracker
105
- upload
106
- uploads
107
- user
108
- users
109
- vendor
110
- version
111
- web
112
- webhook
113
- webmaster
114
- widget
115
- wiki
116
- xml
117
- xmlrpc
@@ -1,147 +0,0 @@
1
- 'use strict';
2
-
3
- // run-ffuf.js — DAST ffuf (path/param fuzzing). GATED by --active.
4
- // Rate-limit (-rate 5) keeps the scan gentle even when active. The
5
- // wordlist is a small embedded file in data/common.txt (~100 entries);
6
- // users with SecLists should pass their own wordlist via extraArgs
7
- // (the data file is the conservative default).
8
-
9
- const path = require('node:path');
10
- const fs = require('node:fs');
11
- const { execFileSync } = require('node:child_process');
12
-
13
- const { assertTargetInScope } = require('../../../_shared/scope-gate.js');
14
- const { filterArgs } = require('../../../_shared/allowlist.js');
15
- const { writePartial, loadPartial } = require('../../../_shared/partial.js');
16
- const { tagOwasp } = require('../../../_shared/owasp.js');
17
-
18
- const TIMEOUT_MS = 10 * 60 * 1000;
19
- const DEFAULT_WORDLIST = path.join(__dirname, '..', '..', '..', 'data', 'common.txt');
20
-
21
- function filterFfufArgs(targetUrl, wordlistPath) {
22
- return [
23
- '-u', targetUrl.replace(/\/+$/, '') + '/FUZZ',
24
- '-w', wordlistPath,
25
- '-mc', '200,201,202,301,302,401,403,500',
26
- '-t', '5',
27
- '-rate', '5',
28
- '-of', 'json',
29
- '-o', path.join(path.dirname(wordlistPath), '..', '..', '..', '.ffuf.json')
30
- ];
31
- }
32
-
33
- function parseFfufJson(text) {
34
- try {
35
- const obj = JSON.parse(text);
36
- return (obj && obj.results) ? obj.results : [];
37
- } catch (_) {
38
- return [];
39
- }
40
- }
41
-
42
- async function runFfuf(opts = {}) {
43
- const sec = opts.securityDir;
44
- const scope = opts.scope;
45
- const active = opts.active === true;
46
- const wordlist = opts.wordlist || DEFAULT_WORDLIST;
47
-
48
- const execFn = opts.execFn || ((bin, args) => {
49
- return execFileSync(bin, args, { encoding: 'utf8', timeout: TIMEOUT_MS });
50
- });
51
- const detectFn = opts.detectFn || require('../../../_shared/detect.js').detectTools;
52
-
53
- const tools = detectFn(['ffuf'], { cacheDir: sec });
54
- const present = !!(tools.ffuf && tools.ffuf.present);
55
-
56
- let targetUrl = null;
57
- for (const line of (scope.body || '').split('\n')) {
58
- const m = line.match(/^url:\s*(.+?)\s*$/);
59
- if (m && line.indexOf('url') === 0) { targetUrl = m[1]; break; }
60
- }
61
-
62
- function mergeDast(sections, status) {
63
- const existing = loadPartial({ securityDir: sec, phase: 'dast' });
64
- const merged = {};
65
- if (existing && existing.body) {
66
- const re = /## ([a-z_]+)\n\n([\s\S]*?)(?=\n## |$)/g;
67
- let m;
68
- while ((m = re.exec(existing.body)) !== null) {
69
- merged[m[1]] = m[2].trim();
70
- }
71
- }
72
- Object.assign(merged, sections);
73
- const finalStatus = merged.degraded_checks ? 'incomplete' : status;
74
- writePartial({
75
- securityDir: sec, phase: 'dast', mode: active ? 'active' : 'passive',
76
- scope, status: finalStatus, tools, sections: merged
77
- });
78
- }
79
-
80
- // 1. Not active -> degraded with [ffuf-passive].
81
- if (!active) {
82
- mergeDast({ degraded_checks: '- ffuf-passive: --active ausente — ffuf não é invocado sem opt-in explícito.' }, 'incomplete');
83
- return { ok: true, partialStatus: 'incomplete' };
84
- }
85
-
86
- if (!targetUrl) {
87
- mergeDast({ degraded_checks: '- ffuf: dast_target.url ausente' }, 'incomplete');
88
- return { ok: true, partialStatus: 'incomplete' };
89
- }
90
-
91
- const urlObj = new URL(targetUrl);
92
- const inScope = assertTargetInScope(scope, { host: urlObj.hostname, url: targetUrl }, { refusalsDir: sec });
93
- if (!inScope) {
94
- mergeDast({ degraded_checks: `- ffuf: target ${targetUrl} recusado pelo gate` }, 'incomplete');
95
- return { ok: false, partialStatus: 'incomplete' };
96
- }
97
-
98
- if (!present) {
99
- mergeDast({ degraded_checks: '- ffuf: ffuf ausente — instale ffuf e re-rode com --active.' }, 'incomplete');
100
- return { ok: true, partialStatus: 'incomplete' };
101
- }
102
-
103
- // Happy path.
104
- const reportPath = path.join(sec, '.ffuf.json');
105
- const args = filterArgs('ffuf', [
106
- '-u', targetUrl.replace(/\/+$/, '') + '/FUZZ',
107
- '-w', wordlist,
108
- '-mc', '200,201,202,301,302,401,403,500',
109
- '-t', '5',
110
- '-rate', '5',
111
- '-of', 'json',
112
- '-o', reportPath
113
- ]);
114
- try {
115
- execFn('ffuf', args, { timeout: TIMEOUT_MS });
116
- } catch (_) { /* ffuf may exit non-zero; the JSON report is still written */ }
117
-
118
- let findings = [];
119
- if (fs.existsSync(reportPath)) {
120
- try {
121
- findings = parseFfufJson(fs.readFileSync(reportPath, 'utf8'));
122
- } catch (_) { findings = []; }
123
- }
124
-
125
- const body = findings.length
126
- ? findings.map(f => {
127
- const owasp = tagOwasp({ rule: `status-${f.status || ''} path-${f.input && f.input.FUZZ || ''}` });
128
- return `- **${f.url}** status=${f.status} length=${f.length || 0} owasp=\`${owasp}\``;
129
- }).join('\n')
130
- : '_(nenhum finding do ffuf)_';
131
-
132
- mergeDast({ ffuf: body }, findings.length ? 'complete' : 'incomplete');
133
- return { ok: true, partialStatus: findings.length ? 'complete' : 'incomplete' };
134
- }
135
-
136
- module.exports = { runFfuf, filterFfufArgs, parseFfufJson };
137
-
138
- if (require.main === module) {
139
- require('../../../_shared/cli-runner.js').runFromArgv({
140
- fn: ({ securityDir, scopePath, active, target, wordlist } = {}) => {
141
- const { loadScope } = require('../../../_shared/scope-gate.js');
142
- const scope = loadScope(scopePath);
143
- return runFfuf({ securityDir, scope, active, target, wordlist });
144
- },
145
- argMap: { 'securityDir': 'securityDir', 'scope': 'scopePath', 'active': 'active', 'target': 'target', 'wordlist': 'wordlist' }
146
- });
147
- }
@@ -1,145 +0,0 @@
1
- 'use strict';
2
-
3
- // run-nikto.js — DAST nikto phase. Nikto runs in safe-checks mode
4
- // (-Tuning x6) which excludes brute force and DoS probes (NFR Security #6).
5
-
6
- const path = require('node:path');
7
- const fs = require('node:fs');
8
- const { execFileSync } = require('node:child_process');
9
-
10
- const { assertTargetInScope } = require('../../../_shared/scope-gate.js');
11
- const { filterArgs } = require('../../../_shared/allowlist.js');
12
- const { writePartial, loadPartial } = require('../../../_shared/partial.js');
13
- const { tagOwasp } = require('../../../_shared/owasp.js');
14
-
15
- // Build nikto argv (raw, before filterArgs).
16
- function filterNiktoArgs(host, outputPath) {
17
- return ['-h', host, '-ask', 'no', '-Tuning', 'x6', '-timeout', '10', '-o', outputPath];
18
- }
19
-
20
- // Parse nikto's text output. We accept a relaxed line shape — every line
21
- // that starts with '+' (or contains OSVDB-) is treated as a finding.
22
- function parseNiktoText(text) {
23
- const findings = [];
24
- for (const line of String(text || '').split('\n')) {
25
- const t = line.trim();
26
- if (!t || t.startsWith('- Nikto')) continue; // header
27
- if (!t.startsWith('+') && !/OSVDB-\d+/.test(t)) continue;
28
- // id: first OSVDB-#### match, else hash of first 8 chars.
29
- const osvdb = t.match(/OSVDB-(\d+)/);
30
- const id = osvdb ? `OSVDB-${osvdb[1]}` : `NIKTO-${Math.abs(hashStr(t)) % 1e6}`;
31
- const msg = t.replace(/^\+\s*/, '').replace(/^OSVDB-\d+:\s*/, '');
32
- // Severity inferred by keyword.
33
- let severity = 'info';
34
- if (/injection|sqli|xss|sql injection/i.test(t)) severity = 'high';
35
- else if (/default.{0,5}account|admin|exposed/i.test(t)) severity = 'medium';
36
- else if (/missing|cookie|httponly|header|csp/i.test(t)) severity = 'low';
37
- findings.push({ id, msg, severity });
38
- }
39
- return findings;
40
- }
41
-
42
- function hashStr(s) {
43
- let h = 0;
44
- for (let i = 0; i < s.length; i++) h = ((h << 5) - h + s.charCodeAt(i)) | 0;
45
- return h;
46
- }
47
-
48
- async function runNikto(opts = {}) {
49
- const sec = opts.securityDir;
50
- const scope = opts.scope;
51
- const active = opts.active === true;
52
-
53
- const execFn = opts.execFn || ((bin, args) => {
54
- return execFileSync(bin, args, { encoding: 'utf8', timeout: 10 * 60 * 1000 });
55
- });
56
- const detectFn = opts.detectFn || require('../../../_shared/detect.js').detectTools;
57
-
58
- const tools = detectFn(['nikto'], { cacheDir: sec });
59
- const present = !!(tools.nikto && tools.nikto.present);
60
-
61
- // Resolve target URL.
62
- let targetUrl = null;
63
- for (const line of (scope.body || '').split('\n')) {
64
- if (/^## dast_target/.test(line)) continue;
65
- const m = line.match(/^url:\s*(.+?)\s*$/);
66
- if (m && line.indexOf('url') === 0) { targetUrl = m[1]; break; }
67
- }
68
- if (!targetUrl) {
69
- mergeDast(sec, scope, active, tools, { degraded_checks: '- nikto: dast_target.url ausente' }, 'incomplete');
70
- return { ok: true, partialStatus: 'incomplete' };
71
- }
72
-
73
- const urlObj = new URL(targetUrl);
74
-
75
- const inScope = assertTargetInScope(scope, { host: urlObj.hostname, url: targetUrl }, { refusalsDir: sec });
76
- if (!inScope) {
77
- mergeDast(sec, scope, active, tools, { degraded_checks: `- nikto: target ${targetUrl} recusado pelo gate` }, 'incomplete');
78
- return { ok: false, partialStatus: 'incomplete' };
79
- }
80
-
81
- if (!present) {
82
- mergeDast(sec, scope, active, tools, { degraded_checks: '- nikto: nikto ausente — instale nikto e re-rode.' }, 'incomplete');
83
- return { ok: true, partialStatus: 'incomplete' };
84
- }
85
-
86
- const outPath = path.join(sec, '.nikto.txt');
87
- const rawArgs = filterNiktoArgs(urlObj.hostname, outPath);
88
- const args = filterArgs('nikto', rawArgs);
89
- const r = execFn('nikto', args, { timeout: 10 * 60 * 1000 });
90
- let text = r && r.stdout ? r.stdout : '';
91
- if (!text && fs.existsSync(outPath)) {
92
- text = fs.readFileSync(outPath, 'utf8');
93
- }
94
- const raw = parseNiktoText(text);
95
- const findings = raw.map(f => ({
96
- id: f.id,
97
- msg: f.msg,
98
- severity: f.severity,
99
- owasp: tagOwasp({ rule: f.id + ' ' + f.msg })
100
- }));
101
- const lines = findings.length
102
- ? findings.map(f => `- **${f.id}** severity=${f.severity} owasp=\`${f.owasp}\` — ${f.msg}`)
103
- : ['_(nenhum finding do nikto)_'];
104
-
105
- // Merge into dast.md: preserve sections from earlier tools (e.g. nuclei).
106
- mergeDast(sec, scope, active, tools, { nikto: lines.join('\n') }, findings.length ? 'complete' : 'incomplete');
107
- return { ok: true, partialStatus: findings.length ? 'complete' : 'incomplete' };
108
- }
109
-
110
- function mergeDast(sec, scope, active, tools, update, defaultStatus) {
111
- const existing = loadPartial({ securityDir: sec, phase: 'dast' });
112
- const sections = {};
113
- if (existing && existing.body) {
114
- const re = /## ([a-z_]+)\n\n([\s\S]*?)(?=\n## |$)/g;
115
- let m;
116
- while ((m = re.exec(existing.body)) !== null) {
117
- sections[m[1]] = m[2].trim();
118
- }
119
- }
120
- Object.assign(sections, update);
121
- // Status: incomplete if any degraded_checks section is present.
122
- const status = sections.degraded_checks ? 'incomplete' : (defaultStatus || 'complete');
123
- writePartial({
124
- securityDir: sec,
125
- phase: 'dast',
126
- mode: active ? 'active' : 'passive',
127
- scope,
128
- status,
129
- tools,
130
- sections
131
- });
132
- }
133
-
134
- module.exports = { runNikto, filterNiktoArgs, parseNiktoText };
135
-
136
- if (require.main === module) {
137
- require('../../../_shared/cli-runner.js').runFromArgv({
138
- fn: ({ securityDir, scopePath, active, target } = {}) => {
139
- const { loadScope } = require('../../../_shared/scope-gate.js');
140
- const scope = loadScope(scopePath);
141
- return runNikto({ securityDir, scope, active, target });
142
- },
143
- argMap: { 'securityDir': 'securityDir', 'scope': 'scopePath', 'active': 'active', 'target': 'target' }
144
- });
145
- }
@@ -1,176 +0,0 @@
1
- 'use strict';
2
-
3
- // run-nuclei.js — DAST nuclei phase. Default is passive (info disclosure,
4
- // misconfig, headers). Active mode is gated by --active (sqlmap/ffuf
5
- // come in separate stories).
6
-
7
- const path = require('node:path');
8
- const fs = require('node:fs');
9
- const { execFileSync } = require('node:child_process');
10
-
11
- const { assertTargetInScope } = require('../../../_shared/scope-gate.js');
12
- const { filterArgs } = require('../../../_shared/allowlist.js');
13
- const { writePartial } = require('../../../_shared/partial.js');
14
- const { tagOwasp } = require('../../../_shared/owasp.js');
15
-
16
- // Build the nuclei args list. Returns the raw argv (before filterArgs).
17
- // Kept as a separate function so tests can assert on the raw list.
18
- function filterNucleiArgs(targetUrl, active, outputPath) {
19
- // nuclei v3: there is no `-t passive` template path. We run the default
20
- // template set and filter by severity. Passive = lower-impact severities
21
- // + aggressive rate limit; active = full severity range. Output is JSONL
22
- // (-jsonl), disable update check (-duc), non-colored (-nc), silent.
23
- const args = [
24
- '-u', targetUrl,
25
- '-severity', active ? 'info,low,medium,high,critical' : 'info,low,medium',
26
- '-rl', '10',
27
- '-jsonl', '-o', outputPath,
28
- '-duc', '-nc', '-silent'
29
- ];
30
- return args;
31
- }
32
-
33
- // Parse line-delimited nuclei JSON output (one finding per line).
34
- function parseNucleiJson(text) {
35
- const out = [];
36
- for (const line of String(text || '').split('\n')) {
37
- const trimmed = line.trim();
38
- if (!trimmed) continue;
39
- try {
40
- const f = JSON.parse(trimmed);
41
- out.push(f);
42
- } catch (_) { /* skip malformed lines */ }
43
- }
44
- return out;
45
- }
46
-
47
- // Build a nuclei finding object (flat) with template_id, severity, owasp, etc.
48
- function normalizeFinding(raw) {
49
- const templateId = raw['template-id'] || raw.templateID || raw.template || '<unknown>';
50
- const info = raw.info || {};
51
- const severity = (info.severity || raw.severity || 'unknown').toString().toLowerCase();
52
- const name = info.name || raw.name || templateId;
53
- const matchedAt = raw['matched-at'] || raw.matched || raw.host || '<unknown>';
54
- // CVSS: nuclei sometimes nests it.
55
- let cvss = raw.cvss;
56
- if (typeof cvss !== 'number' && info && info.classification && info.classification.cvss_score) {
57
- cvss = Number(info.classification.cvss_score);
58
- }
59
- if (typeof cvss !== 'number') cvss = null;
60
- const owasp = tagOwasp({ rule: templateId, cve: raw['cve-id'] || raw.cve });
61
- return { template_id: templateId, name, severity, cvss, matched_at: matchedAt, owasp };
62
- }
63
-
64
- // runNuclei({securityDir, scope, active, execFn?, detectFn?}) -> {ok, partialStatus}
65
- async function runNuclei(opts = {}) {
66
- const sec = opts.securityDir;
67
- const scope = opts.scope;
68
- const active = opts.active === true;
69
-
70
- const execFn = opts.execFn || ((bin, args) => {
71
- return execFileSync(bin, args, { encoding: 'utf8', timeout: 10 * 60 * 1000 });
72
- });
73
- const detectFn = opts.detectFn || require('../../../_shared/detect.js').detectTools;
74
-
75
- const tools = detectFn(['nuclei'], { cacheDir: sec });
76
- const present = !!(tools.nuclei && tools.nuclei.present);
77
-
78
- // 1. Target resolution — prefer scope body's ## dast_target.url.
79
- let targetUrl = null;
80
- const lines = (scope.body || '').split('\n');
81
- let inDast = false;
82
- for (const line of lines) {
83
- if (/^## dast_target/.test(line)) { inDast = true; continue; }
84
- if (inDast && /^url:\s*(.+?)\s*$/.test(line)) { targetUrl = line.match(/^url:\s*(.+?)\s*$/)[1]; break; }
85
- if (inDast && /^## /.test(line)) break;
86
- }
87
- if (!targetUrl) {
88
- writePartial({
89
- securityDir: sec,
90
- phase: 'dast',
91
- mode: active ? 'active' : 'passive',
92
- scope,
93
- status: 'incomplete',
94
- tools,
95
- sections: { degraded_checks: '- nuclei: dast_target.url ausente no scope.md' }
96
- });
97
- return { ok: true, partialStatus: 'incomplete' };
98
- }
99
-
100
- // 2. Gate — target must be in scope.
101
- const urlObj = new URL(targetUrl);
102
- const inScope = assertTargetInScope(scope, { host: urlObj.hostname, url: targetUrl }, { refusalsDir: sec });
103
- if (!inScope) {
104
- writePartial({
105
- securityDir: sec,
106
- phase: 'dast',
107
- mode: active ? 'active' : 'passive',
108
- scope,
109
- status: 'incomplete',
110
- tools,
111
- sections: { degraded_checks: `- nuclei: target ${targetUrl} recusado pelo gate` }
112
- });
113
- return { ok: false, partialStatus: 'incomplete' };
114
- }
115
-
116
- // 3. Missing tool -> degraded.
117
- if (!present) {
118
- writePartial({
119
- securityDir: sec,
120
- phase: 'dast',
121
- mode: active ? 'active' : 'passive',
122
- scope,
123
- status: 'incomplete',
124
- tools,
125
- sections: { degraded_checks: '- nuclei: nuclei ausente — instale nuclei e re-rode a fase.' }
126
- });
127
- return { ok: true, partialStatus: 'incomplete' };
128
- }
129
-
130
- // 4. happy path.
131
- const outPath = path.join(sec, '.nuclei.json');
132
- const rawArgs = filterNucleiArgs(targetUrl, active, outPath);
133
- const args = filterArgs('nuclei', rawArgs);
134
- // nuclei may exit non-zero on some template errors; the JSONL output is
135
- // still written for whatever ran. Read it regardless of exit status.
136
- try {
137
- execFn('nuclei', args, { timeout: 10 * 60 * 1000 });
138
- } catch (_) { /* partial results still in outPath */ }
139
-
140
- let findings = [];
141
- if (fs.existsSync(outPath)) {
142
- try {
143
- findings = parseNucleiJson(fs.readFileSync(outPath, 'utf8'));
144
- } catch (_) {
145
- findings = [];
146
- }
147
- }
148
- const normalized = findings.map(normalizeFinding);
149
- const bodyLines = normalized.length
150
- ? normalized.map(f => `- **${f.template_id}** (\`${f.name}\`) severity=${f.severity} owasp=\`${f.owasp}\`${f.cvss != null ? ` cvss=${f.cvss}` : ''} matched_at: ${f.matched_at}`)
151
- : ['_(nenhum finding do nuclei)_'];
152
-
153
- writePartial({
154
- securityDir: sec,
155
- phase: 'dast',
156
- mode: active ? 'active' : 'passive',
157
- scope,
158
- status: normalized.length ? 'complete' : 'incomplete',
159
- tools,
160
- sections: { nuclei: bodyLines.join('\n') }
161
- });
162
- return { ok: true, partialStatus: normalized.length ? 'complete' : 'incomplete' };
163
- }
164
-
165
- module.exports = { runNuclei, filterNucleiArgs, parseNucleiJson, normalizeFinding };
166
-
167
- if (require.main === module) {
168
- require('../../../_shared/cli-runner.js').runFromArgv({
169
- fn: ({ securityDir, scopePath, active, target } = {}) => {
170
- const { loadScope } = require('../../../_shared/scope-gate.js');
171
- const scope = loadScope(scopePath);
172
- return runNuclei({ securityDir, scope, active, target });
173
- },
174
- argMap: { 'securityDir': 'securityDir', 'scope': 'scopePath', 'active': 'active', 'target': 'target' }
175
- });
176
- }