agentic-qe 3.5.4 → 3.6.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.
- package/.claude/agents/v3/README.md +1 -1
- package/.claude/agents/v3/qe-message-broker-tester.md +380 -0
- package/.claude/agents/v3/qe-middleware-validator.md +423 -0
- package/.claude/agents/v3/qe-odata-contract-tester.md +484 -0
- package/.claude/agents/v3/qe-pentest-validator.md +359 -0
- package/.claude/agents/v3/qe-qx-partner.md +85 -3
- package/.claude/agents/v3/qe-sap-idoc-tester.md +407 -0
- package/.claude/agents/v3/qe-sap-rfc-tester.md +357 -0
- package/.claude/agents/v3/qe-soap-tester.md +340 -0
- package/.claude/agents/v3/qe-sod-analyzer.md +528 -0
- package/.claude/agents/v3/templates/qx-report-template.html +437 -0
- package/.claude/skills/debug-loop/SKILL.md +61 -0
- package/.claude/skills/enterprise-integration-testing/SKILL.md +735 -0
- package/.claude/skills/middleware-testing-patterns/SKILL.md +798 -0
- package/.claude/skills/observability-testing-patterns/SKILL.md +930 -0
- package/.claude/skills/pentest-validation/SKILL.md +268 -0
- package/.claude/skills/pentest-validation/evals/pentest-validation.yaml +708 -0
- package/.claude/skills/pentest-validation/schemas/output.json +281 -0
- package/.claude/skills/pentest-validation/scripts/validate.sh +402 -0
- package/.claude/skills/pr-review/SKILL.md +61 -0
- package/.claude/skills/qcsd-cicd-swarm/SKILL.md +315 -13
- package/.claude/skills/qcsd-development-swarm/SKILL.md +331 -16
- package/.claude/skills/qcsd-ideation-swarm/SKILL.md +258 -9
- package/.claude/skills/qcsd-refinement-swarm/SKILL.md +344 -22
- package/.claude/skills/release/SKILL.md +333 -0
- package/.claude/skills/skills-manifest.json +5 -4
- package/.claude/skills/wms-testing-patterns/SKILL.md +949 -0
- package/README.md +30 -21
- package/package.json +2 -2
- package/v3/CHANGELOG.md +57 -0
- package/v3/README.md +23 -20
- package/v3/assets/agents/v3/qe-message-broker-tester.md +380 -0
- package/v3/assets/agents/v3/qe-middleware-validator.md +423 -0
- package/v3/assets/agents/v3/qe-odata-contract-tester.md +484 -0
- package/v3/assets/agents/v3/qe-pentest-validator.md +359 -0
- package/v3/assets/agents/v3/qe-qx-partner.md +90 -12
- package/v3/assets/agents/v3/qe-sap-idoc-tester.md +407 -0
- package/v3/assets/agents/v3/qe-sap-rfc-tester.md +357 -0
- package/v3/assets/agents/v3/qe-soap-tester.md +340 -0
- package/v3/assets/agents/v3/qe-sod-analyzer.md +528 -0
- package/v3/assets/agents/v3/templates/qx-report-template.html +437 -0
- package/v3/assets/skills/debug-loop/SKILL.md +61 -0
- package/v3/assets/skills/enterprise-integration-testing/SKILL.md +735 -0
- package/v3/assets/skills/middleware-testing-patterns/SKILL.md +798 -0
- package/v3/assets/skills/observability-testing-patterns/SKILL.md +930 -0
- package/v3/assets/skills/pentest-validation/SKILL.md +268 -0
- package/v3/assets/skills/pentest-validation/evals/pentest-validation.yaml +708 -0
- package/v3/assets/skills/pentest-validation/schemas/output.json +281 -0
- package/v3/assets/skills/pentest-validation/scripts/validate.sh +402 -0
- package/v3/assets/skills/pr-review/SKILL.md +61 -0
- package/v3/assets/skills/qcsd-cicd-swarm/SKILL.md +2206 -0
- package/v3/assets/skills/qcsd-development-swarm/SKILL.md +2154 -0
- package/v3/assets/skills/qcsd-ideation-swarm/SKILL.md +2008 -1753
- package/v3/assets/skills/qcsd-refinement-swarm/SKILL.md +2398 -0
- package/v3/assets/skills/security-visual-testing/SKILL.md +223 -0
- package/v3/assets/skills/security-visual-testing/evals/security-visual-testing.yaml +163 -0
- package/v3/assets/skills/security-visual-testing/schemas/output.json +486 -0
- package/v3/assets/skills/security-visual-testing/scripts/validate.sh +748 -0
- package/v3/assets/skills/sfdipot-product-factors/SKILL.md +239 -0
- package/v3/assets/skills/test-idea-rewriting/SKILL.md +229 -0
- package/v3/assets/skills/wms-testing-patterns/SKILL.md +949 -0
- package/v3/dist/cli/bundle.js +10816 -4625
- package/v3/dist/cli/commands/coverage.d.ts.map +1 -1
- package/v3/dist/cli/commands/coverage.js +29 -0
- package/v3/dist/cli/commands/coverage.js.map +1 -1
- package/v3/dist/cli/commands/learning.d.ts.map +1 -1
- package/v3/dist/cli/commands/learning.js +9 -0
- package/v3/dist/cli/commands/learning.js.map +1 -1
- package/v3/dist/cli/commands/token-usage.d.ts.map +1 -1
- package/v3/dist/cli/commands/token-usage.js +6 -2
- package/v3/dist/cli/commands/token-usage.js.map +1 -1
- package/v3/dist/coordination/protocols/learning-consolidation.d.ts.map +1 -1
- package/v3/dist/coordination/protocols/learning-consolidation.js +1 -0
- package/v3/dist/coordination/protocols/learning-consolidation.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/coordinator.d.ts +8 -0
- package/v3/dist/domains/coverage-analysis/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/coordinator.js +67 -0
- package/v3/dist/domains/coverage-analysis/coordinator.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/interfaces.d.ts +33 -0
- package/v3/dist/domains/coverage-analysis/interfaces.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/plugin.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/plugin.js +17 -0
- package/v3/dist/domains/coverage-analysis/plugin.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.d.ts +125 -0
- package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.d.ts.map +1 -0
- package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.js +317 -0
- package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.js.map +1 -0
- package/v3/dist/domains/coverage-analysis/services/index.d.ts +1 -0
- package/v3/dist/domains/coverage-analysis/services/index.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/services/index.js +4 -0
- package/v3/dist/domains/coverage-analysis/services/index.js.map +1 -1
- package/v3/dist/domains/enterprise-integration/coordinator.d.ts +91 -0
- package/v3/dist/domains/enterprise-integration/coordinator.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/coordinator.js +672 -0
- package/v3/dist/domains/enterprise-integration/coordinator.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/index.d.ts +14 -0
- package/v3/dist/domains/enterprise-integration/index.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/index.js +18 -0
- package/v3/dist/domains/enterprise-integration/index.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/interfaces.d.ts +376 -0
- package/v3/dist/domains/enterprise-integration/interfaces.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/interfaces.js +11 -0
- package/v3/dist/domains/enterprise-integration/interfaces.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/plugin.d.ts +88 -0
- package/v3/dist/domains/enterprise-integration/plugin.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/plugin.js +515 -0
- package/v3/dist/domains/enterprise-integration/plugin.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/esb-middleware-service.d.ts +67 -0
- package/v3/dist/domains/enterprise-integration/services/esb-middleware-service.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/esb-middleware-service.js +670 -0
- package/v3/dist/domains/enterprise-integration/services/esb-middleware-service.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/index.d.ts +13 -0
- package/v3/dist/domains/enterprise-integration/services/index.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/index.js +13 -0
- package/v3/dist/domains/enterprise-integration/services/index.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/message-broker-service.d.ts +88 -0
- package/v3/dist/domains/enterprise-integration/services/message-broker-service.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/message-broker-service.js +560 -0
- package/v3/dist/domains/enterprise-integration/services/message-broker-service.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/odata-service.d.ts +75 -0
- package/v3/dist/domains/enterprise-integration/services/odata-service.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/odata-service.js +618 -0
- package/v3/dist/domains/enterprise-integration/services/odata-service.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/sap-integration-service.d.ts +73 -0
- package/v3/dist/domains/enterprise-integration/services/sap-integration-service.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/sap-integration-service.js +513 -0
- package/v3/dist/domains/enterprise-integration/services/sap-integration-service.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/soap-wsdl-service.d.ts +84 -0
- package/v3/dist/domains/enterprise-integration/services/soap-wsdl-service.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/soap-wsdl-service.js +639 -0
- package/v3/dist/domains/enterprise-integration/services/soap-wsdl-service.js.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/sod-analysis-service.d.ts +90 -0
- package/v3/dist/domains/enterprise-integration/services/sod-analysis-service.d.ts.map +1 -0
- package/v3/dist/domains/enterprise-integration/services/sod-analysis-service.js +389 -0
- package/v3/dist/domains/enterprise-integration/services/sod-analysis-service.js.map +1 -0
- package/v3/dist/domains/index.d.ts +1 -0
- package/v3/dist/domains/index.d.ts.map +1 -1
- package/v3/dist/domains/index.js +1 -0
- package/v3/dist/domains/index.js.map +1 -1
- package/v3/dist/domains/learning-optimization/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/learning-optimization/coordinator.js +1 -0
- package/v3/dist/domains/learning-optimization/coordinator.js.map +1 -1
- package/v3/dist/domains/learning-optimization/services/learning-coordinator.d.ts.map +1 -1
- package/v3/dist/domains/learning-optimization/services/learning-coordinator.js +1 -0
- package/v3/dist/domains/learning-optimization/services/learning-coordinator.js.map +1 -1
- package/v3/dist/domains/learning-optimization/services/transfer-specialist.d.ts.map +1 -1
- package/v3/dist/domains/learning-optimization/services/transfer-specialist.js +1 -0
- package/v3/dist/domains/learning-optimization/services/transfer-specialist.js.map +1 -1
- package/v3/dist/domains/test-execution/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/test-execution/coordinator.js +34 -0
- package/v3/dist/domains/test-execution/coordinator.js.map +1 -1
- package/v3/dist/domains/test-generation/services/test-data-generator.d.ts +7 -1
- package/v3/dist/domains/test-generation/services/test-data-generator.d.ts.map +1 -1
- package/v3/dist/domains/test-generation/services/test-data-generator.js +116 -98
- package/v3/dist/domains/test-generation/services/test-data-generator.js.map +1 -1
- package/v3/dist/init/agents-installer.d.ts +4 -0
- package/v3/dist/init/agents-installer.d.ts.map +1 -1
- package/v3/dist/init/agents-installer.js +32 -3
- package/v3/dist/init/agents-installer.js.map +1 -1
- package/v3/dist/init/skills-installer.d.ts.map +1 -1
- package/v3/dist/init/skills-installer.js +4 -1
- package/v3/dist/init/skills-installer.js.map +1 -1
- package/v3/dist/init/types.d.ts.map +1 -1
- package/v3/dist/init/types.js +1 -0
- package/v3/dist/init/types.js.map +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/budget-enforcer.d.ts +16 -0
- package/v3/dist/integrations/agentic-flow/model-router/budget-enforcer.d.ts.map +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/budget-enforcer.js +41 -0
- package/v3/dist/integrations/agentic-flow/model-router/budget-enforcer.js.map +1 -1
- package/v3/dist/integrations/ruvector/provider.d.ts.map +1 -1
- package/v3/dist/integrations/ruvector/provider.js +1 -0
- package/v3/dist/integrations/ruvector/provider.js.map +1 -1
- package/v3/dist/kernel/anti-drift-middleware.d.ts +160 -0
- package/v3/dist/kernel/anti-drift-middleware.d.ts.map +1 -0
- package/v3/dist/kernel/anti-drift-middleware.js +376 -0
- package/v3/dist/kernel/anti-drift-middleware.js.map +1 -0
- package/v3/dist/kernel/event-bus.d.ts +29 -1
- package/v3/dist/kernel/event-bus.d.ts.map +1 -1
- package/v3/dist/kernel/event-bus.js +69 -6
- package/v3/dist/kernel/event-bus.js.map +1 -1
- package/v3/dist/kernel/interfaces.d.ts +35 -0
- package/v3/dist/kernel/interfaces.d.ts.map +1 -1
- package/v3/dist/kernel/kernel.d.ts.map +1 -1
- package/v3/dist/kernel/kernel.js +14 -17
- package/v3/dist/kernel/kernel.js.map +1 -1
- package/v3/dist/kernel/unified-memory.d.ts +5 -0
- package/v3/dist/kernel/unified-memory.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory.js +28 -0
- package/v3/dist/kernel/unified-memory.js.map +1 -1
- package/v3/dist/learning/asymmetric-learning.d.ts +133 -0
- package/v3/dist/learning/asymmetric-learning.d.ts.map +1 -0
- package/v3/dist/learning/asymmetric-learning.js +170 -0
- package/v3/dist/learning/asymmetric-learning.js.map +1 -0
- package/v3/dist/learning/pattern-lifecycle.d.ts +26 -0
- package/v3/dist/learning/pattern-lifecycle.d.ts.map +1 -1
- package/v3/dist/learning/pattern-lifecycle.js +83 -0
- package/v3/dist/learning/pattern-lifecycle.js.map +1 -1
- package/v3/dist/learning/qe-patterns.d.ts +8 -0
- package/v3/dist/learning/qe-patterns.d.ts.map +1 -1
- package/v3/dist/learning/qe-patterns.js.map +1 -1
- package/v3/dist/learning/real-qe-reasoning-bank.d.ts +28 -0
- package/v3/dist/learning/real-qe-reasoning-bank.d.ts.map +1 -1
- package/v3/dist/learning/real-qe-reasoning-bank.js +72 -4
- package/v3/dist/learning/real-qe-reasoning-bank.js.map +1 -1
- package/v3/dist/learning/token-tracker.d.ts +22 -0
- package/v3/dist/learning/token-tracker.d.ts.map +1 -1
- package/v3/dist/learning/token-tracker.js +67 -0
- package/v3/dist/learning/token-tracker.js.map +1 -1
- package/v3/dist/mcp/bundle.js +11099 -4879
- package/v3/dist/mcp/tool-registry.d.ts.map +1 -1
- package/v3/dist/mcp/tool-registry.js +4 -0
- package/v3/dist/mcp/tool-registry.js.map +1 -1
- package/v3/dist/mcp/tools/analysis/token-usage.d.ts +1 -1
- package/v3/dist/mcp/tools/analysis/token-usage.d.ts.map +1 -1
- package/v3/dist/mcp/tools/analysis/token-usage.js +23 -3
- package/v3/dist/mcp/tools/analysis/token-usage.js.map +1 -1
- package/v3/dist/mcp/tools/base.d.ts.map +1 -1
- package/v3/dist/mcp/tools/base.js +1 -15
- package/v3/dist/mcp/tools/base.js.map +1 -1
- package/v3/dist/mcp/tools/coverage-analysis/index.d.ts +7 -0
- package/v3/dist/mcp/tools/coverage-analysis/index.d.ts.map +1 -1
- package/v3/dist/mcp/tools/coverage-analysis/index.js +30 -0
- package/v3/dist/mcp/tools/coverage-analysis/index.js.map +1 -1
- package/v3/dist/optimization/token-optimizer-service.d.ts +7 -0
- package/v3/dist/optimization/token-optimizer-service.d.ts.map +1 -1
- package/v3/dist/optimization/token-optimizer-service.js +10 -1
- package/v3/dist/optimization/token-optimizer-service.js.map +1 -1
- package/v3/dist/shared/types/index.d.ts +20 -1
- package/v3/dist/shared/types/index.d.ts.map +1 -1
- package/v3/dist/shared/types/index.js +1 -0
- package/v3/dist/shared/types/index.js.map +1 -1
- package/v3/dist/strange-loop/healing-controller.d.ts.map +1 -1
- package/v3/dist/strange-loop/healing-controller.js +12 -0
- package/v3/dist/strange-loop/healing-controller.js.map +1 -1
- package/v3/dist/strange-loop/strange-loop.d.ts +14 -0
- package/v3/dist/strange-loop/strange-loop.d.ts.map +1 -1
- package/v3/dist/strange-loop/strange-loop.js +24 -0
- package/v3/dist/strange-loop/strange-loop.js.map +1 -1
- package/v3/dist/strange-loop/types.d.ts +2 -2
- package/v3/dist/strange-loop/types.d.ts.map +1 -1
- package/v3/dist/strange-loop/types.js.map +1 -1
- package/v3/dist/sync/claude-flow-bridge.d.ts.map +1 -1
- package/v3/dist/sync/claude-flow-bridge.js +3 -24
- package/v3/dist/sync/claude-flow-bridge.js.map +1 -1
- package/v3/package.json +12 -9
- /package/{v3/assets/skills/sfdipot-product-factors/skill.md → .claude/skills/sfdipot-product-factors/SKILL.md} +0 -0
- /package/{v3/assets/skills/test-idea-rewriting/skill.md → .claude/skills/test-idea-rewriting/SKILL.md} +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://agentic-qe.dev/schemas/pentest-validation-output.json",
|
|
4
|
+
"title": "AQE Pentest Validation Skill Output Schema",
|
|
5
|
+
"description": "Schema for pentest-validation skill output validation. Validates graduated exploitation results, finding classifications, PoC evidence, and 'No Exploit, No Report' filtering.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["skillName", "version", "timestamp", "status", "trustTier", "output"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"skillName": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"const": "pentest-validation",
|
|
12
|
+
"description": "Must be 'pentest-validation'"
|
|
13
|
+
},
|
|
14
|
+
"version": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9]+)?$",
|
|
17
|
+
"description": "Semantic version of the skill"
|
|
18
|
+
},
|
|
19
|
+
"timestamp": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"format": "date-time",
|
|
22
|
+
"description": "ISO 8601 timestamp of output generation"
|
|
23
|
+
},
|
|
24
|
+
"status": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["success", "partial", "failed", "blocked", "awaiting-authorization"],
|
|
27
|
+
"description": "Overall execution status"
|
|
28
|
+
},
|
|
29
|
+
"trustTier": {
|
|
30
|
+
"type": "integer",
|
|
31
|
+
"const": 3,
|
|
32
|
+
"description": "Trust tier 3 indicates full validation with eval suite"
|
|
33
|
+
},
|
|
34
|
+
"output": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"required": ["validationSummary", "findings"],
|
|
37
|
+
"properties": {
|
|
38
|
+
"validationSummary": {
|
|
39
|
+
"$ref": "#/$defs/validationSummary",
|
|
40
|
+
"description": "Summary of validation results"
|
|
41
|
+
},
|
|
42
|
+
"findings": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"items": {
|
|
45
|
+
"$ref": "#/$defs/validatedFinding"
|
|
46
|
+
},
|
|
47
|
+
"description": "Validated findings (only confirmed/likely per 'No Exploit, No Report')"
|
|
48
|
+
},
|
|
49
|
+
"eliminatedFindings": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": {
|
|
52
|
+
"$ref": "#/$defs/eliminatedFinding"
|
|
53
|
+
},
|
|
54
|
+
"description": "Findings eliminated as false positives"
|
|
55
|
+
},
|
|
56
|
+
"inconclusiveFindings": {
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": {
|
|
59
|
+
"$ref": "#/$defs/inconclusiveFinding"
|
|
60
|
+
},
|
|
61
|
+
"description": "Findings requiring manual review"
|
|
62
|
+
},
|
|
63
|
+
"costBreakdown": {
|
|
64
|
+
"$ref": "#/$defs/costBreakdown",
|
|
65
|
+
"description": "Cost per pipeline and total"
|
|
66
|
+
},
|
|
67
|
+
"playbookUpdates": {
|
|
68
|
+
"type": "integer",
|
|
69
|
+
"minimum": 0,
|
|
70
|
+
"description": "Number of new patterns stored in exploit playbook"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"$defs": {
|
|
76
|
+
"validationSummary": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"required": ["findingsReceived", "confirmedExploitable", "notExploitable"],
|
|
79
|
+
"properties": {
|
|
80
|
+
"findingsReceived": {
|
|
81
|
+
"type": "integer",
|
|
82
|
+
"minimum": 0,
|
|
83
|
+
"description": "Total findings received from scanner"
|
|
84
|
+
},
|
|
85
|
+
"confirmedExploitable": {
|
|
86
|
+
"type": "integer",
|
|
87
|
+
"minimum": 0,
|
|
88
|
+
"description": "Findings proven exploitable with PoC"
|
|
89
|
+
},
|
|
90
|
+
"likelyExploitable": {
|
|
91
|
+
"type": "integer",
|
|
92
|
+
"minimum": 0,
|
|
93
|
+
"description": "Findings with partial exploitation evidence"
|
|
94
|
+
},
|
|
95
|
+
"notExploitable": {
|
|
96
|
+
"type": "integer",
|
|
97
|
+
"minimum": 0,
|
|
98
|
+
"description": "Findings confirmed as false positives"
|
|
99
|
+
},
|
|
100
|
+
"inconclusive": {
|
|
101
|
+
"type": "integer",
|
|
102
|
+
"minimum": 0,
|
|
103
|
+
"description": "Findings blocked by defenses (need manual review)"
|
|
104
|
+
},
|
|
105
|
+
"falsePositivesEliminated": {
|
|
106
|
+
"type": "integer",
|
|
107
|
+
"minimum": 0,
|
|
108
|
+
"description": "Number of false positives removed from report"
|
|
109
|
+
},
|
|
110
|
+
"exploitationTierUsed": {
|
|
111
|
+
"type": "integer",
|
|
112
|
+
"enum": [1, 2, 3],
|
|
113
|
+
"description": "Highest exploitation tier used in this run"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"validatedFinding": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"required": ["id", "type", "severity", "classification", "evidence"],
|
|
120
|
+
"properties": {
|
|
121
|
+
"id": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Finding identifier"
|
|
124
|
+
},
|
|
125
|
+
"type": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": [
|
|
128
|
+
"sql-injection", "nosql-injection", "command-injection", "ldap-injection",
|
|
129
|
+
"reflected-xss", "stored-xss", "dom-xss",
|
|
130
|
+
"auth-bypass", "session-fixation", "jwt-manipulation", "idor", "credential-stuffing",
|
|
131
|
+
"ssrf", "dns-rebinding", "protocol-smuggling",
|
|
132
|
+
"path-traversal", "ssti", "deserialization", "hardcoded-credentials",
|
|
133
|
+
"other"
|
|
134
|
+
],
|
|
135
|
+
"description": "Vulnerability type"
|
|
136
|
+
},
|
|
137
|
+
"severity": {
|
|
138
|
+
"type": "string",
|
|
139
|
+
"enum": ["critical", "high", "medium", "low", "info"],
|
|
140
|
+
"description": "Severity classification"
|
|
141
|
+
},
|
|
142
|
+
"classification": {
|
|
143
|
+
"type": "string",
|
|
144
|
+
"enum": ["confirmed-exploitable", "likely-exploitable"],
|
|
145
|
+
"description": "Exploitation status (only confirmed/likely in output)"
|
|
146
|
+
},
|
|
147
|
+
"location": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"description": "Source code location (file:line)"
|
|
150
|
+
},
|
|
151
|
+
"exploitTier": {
|
|
152
|
+
"type": "integer",
|
|
153
|
+
"enum": [1, 2, 3],
|
|
154
|
+
"description": "Exploitation tier used to confirm"
|
|
155
|
+
},
|
|
156
|
+
"evidence": {
|
|
157
|
+
"$ref": "#/$defs/exploitEvidence",
|
|
158
|
+
"description": "Exploitation evidence"
|
|
159
|
+
},
|
|
160
|
+
"poc": {
|
|
161
|
+
"type": "string",
|
|
162
|
+
"minLength": 10,
|
|
163
|
+
"description": "Copy-paste proof-of-concept command"
|
|
164
|
+
},
|
|
165
|
+
"remediation": {
|
|
166
|
+
"type": "string",
|
|
167
|
+
"minLength": 20,
|
|
168
|
+
"description": "Recommended fix with code example"
|
|
169
|
+
},
|
|
170
|
+
"cwe": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"pattern": "^CWE-\\d+$",
|
|
173
|
+
"description": "CWE identifier"
|
|
174
|
+
},
|
|
175
|
+
"owasp": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"pattern": "^A\\d{2}:\\d{4}$",
|
|
178
|
+
"description": "OWASP Top 10 category"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"exploitEvidence": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"required": ["proof"],
|
|
185
|
+
"properties": {
|
|
186
|
+
"payload": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"description": "Payload used for exploitation"
|
|
189
|
+
},
|
|
190
|
+
"response": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"description": "Server response demonstrating exploitation"
|
|
193
|
+
},
|
|
194
|
+
"proof": {
|
|
195
|
+
"type": "string",
|
|
196
|
+
"minLength": 10,
|
|
197
|
+
"description": "Human-readable description of what was proven"
|
|
198
|
+
},
|
|
199
|
+
"screenshots": {
|
|
200
|
+
"type": "array",
|
|
201
|
+
"items": { "type": "string" },
|
|
202
|
+
"description": "Screenshot paths (for browser-based exploits)"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"eliminatedFinding": {
|
|
207
|
+
"type": "object",
|
|
208
|
+
"required": ["id", "type", "reason"],
|
|
209
|
+
"properties": {
|
|
210
|
+
"id": {
|
|
211
|
+
"type": "string",
|
|
212
|
+
"description": "Finding identifier"
|
|
213
|
+
},
|
|
214
|
+
"type": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"description": "Vulnerability type"
|
|
217
|
+
},
|
|
218
|
+
"reason": {
|
|
219
|
+
"type": "string",
|
|
220
|
+
"minLength": 10,
|
|
221
|
+
"description": "Why this finding was classified as not-exploitable"
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
"inconclusiveFinding": {
|
|
226
|
+
"type": "object",
|
|
227
|
+
"required": ["id", "type", "reason"],
|
|
228
|
+
"properties": {
|
|
229
|
+
"id": {
|
|
230
|
+
"type": "string",
|
|
231
|
+
"description": "Finding identifier"
|
|
232
|
+
},
|
|
233
|
+
"type": {
|
|
234
|
+
"type": "string",
|
|
235
|
+
"description": "Vulnerability type"
|
|
236
|
+
},
|
|
237
|
+
"reason": {
|
|
238
|
+
"type": "string",
|
|
239
|
+
"description": "Why this finding could not be conclusively validated"
|
|
240
|
+
},
|
|
241
|
+
"manualSteps": {
|
|
242
|
+
"type": "string",
|
|
243
|
+
"description": "Suggested manual validation steps"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"costBreakdown": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"properties": {
|
|
250
|
+
"totalUsd": {
|
|
251
|
+
"type": "number",
|
|
252
|
+
"minimum": 0,
|
|
253
|
+
"description": "Total cost in USD"
|
|
254
|
+
},
|
|
255
|
+
"tier1Cost": {
|
|
256
|
+
"type": "number",
|
|
257
|
+
"minimum": 0,
|
|
258
|
+
"description": "Tier 1 (Agent Booster) cost - always $0"
|
|
259
|
+
},
|
|
260
|
+
"tier2Cost": {
|
|
261
|
+
"type": "number",
|
|
262
|
+
"minimum": 0,
|
|
263
|
+
"description": "Tier 2 (Haiku) cost"
|
|
264
|
+
},
|
|
265
|
+
"tier3Cost": {
|
|
266
|
+
"type": "number",
|
|
267
|
+
"minimum": 0,
|
|
268
|
+
"description": "Tier 3 (Sonnet/Opus) cost"
|
|
269
|
+
},
|
|
270
|
+
"budgetRemaining": {
|
|
271
|
+
"type": "number",
|
|
272
|
+
"description": "Remaining budget after validation"
|
|
273
|
+
},
|
|
274
|
+
"withinBudget": {
|
|
275
|
+
"type": "boolean",
|
|
276
|
+
"description": "Whether validation stayed within budget cap"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# AQE Skill Validator: pentest-validation v1.0.0
|
|
4
|
+
# Validates pentest validation skill output per ADR-056
|
|
5
|
+
# =============================================================================
|
|
6
|
+
#
|
|
7
|
+
# This validator checks:
|
|
8
|
+
# 1. JSON schema compliance (finding classifications, PoC structure, evidence)
|
|
9
|
+
# 2. "No Exploit, No Report" filter enforcement
|
|
10
|
+
# 3. Finding classification accuracy
|
|
11
|
+
# 4. PoC quality and reproducibility
|
|
12
|
+
# 5. Safeguard enforcement (production URL blocking, authorization)
|
|
13
|
+
# 6. Cost tracking and budget compliance
|
|
14
|
+
#
|
|
15
|
+
# Usage: ./validate.sh <output-file> [options]
|
|
16
|
+
#
|
|
17
|
+
# Options:
|
|
18
|
+
# --self-test Run validator self-test mode
|
|
19
|
+
# --verbose Enable verbose output
|
|
20
|
+
# --json Output results as JSON only
|
|
21
|
+
# --list-tools Show available validation tools
|
|
22
|
+
# --help Show this help message
|
|
23
|
+
#
|
|
24
|
+
# Exit Codes:
|
|
25
|
+
# 0 - Validation passed
|
|
26
|
+
# 1 - Validation failed
|
|
27
|
+
# 2 - Validation skipped (missing required tools)
|
|
28
|
+
#
|
|
29
|
+
# =============================================================================
|
|
30
|
+
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
|
|
33
|
+
# Get script directory
|
|
34
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
35
|
+
|
|
36
|
+
# Navigate to skill directory and project root
|
|
37
|
+
# scripts/ -> pentest-validation/ -> skills/ -> .claude/ -> project root
|
|
38
|
+
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
39
|
+
PROJECT_ROOT="$(cd "$SKILL_DIR/../../.." && pwd)"
|
|
40
|
+
|
|
41
|
+
# Source validator library - check multiple locations
|
|
42
|
+
VALIDATOR_LIB=""
|
|
43
|
+
for lib_path in \
|
|
44
|
+
"$PROJECT_ROOT/.claude/skills/.validation/templates/validator-lib.sh" \
|
|
45
|
+
"$SKILL_DIR/scripts/validator-lib.sh" \
|
|
46
|
+
"$SCRIPT_DIR/validator-lib.sh"; do
|
|
47
|
+
if [[ -f "$lib_path" ]]; then
|
|
48
|
+
VALIDATOR_LIB="$lib_path"
|
|
49
|
+
break
|
|
50
|
+
fi
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
if [[ -n "$VALIDATOR_LIB" ]]; then
|
|
54
|
+
# shellcheck source=/dev/null
|
|
55
|
+
source "$VALIDATOR_LIB"
|
|
56
|
+
else
|
|
57
|
+
echo "ERROR: Validator library not found"
|
|
58
|
+
echo "Searched:"
|
|
59
|
+
echo " - $PROJECT_ROOT/.claude/skills/.validation/templates/validator-lib.sh"
|
|
60
|
+
echo " - $SKILL_DIR/scripts/validator-lib.sh"
|
|
61
|
+
echo " - $SCRIPT_DIR/validator-lib.sh"
|
|
62
|
+
exit 2
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# =============================================================================
|
|
66
|
+
# Validator Configuration
|
|
67
|
+
# =============================================================================
|
|
68
|
+
|
|
69
|
+
SKILL_NAME="pentest-validation"
|
|
70
|
+
SKILL_VERSION="1.0.0"
|
|
71
|
+
SCHEMA_FILE="$SKILL_DIR/schemas/output.json"
|
|
72
|
+
TRUST_TIER=3
|
|
73
|
+
|
|
74
|
+
# =============================================================================
|
|
75
|
+
# Self-Test Mode
|
|
76
|
+
# =============================================================================
|
|
77
|
+
|
|
78
|
+
run_self_test() {
|
|
79
|
+
local test_output
|
|
80
|
+
test_output=$(cat <<'SELF_TEST_JSON'
|
|
81
|
+
{
|
|
82
|
+
"skillName": "pentest-validation",
|
|
83
|
+
"version": "1.0.0",
|
|
84
|
+
"timestamp": "2026-02-08T12:00:00Z",
|
|
85
|
+
"status": "success",
|
|
86
|
+
"trustTier": 3,
|
|
87
|
+
"output": {
|
|
88
|
+
"validationSummary": {
|
|
89
|
+
"findingsReceived": 8,
|
|
90
|
+
"confirmedExploitable": 2,
|
|
91
|
+
"likelyExploitable": 1,
|
|
92
|
+
"notExploitable": 4,
|
|
93
|
+
"inconclusive": 1,
|
|
94
|
+
"falsePositivesEliminated": 4,
|
|
95
|
+
"exploitationTierUsed": 2
|
|
96
|
+
},
|
|
97
|
+
"findings": [
|
|
98
|
+
{
|
|
99
|
+
"id": "VULN-001",
|
|
100
|
+
"type": "sql-injection",
|
|
101
|
+
"severity": "critical",
|
|
102
|
+
"classification": "confirmed-exploitable",
|
|
103
|
+
"location": "src/api/users.ts:45",
|
|
104
|
+
"exploitTier": 2,
|
|
105
|
+
"evidence": {
|
|
106
|
+
"payload": "' OR '1'='1",
|
|
107
|
+
"response": "200 OK with all user records",
|
|
108
|
+
"proof": "Payload returned all 150 user records instead of single user"
|
|
109
|
+
},
|
|
110
|
+
"poc": "curl -X GET 'https://staging.app.com/api/users?id=1%27%20OR%20%271%27%3D%271'",
|
|
111
|
+
"remediation": "Use parameterized queries: db.query('SELECT * FROM users WHERE id = ?', [id])",
|
|
112
|
+
"cwe": "CWE-89",
|
|
113
|
+
"owasp": "A03:2021"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"id": "VULN-003",
|
|
117
|
+
"type": "reflected-xss",
|
|
118
|
+
"severity": "high",
|
|
119
|
+
"classification": "confirmed-exploitable",
|
|
120
|
+
"location": "src/routes/profile.ts:12",
|
|
121
|
+
"exploitTier": 2,
|
|
122
|
+
"evidence": {
|
|
123
|
+
"payload": "<img src=x onerror=alert(1)>",
|
|
124
|
+
"response": "Payload reflected unescaped in HTML",
|
|
125
|
+
"proof": "Injected img tag executed onerror handler in response"
|
|
126
|
+
},
|
|
127
|
+
"poc": "curl 'https://staging.app.com/profile?name=%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E'",
|
|
128
|
+
"remediation": "Use template engine auto-escaping or explicit DOMPurify sanitization",
|
|
129
|
+
"cwe": "CWE-79",
|
|
130
|
+
"owasp": "A03:2021"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"id": "VULN-005",
|
|
134
|
+
"type": "idor",
|
|
135
|
+
"severity": "high",
|
|
136
|
+
"classification": "likely-exploitable",
|
|
137
|
+
"location": "src/api/orders.ts:23",
|
|
138
|
+
"exploitTier": 2,
|
|
139
|
+
"evidence": {
|
|
140
|
+
"proof": "User A token returned User B order data with sequential ID guessing"
|
|
141
|
+
},
|
|
142
|
+
"poc": "curl -H 'Authorization: Bearer <userA_token>' 'https://staging.app.com/api/orders/2'",
|
|
143
|
+
"remediation": "Add ownership check: if (order.userId !== req.user.id) return res.status(403)",
|
|
144
|
+
"cwe": "CWE-639",
|
|
145
|
+
"owasp": "A01:2021"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"eliminatedFindings": [
|
|
149
|
+
{
|
|
150
|
+
"id": "VULN-002",
|
|
151
|
+
"type": "sql-injection",
|
|
152
|
+
"reason": "Parameterized query with integer parsing - not exploitable"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "VULN-004",
|
|
156
|
+
"type": "xss",
|
|
157
|
+
"reason": "Output auto-escaped by React JSX - not exploitable"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"id": "VULN-006",
|
|
161
|
+
"type": "path-traversal",
|
|
162
|
+
"reason": "Path normalized and restricted to uploads/ directory"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "VULN-007",
|
|
166
|
+
"type": "hardcoded-credentials",
|
|
167
|
+
"reason": "Test fixture file, not production code"
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"inconclusiveFindings": [
|
|
171
|
+
{
|
|
172
|
+
"id": "VULN-008",
|
|
173
|
+
"type": "ssrf",
|
|
174
|
+
"reason": "WAF blocked all internal URL attempts",
|
|
175
|
+
"manualSteps": "Test with WAF in learning mode or try DNS rebinding"
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"costBreakdown": {
|
|
179
|
+
"totalUsd": 4.82,
|
|
180
|
+
"tier1Cost": 0,
|
|
181
|
+
"tier2Cost": 1.20,
|
|
182
|
+
"tier3Cost": 3.62,
|
|
183
|
+
"budgetRemaining": 10.18,
|
|
184
|
+
"withinBudget": true
|
|
185
|
+
},
|
|
186
|
+
"playbookUpdates": 3
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
SELF_TEST_JSON
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
echo "$test_output" > /tmp/pentest-validation-self-test.json
|
|
193
|
+
validate_output /tmp/pentest-validation-self-test.json
|
|
194
|
+
local result=$?
|
|
195
|
+
rm -f /tmp/pentest-validation-self-test.json
|
|
196
|
+
return $result
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# =============================================================================
|
|
200
|
+
# Validation Functions
|
|
201
|
+
# =============================================================================
|
|
202
|
+
|
|
203
|
+
validate_output() {
|
|
204
|
+
local output_file="$1"
|
|
205
|
+
local verbose="${VERBOSE:-false}"
|
|
206
|
+
local json_only="${JSON_ONLY:-false}"
|
|
207
|
+
local pass_count=0
|
|
208
|
+
local fail_count=0
|
|
209
|
+
local skip_count=0
|
|
210
|
+
local results=()
|
|
211
|
+
|
|
212
|
+
# Check file exists
|
|
213
|
+
if [[ ! -f "$output_file" ]]; then
|
|
214
|
+
echo "ERROR: Output file not found: $output_file"
|
|
215
|
+
return 1
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
# Check jq is available
|
|
219
|
+
if ! command -v jq &>/dev/null; then
|
|
220
|
+
echo "SKIP: jq not available (required for JSON validation)"
|
|
221
|
+
return 2
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
# Validate JSON syntax
|
|
225
|
+
if ! jq empty "$output_file" 2>/dev/null; then
|
|
226
|
+
results+=('{"check": "json_syntax", "status": "FAIL", "message": "Invalid JSON"}')
|
|
227
|
+
fail_count=$((fail_count + 1))
|
|
228
|
+
else
|
|
229
|
+
results+=('{"check": "json_syntax", "status": "PASS", "message": "Valid JSON"}')
|
|
230
|
+
pass_count=$((pass_count + 1))
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
# Check required top-level fields
|
|
234
|
+
for field in skillName version timestamp status trustTier output; do
|
|
235
|
+
if jq -e ".$field" "$output_file" &>/dev/null; then
|
|
236
|
+
results+=("{\"check\": \"field_$field\", \"status\": \"PASS\", \"message\": \"Field $field present\"}")
|
|
237
|
+
pass_count=$((pass_count + 1))
|
|
238
|
+
else
|
|
239
|
+
results+=("{\"check\": \"field_$field\", \"status\": \"FAIL\", \"message\": \"Missing required field: $field\"}")
|
|
240
|
+
fail_count=$((fail_count + 1))
|
|
241
|
+
fi
|
|
242
|
+
done
|
|
243
|
+
|
|
244
|
+
# Check skillName matches
|
|
245
|
+
local skill_name
|
|
246
|
+
skill_name=$(jq -r '.skillName // ""' "$output_file")
|
|
247
|
+
if [[ "$skill_name" == "pentest-validation" ]]; then
|
|
248
|
+
results+=('{"check": "skill_name", "status": "PASS", "message": "Correct skill name"}')
|
|
249
|
+
pass_count=$((pass_count + 1))
|
|
250
|
+
else
|
|
251
|
+
results+=("{\"check\": \"skill_name\", \"status\": \"FAIL\", \"message\": \"Expected pentest-validation, got $skill_name\"}")
|
|
252
|
+
fail_count=$((fail_count + 1))
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
# Check trustTier is 3
|
|
256
|
+
local trust_tier
|
|
257
|
+
trust_tier=$(jq -r '.trustTier // 0' "$output_file")
|
|
258
|
+
if [[ "$trust_tier" == "3" ]]; then
|
|
259
|
+
results+=('{"check": "trust_tier", "status": "PASS", "message": "Trust tier 3"}')
|
|
260
|
+
pass_count=$((pass_count + 1))
|
|
261
|
+
else
|
|
262
|
+
results+=("{\"check\": \"trust_tier\", \"status\": \"FAIL\", \"message\": \"Expected trust tier 3, got $trust_tier\"}")
|
|
263
|
+
fail_count=$((fail_count + 1))
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
# Check validation summary exists
|
|
267
|
+
if jq -e '.output.validationSummary' "$output_file" &>/dev/null; then
|
|
268
|
+
results+=('{"check": "validation_summary", "status": "PASS", "message": "Validation summary present"}')
|
|
269
|
+
pass_count=$((pass_count + 1))
|
|
270
|
+
|
|
271
|
+
# Check "No Exploit, No Report" filter
|
|
272
|
+
local confirmed
|
|
273
|
+
local not_exploitable
|
|
274
|
+
confirmed=$(jq -r '.output.validationSummary.confirmedExploitable // 0' "$output_file")
|
|
275
|
+
not_exploitable=$(jq -r '.output.validationSummary.notExploitable // 0' "$output_file")
|
|
276
|
+
local reported_count
|
|
277
|
+
reported_count=$(jq -r '.output.findings | length' "$output_file")
|
|
278
|
+
|
|
279
|
+
# Reported findings should only be confirmed or likely
|
|
280
|
+
local invalid_classifications
|
|
281
|
+
invalid_classifications=$(jq '[.output.findings[] | select(.classification != "confirmed-exploitable" and .classification != "likely-exploitable")] | length' "$output_file" 2>/dev/null || echo "0")
|
|
282
|
+
if [[ "$invalid_classifications" == "0" ]]; then
|
|
283
|
+
results+=('{"check": "no_exploit_no_report", "status": "PASS", "message": "Only confirmed/likely findings in output"}')
|
|
284
|
+
pass_count=$((pass_count + 1))
|
|
285
|
+
else
|
|
286
|
+
results+=("{\"check\": \"no_exploit_no_report\", \"status\": \"FAIL\", \"message\": \"$invalid_classifications findings with wrong classification in output\"}")
|
|
287
|
+
fail_count=$((fail_count + 1))
|
|
288
|
+
fi
|
|
289
|
+
else
|
|
290
|
+
results+=('{"check": "validation_summary", "status": "FAIL", "message": "Missing validation summary"}')
|
|
291
|
+
fail_count=$((fail_count + 1))
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# Check PoC exists for confirmed findings
|
|
295
|
+
local confirmed_without_poc
|
|
296
|
+
confirmed_without_poc=$(jq '[.output.findings[] | select(.classification == "confirmed-exploitable" and (.poc == null or .poc == ""))] | length' "$output_file" 2>/dev/null || echo "0")
|
|
297
|
+
if [[ "$confirmed_without_poc" == "0" ]]; then
|
|
298
|
+
results+=('{"check": "poc_coverage", "status": "PASS", "message": "All confirmed findings have PoC"}')
|
|
299
|
+
pass_count=$((pass_count + 1))
|
|
300
|
+
else
|
|
301
|
+
results+=("{\"check\": \"poc_coverage\", \"status\": \"FAIL\", \"message\": \"$confirmed_without_poc confirmed findings missing PoC\"}")
|
|
302
|
+
fail_count=$((fail_count + 1))
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
# Check evidence exists for all findings
|
|
306
|
+
local findings_without_evidence
|
|
307
|
+
findings_without_evidence=$(jq '[.output.findings[] | select(.evidence == null or .evidence.proof == null or .evidence.proof == "")] | length' "$output_file" 2>/dev/null || echo "0")
|
|
308
|
+
if [[ "$findings_without_evidence" == "0" ]]; then
|
|
309
|
+
results+=('{"check": "evidence_coverage", "status": "PASS", "message": "All findings have evidence"}')
|
|
310
|
+
pass_count=$((pass_count + 1))
|
|
311
|
+
else
|
|
312
|
+
results+=("{\"check\": \"evidence_coverage\", \"status\": \"FAIL\", \"message\": \"$findings_without_evidence findings missing evidence\"}")
|
|
313
|
+
fail_count=$((fail_count + 1))
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
# Check cost tracking
|
|
317
|
+
if jq -e '.output.costBreakdown.withinBudget' "$output_file" &>/dev/null; then
|
|
318
|
+
local within_budget
|
|
319
|
+
within_budget=$(jq -r '.output.costBreakdown.withinBudget' "$output_file")
|
|
320
|
+
if [[ "$within_budget" == "true" ]]; then
|
|
321
|
+
results+=('{"check": "budget_compliance", "status": "PASS", "message": "Within budget"}')
|
|
322
|
+
pass_count=$((pass_count + 1))
|
|
323
|
+
else
|
|
324
|
+
results+=('{"check": "budget_compliance", "status": "FAIL", "message": "Over budget"}')
|
|
325
|
+
fail_count=$((fail_count + 1))
|
|
326
|
+
fi
|
|
327
|
+
else
|
|
328
|
+
results+=('{"check": "budget_compliance", "status": "SKIP", "message": "No cost breakdown"}')
|
|
329
|
+
skip_count=$((skip_count + 1))
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
# Output results
|
|
333
|
+
local total=$((pass_count + fail_count + skip_count))
|
|
334
|
+
if [[ "$json_only" == "true" ]]; then
|
|
335
|
+
echo "{\"skill\": \"$SKILL_NAME\", \"version\": \"$SKILL_VERSION\", \"trustTier\": $TRUST_TIER, \"pass\": $pass_count, \"fail\": $fail_count, \"skip\": $skip_count, \"total\": $total, \"results\": [$(IFS=,; echo "${results[*]}")]}"
|
|
336
|
+
else
|
|
337
|
+
echo "=== Pentest Validation Skill Validator ==="
|
|
338
|
+
echo "Skill: $SKILL_NAME v$SKILL_VERSION (Trust Tier $TRUST_TIER)"
|
|
339
|
+
echo "---"
|
|
340
|
+
echo "PASS: $pass_count | FAIL: $fail_count | SKIP: $skip_count | TOTAL: $total"
|
|
341
|
+
echo "---"
|
|
342
|
+
if [[ "$verbose" == "true" ]]; then
|
|
343
|
+
for result in "${results[@]}"; do
|
|
344
|
+
local status
|
|
345
|
+
local check
|
|
346
|
+
local message
|
|
347
|
+
status=$(echo "$result" | jq -r '.status')
|
|
348
|
+
check=$(echo "$result" | jq -r '.check')
|
|
349
|
+
message=$(echo "$result" | jq -r '.message')
|
|
350
|
+
echo " [$status] $check: $message"
|
|
351
|
+
done
|
|
352
|
+
fi
|
|
353
|
+
echo "---"
|
|
354
|
+
if [[ $fail_count -eq 0 ]]; then
|
|
355
|
+
echo "RESULT: PASS"
|
|
356
|
+
else
|
|
357
|
+
echo "RESULT: FAIL ($fail_count checks failed)"
|
|
358
|
+
fi
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
[[ $fail_count -eq 0 ]]
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
# =============================================================================
|
|
365
|
+
# Main
|
|
366
|
+
# =============================================================================
|
|
367
|
+
|
|
368
|
+
main() {
|
|
369
|
+
case "${1:-}" in
|
|
370
|
+
--self-test)
|
|
371
|
+
echo "Running self-test..."
|
|
372
|
+
run_self_test
|
|
373
|
+
;;
|
|
374
|
+
--help)
|
|
375
|
+
head -27 "$0" | tail -20
|
|
376
|
+
;;
|
|
377
|
+
--list-tools)
|
|
378
|
+
echo "Required: jq"
|
|
379
|
+
echo "Optional: curl (for live endpoint testing)"
|
|
380
|
+
;;
|
|
381
|
+
*)
|
|
382
|
+
if [[ -z "${1:-}" ]]; then
|
|
383
|
+
echo "Usage: $0 <output-file> [--verbose] [--json] [--self-test]"
|
|
384
|
+
exit 1
|
|
385
|
+
fi
|
|
386
|
+
|
|
387
|
+
# Parse options
|
|
388
|
+
export VERBOSE="false"
|
|
389
|
+
export JSON_ONLY="false"
|
|
390
|
+
for arg in "${@:2}"; do
|
|
391
|
+
case "$arg" in
|
|
392
|
+
--verbose) VERBOSE="true" ;;
|
|
393
|
+
--json) JSON_ONLY="true" ;;
|
|
394
|
+
esac
|
|
395
|
+
done
|
|
396
|
+
|
|
397
|
+
validate_output "$1"
|
|
398
|
+
;;
|
|
399
|
+
esac
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
main "$@"
|