hullproof 0.0.0-stage → 0.5.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 (363) hide show
  1. package/LICENSE +222 -0
  2. package/NOTICE +32 -0
  3. package/README.md +313 -2
  4. package/checks/db.firebase-rules-not-open.json +24 -0
  5. package/checks/db.rls-every-table.json +25 -0
  6. package/checks/log.no-credential-in-logs.json +30 -0
  7. package/checks/secrets.no-env-file-committed.json +31 -0
  8. package/checks/secrets.no-secret-in-public-env.json +37 -0
  9. package/checks/storage.firebase-rules-not-open.json +22 -0
  10. package/checks/supply.no-untrusted-event-in-run.json +23 -0
  11. package/checks/web.cors-no-reflected-origin.json +31 -0
  12. package/detectors/ai.json +25 -0
  13. package/detectors/auth.json +27 -0
  14. package/detectors/ci.json +19 -0
  15. package/detectors/containers.json +8 -0
  16. package/detectors/data_stores.json +38 -0
  17. package/detectors/frameworks.json +94 -0
  18. package/detectors/hosting.json +44 -0
  19. package/detectors/iac.json +43 -0
  20. package/detectors/languages.json +48 -0
  21. package/detectors/mobile.json +22 -0
  22. package/detectors/package_managers.json +39 -0
  23. package/detectors/payments.json +19 -0
  24. package/detectors/runtimes.json +17 -0
  25. package/dist/checks/code/admin-role.js +46 -0
  26. package/dist/checks/code/owner-filter.js +91 -0
  27. package/dist/checks/code/shared.js +84 -0
  28. package/dist/checks/code/webhook-verify.js +77 -0
  29. package/dist/checks/context.js +64 -0
  30. package/dist/checks/map/config-checks.js +74 -0
  31. package/dist/checks/map/entry-checks.js +97 -0
  32. package/dist/checks/map/shared.js +44 -0
  33. package/dist/checks/ops.js +307 -0
  34. package/dist/checks/pro-map.js +1 -0
  35. package/dist/checks/run.js +92 -0
  36. package/dist/checks/types.js +1 -0
  37. package/dist/ci/comment.js +44 -0
  38. package/dist/ci/sarif-check.js +157 -0
  39. package/dist/ci/sarif.js +61 -0
  40. package/dist/cli.js +358 -0
  41. package/dist/commands/ci.js +115 -0
  42. package/dist/commands/git.js +58 -0
  43. package/dist/commands/hooks.js +30 -0
  44. package/dist/commands/hunt-pro.js +1 -0
  45. package/dist/commands/hunt.js +86 -0
  46. package/dist/commands/map.js +33 -0
  47. package/dist/commands/mcp.js +17 -0
  48. package/dist/commands/pack.js +48 -0
  49. package/dist/commands/prove-pro.js +1 -0
  50. package/dist/commands/prove.js +173 -0
  51. package/dist/commands/report-gate.js +92 -0
  52. package/dist/commands/scan.js +158 -0
  53. package/dist/confirm/agreement.js +18 -0
  54. package/dist/confirm/chain.js +84 -0
  55. package/dist/confirm/confirm.js +112 -0
  56. package/dist/confirm/honesty.js +75 -0
  57. package/dist/confirm/lead.js +92 -0
  58. package/dist/confirm/merge.js +88 -0
  59. package/dist/confirm/query.js +145 -0
  60. package/dist/confirm/rule.js +86 -0
  61. package/dist/confirm/store.js +42 -0
  62. package/dist/confirm/summary.js +6 -0
  63. package/dist/confirm/synthesis.js +28 -0
  64. package/dist/discover/detectors.js +50 -0
  65. package/dist/discover/discover.js +270 -0
  66. package/dist/discover/extract.js +282 -0
  67. package/dist/discover/git.js +40 -0
  68. package/dist/discover/kit-files.js +47 -0
  69. package/dist/discover/walk.js +110 -0
  70. package/dist/env.js +57 -0
  71. package/dist/gate/gate.js +173 -0
  72. package/dist/hooks/install.js +153 -0
  73. package/dist/hooks/run.js +112 -0
  74. package/dist/map/analyze.js +201 -0
  75. package/dist/map/build.js +253 -0
  76. package/dist/map/candidates.js +49 -0
  77. package/dist/map/cblocks.js +77 -0
  78. package/dist/map/config.js +291 -0
  79. package/dist/map/dotnet.js +242 -0
  80. package/dist/map/entry.js +78 -0
  81. package/dist/map/expo.js +190 -0
  82. package/dist/map/go.js +292 -0
  83. package/dist/map/js-express.js +143 -0
  84. package/dist/map/js-misc.js +295 -0
  85. package/dist/map/js-next.js +292 -0
  86. package/dist/map/laravel.js +389 -0
  87. package/dist/map/lex-more.js +305 -0
  88. package/dist/map/lex.js +425 -0
  89. package/dist/map/light-index.js +191 -0
  90. package/dist/map/light-profiles.js +324 -0
  91. package/dist/map/light.js +574 -0
  92. package/dist/map/local-vocab.js +27 -0
  93. package/dist/map/mobile.js +326 -0
  94. package/dist/map/py-django.js +281 -0
  95. package/dist/map/py.js +391 -0
  96. package/dist/map/rails.js +391 -0
  97. package/dist/map/repo.js +178 -0
  98. package/dist/map/rust.js +312 -0
  99. package/dist/map/spring.js +207 -0
  100. package/dist/map/taint.js +96 -0
  101. package/dist/map/touches.js +355 -0
  102. package/dist/map/vocab.js +88 -0
  103. package/dist/mapping/controls.js +34 -0
  104. package/dist/mapping/dependency-policy.js +44 -0
  105. package/dist/mapping/map.js +44 -0
  106. package/dist/mapping/maps/gitleaks.json +12 -0
  107. package/dist/mapping/maps/osv-scanner.json +7 -0
  108. package/dist/mapping/maps/trivy.json +13 -0
  109. package/dist/mcp/confine.js +59 -0
  110. package/dist/mcp/protocol.js +140 -0
  111. package/dist/mcp/schema.js +43 -0
  112. package/dist/mcp/server.js +37 -0
  113. package/dist/mcp/tools.js +238 -0
  114. package/dist/packs/coverage.js +79 -0
  115. package/dist/packs/manifest.js +36 -0
  116. package/dist/packs/validate.js +271 -0
  117. package/dist/prove/container.js +276 -0
  118. package/dist/prove/exec-main.js +20 -0
  119. package/dist/prove/executor.js +149 -0
  120. package/dist/prove/local.js +131 -0
  121. package/dist/prove/probes.js +65 -0
  122. package/dist/prove/recipe.js +278 -0
  123. package/dist/prove/run.js +136 -0
  124. package/dist/prove/runner.js +1 -0
  125. package/dist/prove/safety.js +126 -0
  126. package/dist/prove/spec.js +357 -0
  127. package/dist/prove/store.js +65 -0
  128. package/dist/report/build.js +297 -0
  129. package/dist/report/entry-points.js +75 -0
  130. package/dist/report/hunt-section.js +71 -0
  131. package/dist/report/kit.js +41 -0
  132. package/dist/report/load.js +35 -0
  133. package/dist/report/messages.js +273 -0
  134. package/dist/report/prove-section.js +65 -0
  135. package/dist/report/report.js +156 -0
  136. package/dist/report/surface.js +21 -0
  137. package/dist/report/test-code.js +51 -0
  138. package/dist/report/tiers.js +44 -0
  139. package/dist/scanners/common.js +162 -0
  140. package/dist/scanners/gitleaks.js +90 -0
  141. package/dist/scanners/index.js +113 -0
  142. package/dist/scanners/osv-scanner.js +77 -0
  143. package/dist/scanners/run-targets.js +34 -0
  144. package/dist/scanners/secret-noise.js +89 -0
  145. package/dist/scanners/semgrep.js +142 -0
  146. package/dist/scanners/trivy.js +65 -0
  147. package/dist/scanners/types.js +1 -0
  148. package/dist/types/check.js +1 -0
  149. package/dist/types/codemap.js +1 -0
  150. package/dist/types/findings.js +5 -0
  151. package/dist/types/hunt.js +1 -0
  152. package/dist/types/index.js +1 -0
  153. package/dist/types/prove.js +1 -0
  154. package/dist/types/results.js +2 -0
  155. package/dist/types/scan.js +1 -0
  156. package/dist/types/stack.js +5 -0
  157. package/dist/util.js +71 -0
  158. package/dist/version.js +2 -0
  159. package/package.json +46 -4
  160. package/packs/android/fixture-result.json +43 -0
  161. package/packs/android/pack.json +56 -0
  162. package/packs/dotnet/fixture-result.json +62 -0
  163. package/packs/dotnet/pack.json +88 -0
  164. package/packs/expo/answer-key.json +51 -0
  165. package/packs/expo/fixture-result.json +62 -0
  166. package/packs/expo/pack.json +79 -0
  167. package/packs/firebase/answer-key.json +27 -0
  168. package/packs/firebase/fixture-result.json +43 -0
  169. package/packs/firebase/pack.json +58 -0
  170. package/packs/go/answer-key.json +101 -0
  171. package/packs/go/fixture-result.json +64 -0
  172. package/packs/go/pack.json +99 -0
  173. package/packs/ios/fixture-result.json +43 -0
  174. package/packs/ios/pack.json +55 -0
  175. package/packs/laravel/answer-key.json +84 -0
  176. package/packs/laravel/fixture-result.json +60 -0
  177. package/packs/laravel/pack.json +91 -0
  178. package/packs/node-ts/answer-key.json +220 -0
  179. package/packs/node-ts/fixture-result.json +114 -0
  180. package/packs/node-ts/pack.json +134 -0
  181. package/packs/python/answer-key.json +195 -0
  182. package/packs/python/fixture-result.json +119 -0
  183. package/packs/python/pack.json +121 -0
  184. package/packs/rails/answer-key.json +84 -0
  185. package/packs/rails/fixture-result.json +60 -0
  186. package/packs/rails/pack.json +78 -0
  187. package/packs/rust/fixture-result.json +43 -0
  188. package/packs/rust/pack.json +69 -0
  189. package/packs/spring/fixture-result.json +63 -0
  190. package/packs/spring/pack.json +103 -0
  191. package/packs/supabase/answer-key.json +52 -0
  192. package/packs/supabase/fixture-result.json +58 -0
  193. package/packs/supabase/pack.json +60 -0
  194. package/rules/gitleaks.toml +256 -0
  195. package/rules/semgrep/api-route-no-auth.yaml +31 -0
  196. package/rules/semgrep/cors-reflect-origin.yaml +48 -0
  197. package/rules/semgrep/eval-or-new-function.yaml +185 -0
  198. package/rules/semgrep/log-session-token.yaml +48 -0
  199. package/rules/semgrep/math-random-tokens.yaml +24 -0
  200. package/rules/semgrep/next-public-secret-name.yaml +32 -0
  201. package/rules/semgrep/postgrest-filter-injection.yaml +78 -0
  202. package/rules/semgrep/raw-sql-concat.yaml +42 -0
  203. package/rules/semgrep/read-by-id-no-owner.yaml +49 -0
  204. package/rules/semgrep/server-action-no-auth.yaml +26 -0
  205. package/rules/semgrep/sql-variants.yaml +99 -0
  206. package/rules/semgrep/ssrf-unguarded-url.yaml +137 -0
  207. package/rules/semgrep/subprocess-injection.yaml +163 -0
  208. package/rules/semgrep/taint-go.yaml +333 -0
  209. package/rules/semgrep/taint-java.yaml +317 -0
  210. package/rules/semgrep/taint-javascript.yaml +412 -0
  211. package/rules/semgrep/taint-php.yaml +361 -0
  212. package/rules/semgrep/taint-python.yaml +414 -0
  213. package/rules/semgrep/tool-endpoint-admin-client.yaml +86 -0
  214. package/rules/semgrep/user-metadata-authz.yaml +22 -0
  215. package/rules/semgrep/verify-result-unused.yaml +62 -0
  216. package/rules/semgrep/webhook-parse-before-verify.yaml +29 -0
  217. package/rules/test-artifact-ids.json +4 -0
  218. package/rules/tiers.json +427 -0
  219. package/schemas/check-results.schema.json +55 -0
  220. package/schemas/check.schema.json +41 -0
  221. package/schemas/codemap.schema.json +216 -0
  222. package/schemas/findings.schema.json +1048 -0
  223. package/schemas/hunt-output.schema.json +46 -0
  224. package/schemas/hunt-result.schema.json +58 -0
  225. package/schemas/results.schema.json +17 -0
  226. package/schemas/scan-hits.schema.json +32 -0
  227. package/schemas/scan-meta.schema.json +25 -0
  228. package/schemas/stack.schema.json +93 -0
  229. package/src/checks/README.md +32 -0
  230. package/src/checks/code/admin-role.ts +49 -0
  231. package/src/checks/code/owner-filter.ts +95 -0
  232. package/src/checks/code/shared.ts +66 -0
  233. package/src/checks/code/webhook-verify.ts +75 -0
  234. package/src/checks/context.ts +72 -0
  235. package/src/checks/map/config-checks.ts +79 -0
  236. package/src/checks/map/entry-checks.ts +116 -0
  237. package/src/checks/map/shared.ts +63 -0
  238. package/src/checks/ops.ts +280 -0
  239. package/src/checks/pro-map.ts +4 -0
  240. package/src/checks/run.ts +80 -0
  241. package/src/checks/types.ts +12 -0
  242. package/src/ci/comment.ts +52 -0
  243. package/src/ci/sarif-check.ts +100 -0
  244. package/src/ci/sarif.ts +72 -0
  245. package/src/cli.ts +273 -0
  246. package/src/commands/ci.ts +104 -0
  247. package/src/commands/git.ts +59 -0
  248. package/src/commands/hooks.ts +27 -0
  249. package/src/commands/hunt-pro.ts +4 -0
  250. package/src/commands/hunt.ts +68 -0
  251. package/src/commands/map.ts +27 -0
  252. package/src/commands/mcp.ts +18 -0
  253. package/src/commands/pack.ts +34 -0
  254. package/src/commands/prove-pro.ts +4 -0
  255. package/src/commands/prove.ts +126 -0
  256. package/src/commands/report-gate.ts +75 -0
  257. package/src/commands/scan.ts +156 -0
  258. package/src/confirm/agreement.ts +23 -0
  259. package/src/confirm/chain.ts +67 -0
  260. package/src/confirm/confirm.ts +107 -0
  261. package/src/confirm/honesty.ts +65 -0
  262. package/src/confirm/lead.ts +76 -0
  263. package/src/confirm/merge.ts +89 -0
  264. package/src/confirm/query.ts +126 -0
  265. package/src/confirm/rule.ts +76 -0
  266. package/src/confirm/store.ts +42 -0
  267. package/src/confirm/summary.ts +9 -0
  268. package/src/confirm/synthesis.ts +33 -0
  269. package/src/discover/detectors.ts +71 -0
  270. package/src/discover/discover.ts +253 -0
  271. package/src/discover/extract.ts +235 -0
  272. package/src/discover/git.ts +31 -0
  273. package/src/discover/kit-files.ts +37 -0
  274. package/src/discover/walk.ts +88 -0
  275. package/src/env.ts +51 -0
  276. package/src/gate/gate.ts +169 -0
  277. package/src/hooks/install.ts +142 -0
  278. package/src/hooks/run.ts +121 -0
  279. package/src/map/analyze.ts +219 -0
  280. package/src/map/build.ts +206 -0
  281. package/src/map/candidates.ts +47 -0
  282. package/src/map/cblocks.ts +55 -0
  283. package/src/map/config.ts +207 -0
  284. package/src/map/dotnet.ts +205 -0
  285. package/src/map/entry.ts +80 -0
  286. package/src/map/expo.ts +171 -0
  287. package/src/map/go.ts +271 -0
  288. package/src/map/js-express.ts +135 -0
  289. package/src/map/js-misc.ts +221 -0
  290. package/src/map/js-next.ts +282 -0
  291. package/src/map/laravel.ts +327 -0
  292. package/src/map/lex-more.ts +152 -0
  293. package/src/map/lex.ts +274 -0
  294. package/src/map/light-index.ts +134 -0
  295. package/src/map/light-profiles.ts +363 -0
  296. package/src/map/light.ts +484 -0
  297. package/src/map/local-vocab.ts +30 -0
  298. package/src/map/mobile.ts +263 -0
  299. package/src/map/py-django.ts +239 -0
  300. package/src/map/py.ts +329 -0
  301. package/src/map/rails.ts +291 -0
  302. package/src/map/repo.ts +150 -0
  303. package/src/map/rust.ts +256 -0
  304. package/src/map/spring.ts +185 -0
  305. package/src/map/taint.ts +86 -0
  306. package/src/map/touches.ts +296 -0
  307. package/src/map/vocab.ts +106 -0
  308. package/src/mapping/controls.ts +47 -0
  309. package/src/mapping/dependency-policy.ts +55 -0
  310. package/src/mapping/map.ts +59 -0
  311. package/src/mapping/maps/gitleaks.json +12 -0
  312. package/src/mapping/maps/osv-scanner.json +7 -0
  313. package/src/mapping/maps/trivy.json +13 -0
  314. package/src/mcp/confine.ts +44 -0
  315. package/src/mcp/protocol.ts +144 -0
  316. package/src/mcp/schema.ts +35 -0
  317. package/src/mcp/server.ts +32 -0
  318. package/src/mcp/tools.ts +235 -0
  319. package/src/packs/coverage.ts +98 -0
  320. package/src/packs/manifest.ts +97 -0
  321. package/src/packs/validate.ts +204 -0
  322. package/src/prove/container.ts +237 -0
  323. package/src/prove/exec-main.ts +16 -0
  324. package/src/prove/executor.ts +130 -0
  325. package/src/prove/local.ts +100 -0
  326. package/src/prove/probes.ts +68 -0
  327. package/src/prove/recipe.ts +215 -0
  328. package/src/prove/run.ts +124 -0
  329. package/src/prove/runner.ts +28 -0
  330. package/src/prove/safety.ts +98 -0
  331. package/src/prove/spec.ts +256 -0
  332. package/src/prove/store.ts +48 -0
  333. package/src/report/build.ts +304 -0
  334. package/src/report/entry-points.ts +78 -0
  335. package/src/report/hunt-section.ts +67 -0
  336. package/src/report/kit.ts +59 -0
  337. package/src/report/load.ts +49 -0
  338. package/src/report/messages.ts +270 -0
  339. package/src/report/prove-section.ts +61 -0
  340. package/src/report/report.ts +160 -0
  341. package/src/report/surface.ts +32 -0
  342. package/src/report/test-code.ts +56 -0
  343. package/src/report/tiers.ts +50 -0
  344. package/src/scanners/common.ts +149 -0
  345. package/src/scanners/gitleaks.ts +89 -0
  346. package/src/scanners/index.ts +103 -0
  347. package/src/scanners/osv-scanner.ts +90 -0
  348. package/src/scanners/run-targets.ts +35 -0
  349. package/src/scanners/secret-noise.ts +80 -0
  350. package/src/scanners/semgrep.ts +139 -0
  351. package/src/scanners/trivy.ts +66 -0
  352. package/src/scanners/types.ts +98 -0
  353. package/src/types/check.ts +52 -0
  354. package/src/types/codemap.ts +142 -0
  355. package/src/types/findings.ts +107 -0
  356. package/src/types/hunt.ts +97 -0
  357. package/src/types/index.ts +10 -0
  358. package/src/types/prove.ts +83 -0
  359. package/src/types/results.ts +15 -0
  360. package/src/types/scan.ts +63 -0
  361. package/src/types/stack.ts +61 -0
  362. package/src/util.ts +59 -0
  363. package/src/version.ts +2 -0
@@ -0,0 +1,1048 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hullproof.invalid/findings.schema.json",
4
+ "title": "Hullproof findings record",
5
+ "description": "The JSON object inside the hullproof-findings block of a <report>.findings.md file. This schema states field names, types and limits only. It cannot state the rules that connect fields (class and kind requirements, fingerprint order and prefix, verifier and lowering rules, report consistency, machine_evidence from schema_version 1.1.0, its evidence_kind and run fields from 1.2.0). validate-findings.mjs checks those.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "schema_version": {
10
+ "enum": [
11
+ "1.0.0",
12
+ "1.1.0",
13
+ "1.2.0"
14
+ ]
15
+ },
16
+ "report": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "commit": {
21
+ "type": "string",
22
+ "pattern": "^[0-9a-f]{40}$"
23
+ },
24
+ "tree": {
25
+ "type": "string",
26
+ "pattern": "^[0-9a-f]{40}$"
27
+ },
28
+ "tree_clean": {
29
+ "type": "boolean"
30
+ },
31
+ "stage": {
32
+ "enum": [
33
+ "LAUNCH",
34
+ "GROWTH",
35
+ "SCALE"
36
+ ]
37
+ },
38
+ "profile": {
39
+ "enum": [
40
+ "quick",
41
+ "standard",
42
+ "deep"
43
+ ]
44
+ },
45
+ "scope": {
46
+ "enum": [
47
+ "full",
48
+ "partial"
49
+ ]
50
+ },
51
+ "scope_note": {
52
+ "type": "string",
53
+ "minLength": 1,
54
+ "maxLength": 200
55
+ },
56
+ "run_status": {
57
+ "enum": [
58
+ "complete",
59
+ "incomplete"
60
+ ]
61
+ },
62
+ "incomplete_reason": {
63
+ "enum": [
64
+ "budget_exhausted",
65
+ "agent_failure",
66
+ "owner_stopped",
67
+ "deterministic_only",
68
+ "engine_hunt"
69
+ ]
70
+ },
71
+ "agent_calls": {
72
+ "type": "integer",
73
+ "minimum": 0
74
+ },
75
+ "budget": {
76
+ "type": [
77
+ "integer",
78
+ "null"
79
+ ],
80
+ "minimum": 1
81
+ }
82
+ },
83
+ "required": [
84
+ "commit",
85
+ "tree",
86
+ "tree_clean",
87
+ "stage",
88
+ "profile",
89
+ "scope",
90
+ "run_status",
91
+ "agent_calls",
92
+ "budget"
93
+ ]
94
+ },
95
+ "records": {
96
+ "type": "array",
97
+ "maxItems": 500,
98
+ "items": {
99
+ "oneOf": [
100
+ {
101
+ "type": "object",
102
+ "additionalProperties": false,
103
+ "properties": {
104
+ "fingerprint": {
105
+ "type": "string",
106
+ "pattern": "^(SEC-[A-Z]+-[0-9]{3}|GAP|OBS):(-|[^\\s:]+):[a-z0-9]+(-[a-z0-9]+){0,15}$"
107
+ },
108
+ "kind": {
109
+ "const": "fail"
110
+ },
111
+ "sec_ids": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string",
115
+ "pattern": "^SEC-[A-Z]+-[0-9]{3}$"
116
+ },
117
+ "minItems": 0,
118
+ "maxItems": 12
119
+ },
120
+ "title": {
121
+ "type": "string",
122
+ "minLength": 1,
123
+ "maxLength": 160
124
+ },
125
+ "class": {
126
+ "enum": [
127
+ "finding",
128
+ "missing_control",
129
+ "hardening_note"
130
+ ]
131
+ },
132
+ "gap_in_standard": {
133
+ "type": "boolean"
134
+ },
135
+ "severity": {
136
+ "enum": [
137
+ "BLOCKER",
138
+ "CRITICAL",
139
+ "HIGH",
140
+ "MEDIUM",
141
+ "LOW"
142
+ ]
143
+ },
144
+ "confidence": {
145
+ "enum": [
146
+ "VERIFIED",
147
+ "SUSPECTED"
148
+ ]
149
+ },
150
+ "demonstrated": {
151
+ "type": "boolean"
152
+ },
153
+ "root_cause": {
154
+ "type": "string",
155
+ "minLength": 1,
156
+ "maxLength": 120
157
+ },
158
+ "raised_by": {
159
+ "type": "array",
160
+ "items": {
161
+ "type": "string",
162
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9 .:_/-]{0,60}$",
163
+ "maxLength": 61
164
+ },
165
+ "minItems": 1,
166
+ "maxItems": 6
167
+ },
168
+ "impact_statement": {
169
+ "type": "string",
170
+ "minLength": 1,
171
+ "maxLength": 600
172
+ },
173
+ "remediation": {
174
+ "type": "object",
175
+ "additionalProperties": false,
176
+ "properties": {
177
+ "strategy": {
178
+ "type": "string",
179
+ "minLength": 1,
180
+ "maxLength": 800
181
+ },
182
+ "confirm": {
183
+ "type": "string",
184
+ "minLength": 1,
185
+ "maxLength": 400
186
+ }
187
+ },
188
+ "required": [
189
+ "strategy",
190
+ "confirm"
191
+ ]
192
+ },
193
+ "evidence": {
194
+ "type": "array",
195
+ "items": {
196
+ "type": "object",
197
+ "additionalProperties": false,
198
+ "properties": {
199
+ "file": {
200
+ "type": "string",
201
+ "minLength": 1,
202
+ "maxLength": 300,
203
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
204
+ },
205
+ "line": {
206
+ "type": "integer",
207
+ "minimum": 1,
208
+ "maximum": 10000000
209
+ },
210
+ "note": {
211
+ "type": "string",
212
+ "minLength": 1,
213
+ "maxLength": 300
214
+ }
215
+ },
216
+ "required": [
217
+ "file",
218
+ "line",
219
+ "note"
220
+ ]
221
+ },
222
+ "minItems": 1,
223
+ "maxItems": 8
224
+ },
225
+ "boundary": {
226
+ "type": "object",
227
+ "additionalProperties": false,
228
+ "properties": {
229
+ "principal": {
230
+ "type": "string",
231
+ "minLength": 1,
232
+ "maxLength": 400
233
+ },
234
+ "input": {
235
+ "type": "string",
236
+ "minLength": 1,
237
+ "maxLength": 400
238
+ },
239
+ "intended_control": {
240
+ "type": "string",
241
+ "minLength": 1,
242
+ "maxLength": 400
243
+ },
244
+ "crossed": {
245
+ "type": "string",
246
+ "minLength": 1,
247
+ "maxLength": 400
248
+ },
249
+ "affected": {
250
+ "type": "string",
251
+ "minLength": 1,
252
+ "maxLength": 400
253
+ },
254
+ "result": {
255
+ "type": "string",
256
+ "minLength": 1,
257
+ "maxLength": 400
258
+ }
259
+ },
260
+ "required": [
261
+ "principal",
262
+ "input",
263
+ "intended_control",
264
+ "crossed",
265
+ "affected",
266
+ "result"
267
+ ]
268
+ },
269
+ "trace": {
270
+ "type": "array",
271
+ "items": {
272
+ "type": "object",
273
+ "additionalProperties": false,
274
+ "properties": {
275
+ "kind": {
276
+ "enum": [
277
+ "entrypoint",
278
+ "handoff",
279
+ "sink"
280
+ ]
281
+ },
282
+ "file": {
283
+ "type": "string",
284
+ "minLength": 1,
285
+ "maxLength": 300,
286
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
287
+ },
288
+ "line": {
289
+ "type": "integer",
290
+ "minimum": 1,
291
+ "maximum": 10000000
292
+ },
293
+ "note": {
294
+ "type": "string",
295
+ "minLength": 1,
296
+ "maxLength": 300
297
+ }
298
+ },
299
+ "required": [
300
+ "kind",
301
+ "file",
302
+ "line",
303
+ "note"
304
+ ]
305
+ },
306
+ "minItems": 1,
307
+ "maxItems": 12
308
+ },
309
+ "absence_search": {
310
+ "type": "object",
311
+ "additionalProperties": false,
312
+ "properties": {
313
+ "command": {
314
+ "type": "string",
315
+ "minLength": 1,
316
+ "maxLength": 300
317
+ },
318
+ "files_searched": {
319
+ "type": "integer",
320
+ "minimum": 0
321
+ },
322
+ "count": {
323
+ "type": "integer",
324
+ "minimum": 0
325
+ },
326
+ "practice": {
327
+ "enum": [
328
+ "absent",
329
+ "present_unsafe"
330
+ ]
331
+ }
332
+ },
333
+ "required": [
334
+ "command",
335
+ "files_searched",
336
+ "count",
337
+ "practice"
338
+ ]
339
+ },
340
+ "preventing_layer": {
341
+ "type": "array",
342
+ "items": {
343
+ "type": "object",
344
+ "additionalProperties": false,
345
+ "properties": {
346
+ "file": {
347
+ "type": "string",
348
+ "minLength": 1,
349
+ "maxLength": 300,
350
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
351
+ },
352
+ "line": {
353
+ "type": "integer",
354
+ "minimum": 1,
355
+ "maximum": 10000000
356
+ },
357
+ "note": {
358
+ "type": "string",
359
+ "minLength": 1,
360
+ "maxLength": 300
361
+ }
362
+ },
363
+ "required": [
364
+ "file",
365
+ "line",
366
+ "note"
367
+ ]
368
+ },
369
+ "minItems": 1,
370
+ "maxItems": 6
371
+ },
372
+ "paths_enumerated": {
373
+ "type": "object",
374
+ "additionalProperties": false,
375
+ "properties": {
376
+ "count": {
377
+ "type": "integer",
378
+ "minimum": 1
379
+ },
380
+ "method": {
381
+ "type": "string",
382
+ "minLength": 1,
383
+ "maxLength": 400
384
+ }
385
+ },
386
+ "required": [
387
+ "count",
388
+ "method"
389
+ ]
390
+ },
391
+ "expiry_condition": {
392
+ "type": "string",
393
+ "minLength": 1,
394
+ "maxLength": 300
395
+ },
396
+ "owner_evidence": {
397
+ "type": "array",
398
+ "items": {
399
+ "type": "object",
400
+ "additionalProperties": false,
401
+ "properties": {
402
+ "file": {
403
+ "type": "string",
404
+ "minLength": 1,
405
+ "maxLength": 300,
406
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
407
+ },
408
+ "hash": {
409
+ "type": "string",
410
+ "pattern": "^([0-9a-f]{40}|[0-9a-f]{64})$"
411
+ },
412
+ "hash_kind": {
413
+ "enum": [
414
+ "git_blob",
415
+ "sha256"
416
+ ]
417
+ },
418
+ "date": {
419
+ "type": "string",
420
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
421
+ },
422
+ "commit": {
423
+ "type": "string",
424
+ "pattern": "^[0-9a-f]{40}$"
425
+ },
426
+ "note": {
427
+ "type": "string",
428
+ "minLength": 1,
429
+ "maxLength": 300
430
+ }
431
+ },
432
+ "required": [
433
+ "file",
434
+ "hash",
435
+ "hash_kind",
436
+ "date",
437
+ "commit",
438
+ "note"
439
+ ]
440
+ },
441
+ "minItems": 0,
442
+ "maxItems": 6
443
+ },
444
+ "lowering": {
445
+ "type": "object",
446
+ "additionalProperties": false,
447
+ "properties": {
448
+ "from": {
449
+ "enum": [
450
+ "BLOCKER",
451
+ "CRITICAL",
452
+ "HIGH",
453
+ "MEDIUM",
454
+ "LOW"
455
+ ]
456
+ },
457
+ "to": {
458
+ "enum": [
459
+ "BLOCKER",
460
+ "CRITICAL",
461
+ "HIGH",
462
+ "MEDIUM",
463
+ "LOW"
464
+ ]
465
+ },
466
+ "evidence": {
467
+ "type": "array",
468
+ "items": {
469
+ "type": "object",
470
+ "additionalProperties": false,
471
+ "properties": {
472
+ "file": {
473
+ "type": "string",
474
+ "minLength": 1,
475
+ "maxLength": 300,
476
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
477
+ },
478
+ "line": {
479
+ "type": "integer",
480
+ "minimum": 1,
481
+ "maximum": 10000000
482
+ },
483
+ "note": {
484
+ "type": "string",
485
+ "minLength": 1,
486
+ "maxLength": 300
487
+ }
488
+ },
489
+ "required": [
490
+ "file",
491
+ "line",
492
+ "note"
493
+ ]
494
+ },
495
+ "minItems": 1,
496
+ "maxItems": 4
497
+ },
498
+ "reviewer": {
499
+ "type": "object",
500
+ "additionalProperties": false,
501
+ "properties": {
502
+ "type": {
503
+ "enum": [
504
+ "person",
505
+ "agent_session",
506
+ "PENDING"
507
+ ]
508
+ },
509
+ "name": {
510
+ "type": "string",
511
+ "minLength": 1,
512
+ "maxLength": 60
513
+ },
514
+ "date": {
515
+ "type": "string",
516
+ "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
517
+ }
518
+ },
519
+ "required": [
520
+ "type"
521
+ ]
522
+ }
523
+ },
524
+ "required": [
525
+ "from",
526
+ "to",
527
+ "evidence",
528
+ "reviewer"
529
+ ]
530
+ },
531
+ "verified_by": {
532
+ "type": "object",
533
+ "additionalProperties": false,
534
+ "properties": {
535
+ "agent": {
536
+ "const": "hullproof-finding-verifier"
537
+ },
538
+ "mode": {
539
+ "const": "finding"
540
+ },
541
+ "outcome": {
542
+ "enum": [
543
+ "UPHELD",
544
+ "ADJUSTED",
545
+ "INSUFFICIENT"
546
+ ]
547
+ },
548
+ "own_severity": {
549
+ "enum": [
550
+ "BLOCKER",
551
+ "CRITICAL",
552
+ "HIGH",
553
+ "MEDIUM",
554
+ "LOW"
555
+ ]
556
+ },
557
+ "own_class": {
558
+ "enum": [
559
+ "finding",
560
+ "missing_control",
561
+ "hardening_note"
562
+ ]
563
+ },
564
+ "call": {
565
+ "type": "integer",
566
+ "minimum": 1
567
+ }
568
+ },
569
+ "required": [
570
+ "agent",
571
+ "mode",
572
+ "outcome",
573
+ "own_severity",
574
+ "own_class"
575
+ ]
576
+ },
577
+ "machine_evidence": {
578
+ "type": "object",
579
+ "additionalProperties": false,
580
+ "properties": {
581
+ "tool": {
582
+ "type": "string",
583
+ "pattern": "^[a-z][a-z0-9._-]{0,39}$",
584
+ "maxLength": 40
585
+ },
586
+ "rule_id": {
587
+ "type": "string",
588
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:/@+-]{0,199}$",
589
+ "maxLength": 200
590
+ },
591
+ "tool_version": {
592
+ "type": "string",
593
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]{0,59}$",
594
+ "maxLength": 60
595
+ },
596
+ "config_sha256": {
597
+ "type": [
598
+ "string",
599
+ "null"
600
+ ],
601
+ "pattern": "^[0-9a-f]{64}$",
602
+ "maxLength": 64
603
+ },
604
+ "evidence_kind": {
605
+ "enum": [
606
+ "scanner_rule",
607
+ "engine_check",
608
+ "hunt_confirmed",
609
+ "sandbox_test"
610
+ ]
611
+ },
612
+ "runs": {
613
+ "type": "integer",
614
+ "minimum": 1,
615
+ "maximum": 20
616
+ },
617
+ "runs_proven": {
618
+ "type": "integer",
619
+ "minimum": 0,
620
+ "maximum": 20
621
+ }
622
+ },
623
+ "required": [
624
+ "tool",
625
+ "rule_id",
626
+ "tool_version",
627
+ "config_sha256"
628
+ ]
629
+ }
630
+ },
631
+ "required": [
632
+ "fingerprint",
633
+ "kind",
634
+ "sec_ids",
635
+ "title",
636
+ "class",
637
+ "gap_in_standard",
638
+ "severity",
639
+ "confidence",
640
+ "demonstrated",
641
+ "root_cause",
642
+ "raised_by",
643
+ "impact_statement",
644
+ "remediation",
645
+ "evidence"
646
+ ]
647
+ },
648
+ {
649
+ "type": "object",
650
+ "additionalProperties": false,
651
+ "properties": {
652
+ "fingerprint": {
653
+ "type": "string",
654
+ "pattern": "^(SEC-[A-Z]+-[0-9]{3}|GAP|OBS):(-|[^\\s:]+):[a-z0-9]+(-[a-z0-9]+){0,15}$"
655
+ },
656
+ "kind": {
657
+ "const": "routed"
658
+ },
659
+ "sec_ids": {
660
+ "type": "array",
661
+ "items": {
662
+ "type": "string",
663
+ "pattern": "^SEC-[A-Z]+-[0-9]{3}$"
664
+ },
665
+ "minItems": 0,
666
+ "maxItems": 12
667
+ },
668
+ "title": {
669
+ "type": "string",
670
+ "minLength": 1,
671
+ "maxLength": 160
672
+ },
673
+ "state": {
674
+ "enum": [
675
+ "NEEDS DASHBOARD",
676
+ "NEEDS BUILD",
677
+ "NEEDS DYNAMIC TEST",
678
+ "ASK OWNER",
679
+ "ATTESTATION",
680
+ "UNKNOWN"
681
+ ]
682
+ },
683
+ "reason": {
684
+ "type": "string",
685
+ "minLength": 1,
686
+ "maxLength": 500
687
+ },
688
+ "owner_action": {
689
+ "type": "string",
690
+ "minLength": 1,
691
+ "maxLength": 500
692
+ },
693
+ "check_card": {
694
+ "type": [
695
+ "string",
696
+ "null"
697
+ ],
698
+ "pattern": "^CC-[A-Z]+-[0-9]+$",
699
+ "maxLength": 40
700
+ },
701
+ "raised_by": {
702
+ "type": "array",
703
+ "items": {
704
+ "type": "string",
705
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9 .:_/-]{0,60}$",
706
+ "maxLength": 61
707
+ },
708
+ "minItems": 1,
709
+ "maxItems": 6
710
+ },
711
+ "boundary": {
712
+ "type": "object",
713
+ "additionalProperties": false,
714
+ "properties": {
715
+ "principal": {
716
+ "type": "string",
717
+ "minLength": 1,
718
+ "maxLength": 400
719
+ },
720
+ "input": {
721
+ "type": "string",
722
+ "minLength": 1,
723
+ "maxLength": 400
724
+ },
725
+ "intended_control": {
726
+ "type": "string",
727
+ "minLength": 1,
728
+ "maxLength": 400
729
+ },
730
+ "crossed": {
731
+ "type": "string",
732
+ "minLength": 1,
733
+ "maxLength": 400
734
+ },
735
+ "affected": {
736
+ "type": "string",
737
+ "minLength": 1,
738
+ "maxLength": 400
739
+ },
740
+ "result": {
741
+ "type": "string",
742
+ "minLength": 1,
743
+ "maxLength": 400
744
+ }
745
+ },
746
+ "required": [
747
+ "principal",
748
+ "input",
749
+ "intended_control",
750
+ "crossed",
751
+ "affected",
752
+ "result"
753
+ ]
754
+ },
755
+ "trace": {
756
+ "type": "array",
757
+ "items": {
758
+ "type": "object",
759
+ "additionalProperties": false,
760
+ "properties": {
761
+ "kind": {
762
+ "enum": [
763
+ "entrypoint",
764
+ "handoff",
765
+ "sink"
766
+ ]
767
+ },
768
+ "file": {
769
+ "type": "string",
770
+ "minLength": 1,
771
+ "maxLength": 300,
772
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
773
+ },
774
+ "line": {
775
+ "type": "integer",
776
+ "minimum": 1,
777
+ "maximum": 10000000
778
+ },
779
+ "note": {
780
+ "type": "string",
781
+ "minLength": 1,
782
+ "maxLength": 300
783
+ }
784
+ },
785
+ "required": [
786
+ "kind",
787
+ "file",
788
+ "line",
789
+ "note"
790
+ ]
791
+ },
792
+ "minItems": 1,
793
+ "maxItems": 12
794
+ },
795
+ "verified_by": {
796
+ "type": "object",
797
+ "additionalProperties": false,
798
+ "properties": {
799
+ "agent": {
800
+ "const": "hullproof-finding-verifier"
801
+ },
802
+ "mode": {
803
+ "const": "handoff"
804
+ },
805
+ "outcome": {
806
+ "enum": [
807
+ "UPHELD",
808
+ "ADJUSTED",
809
+ "INSUFFICIENT"
810
+ ]
811
+ },
812
+ "call": {
813
+ "type": "integer",
814
+ "minimum": 1
815
+ }
816
+ },
817
+ "required": [
818
+ "agent",
819
+ "mode",
820
+ "outcome",
821
+ "call"
822
+ ]
823
+ }
824
+ },
825
+ "required": [
826
+ "fingerprint",
827
+ "kind",
828
+ "sec_ids",
829
+ "title",
830
+ "state",
831
+ "reason",
832
+ "owner_action",
833
+ "check_card",
834
+ "raised_by",
835
+ "boundary"
836
+ ]
837
+ },
838
+ {
839
+ "type": "object",
840
+ "additionalProperties": false,
841
+ "properties": {
842
+ "fingerprint": {
843
+ "type": "string",
844
+ "pattern": "^(SEC-[A-Z]+-[0-9]{3}|GAP|OBS):(-|[^\\s:]+):[a-z0-9]+(-[a-z0-9]+){0,15}$"
845
+ },
846
+ "kind": {
847
+ "const": "refuted"
848
+ },
849
+ "sec_ids": {
850
+ "type": "array",
851
+ "items": {
852
+ "type": "string",
853
+ "pattern": "^SEC-[A-Z]+-[0-9]{3}$"
854
+ },
855
+ "minItems": 0,
856
+ "maxItems": 12
857
+ },
858
+ "title": {
859
+ "type": "string",
860
+ "minLength": 1,
861
+ "maxLength": 160
862
+ },
863
+ "claim": {
864
+ "type": "string",
865
+ "minLength": 1,
866
+ "maxLength": 300
867
+ },
868
+ "reason": {
869
+ "type": "string",
870
+ "minLength": 1,
871
+ "maxLength": 500
872
+ },
873
+ "preventing_layer": {
874
+ "type": "array",
875
+ "items": {
876
+ "type": "object",
877
+ "additionalProperties": false,
878
+ "properties": {
879
+ "file": {
880
+ "type": "string",
881
+ "minLength": 1,
882
+ "maxLength": 300,
883
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
884
+ },
885
+ "line": {
886
+ "type": "integer",
887
+ "minimum": 1,
888
+ "maximum": 10000000
889
+ },
890
+ "note": {
891
+ "type": "string",
892
+ "minLength": 1,
893
+ "maxLength": 300
894
+ }
895
+ },
896
+ "required": [
897
+ "file",
898
+ "line",
899
+ "note"
900
+ ]
901
+ },
902
+ "minItems": 1,
903
+ "maxItems": 6
904
+ },
905
+ "raised_by": {
906
+ "type": "array",
907
+ "items": {
908
+ "type": "string",
909
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9 .:_/-]{0,60}$",
910
+ "maxLength": 61
911
+ },
912
+ "minItems": 1,
913
+ "maxItems": 6
914
+ },
915
+ "verified_by": {
916
+ "type": "object",
917
+ "additionalProperties": false,
918
+ "properties": {
919
+ "agent": {
920
+ "const": "hullproof-finding-verifier"
921
+ },
922
+ "mode": {
923
+ "enum": [
924
+ "finding",
925
+ "handoff"
926
+ ]
927
+ },
928
+ "outcome": {
929
+ "const": "REFUTED"
930
+ },
931
+ "call": {
932
+ "type": "integer",
933
+ "minimum": 1
934
+ }
935
+ },
936
+ "required": [
937
+ "agent",
938
+ "mode",
939
+ "outcome",
940
+ "call"
941
+ ]
942
+ }
943
+ },
944
+ "required": [
945
+ "fingerprint",
946
+ "kind",
947
+ "sec_ids",
948
+ "title",
949
+ "claim",
950
+ "reason",
951
+ "preventing_layer",
952
+ "raised_by",
953
+ "verified_by"
954
+ ]
955
+ },
956
+ {
957
+ "type": "object",
958
+ "additionalProperties": false,
959
+ "properties": {
960
+ "fingerprint": {
961
+ "type": "string",
962
+ "pattern": "^(SEC-[A-Z]+-[0-9]{3}|GAP|OBS):(-|[^\\s:]+):[a-z0-9]+(-[a-z0-9]+){0,15}$"
963
+ },
964
+ "kind": {
965
+ "const": "observation"
966
+ },
967
+ "sec_ids": {
968
+ "type": "array",
969
+ "items": {
970
+ "type": "string",
971
+ "pattern": "^SEC-[A-Z]+-[0-9]{3}$"
972
+ },
973
+ "minItems": 0,
974
+ "maxItems": 12
975
+ },
976
+ "title": {
977
+ "type": "string",
978
+ "minLength": 1,
979
+ "maxLength": 160
980
+ },
981
+ "where": {
982
+ "type": "array",
983
+ "items": {
984
+ "type": "object",
985
+ "additionalProperties": false,
986
+ "properties": {
987
+ "file": {
988
+ "type": "string",
989
+ "minLength": 1,
990
+ "maxLength": 300,
991
+ "description": "repository relative path, no leading slash, no .. segment, no backslash, colon or ~"
992
+ },
993
+ "line": {
994
+ "type": "integer",
995
+ "minimum": 1,
996
+ "maximum": 10000000
997
+ },
998
+ "note": {
999
+ "type": "string",
1000
+ "minLength": 1,
1001
+ "maxLength": 300
1002
+ }
1003
+ },
1004
+ "required": [
1005
+ "file",
1006
+ "line",
1007
+ "note"
1008
+ ]
1009
+ },
1010
+ "minItems": 1,
1011
+ "maxItems": 4
1012
+ },
1013
+ "note": {
1014
+ "type": "string",
1015
+ "minLength": 1,
1016
+ "maxLength": 400
1017
+ },
1018
+ "raised_by": {
1019
+ "type": "array",
1020
+ "items": {
1021
+ "type": "string",
1022
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9 .:_/-]{0,60}$",
1023
+ "maxLength": 61
1024
+ },
1025
+ "minItems": 1,
1026
+ "maxItems": 6
1027
+ }
1028
+ },
1029
+ "required": [
1030
+ "fingerprint",
1031
+ "kind",
1032
+ "sec_ids",
1033
+ "title",
1034
+ "where",
1035
+ "note",
1036
+ "raised_by"
1037
+ ]
1038
+ }
1039
+ ]
1040
+ }
1041
+ }
1042
+ },
1043
+ "required": [
1044
+ "schema_version",
1045
+ "report",
1046
+ "records"
1047
+ ]
1048
+ }