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,427 @@
1
+ {
2
+ "min_judged": 3,
3
+ "rules": {
4
+ "check.map.data-read-without-auth": {
5
+ "date": "2026-10-11",
6
+ "evidence": "Juice Shop 0e6d909 and BenchmarkPython f129148, hand checked samples of 20 findings each, seed 20261011, engine a3035af; see bench/PHASE2-MEASURED-2026-10-11.md",
7
+ "judged": 3,
8
+ "precision": 0,
9
+ "tier": "lead"
10
+ },
11
+ "check.map.mutating-route-without-auth": {
12
+ "date": "2026-10-11",
13
+ "evidence": "Juice Shop 0e6d909 and BenchmarkPython f129148, hand checked samples of 20 findings each, seed 20261011, engine a3035af; see bench/PHASE2-MEASURED-2026-10-11.md",
14
+ "judged": 27,
15
+ "precision": 0.44,
16
+ "tier": "lead"
17
+ },
18
+ "check.map.privileged-field-from-request": {
19
+ "date": "2026-10-11",
20
+ "evidence": "Juice Shop 0e6d909 and BenchmarkPython f129148, hand checked samples of 20 findings each, seed 20261011, engine a3035af; see bench/PHASE2-MEASURED-2026-10-11.md",
21
+ "judged": 1,
22
+ "precision": 0,
23
+ "tier": "lead"
24
+ },
25
+ "check.map.read-by-id-without-owner": {
26
+ "date": "2026-10-14",
27
+ "evidence": "hand judged against the route chain: OWASP RailsGoat f5951f1 (6 places, all true), Juice Shop (1 true), hullproof-demo F04 (1 true), WebGoat (1 not the flaw); BenchmarkPython and the other nine real apps had no hit; see bench/PHASE6C-MEASURED-2026-10-14.md",
28
+ "judged": 9,
29
+ "needs_judged": 20,
30
+ "precision": 0.89,
31
+ "tier": "lead"
32
+ },
33
+ "check.map.write-by-id-without-owner": {
34
+ "date": "2026-10-11",
35
+ "evidence": "Juice Shop 0e6d909 and BenchmarkPython f129148, hand checked samples of 20 findings each, seed 20261011, engine a3035af; see bench/PHASE2-MEASURED-2026-10-11.md",
36
+ "judged": 1,
37
+ "precision": 0,
38
+ "tier": "lead"
39
+ },
40
+ "hullproof-api-route-no-auth": {
41
+ "date": null,
42
+ "evidence": "not measured yet",
43
+ "judged": 0,
44
+ "precision": null,
45
+ "tier": "gate"
46
+ },
47
+ "hullproof-cors-origin-true": {
48
+ "date": null,
49
+ "evidence": "not measured yet",
50
+ "judged": 0,
51
+ "precision": null,
52
+ "tier": "gate"
53
+ },
54
+ "hullproof-cors-reflect-origin": {
55
+ "date": null,
56
+ "evidence": "not measured yet",
57
+ "judged": 0,
58
+ "precision": null,
59
+ "tier": "gate"
60
+ },
61
+ "hullproof-dynamic-module-path": {
62
+ "date": null,
63
+ "evidence": "not measured yet",
64
+ "judged": 0,
65
+ "precision": null,
66
+ "tier": "gate"
67
+ },
68
+ "hullproof-eval-or-new-function": {
69
+ "date": "2026-10-10",
70
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
71
+ "judged": 1,
72
+ "precision": 0,
73
+ "tier": "gate"
74
+ },
75
+ "hullproof-eval-through-alias": {
76
+ "date": null,
77
+ "evidence": "not measured yet",
78
+ "judged": 0,
79
+ "precision": null,
80
+ "tier": "gate"
81
+ },
82
+ "hullproof-expression-library-eval": {
83
+ "date": null,
84
+ "evidence": "not measured yet",
85
+ "judged": 0,
86
+ "precision": null,
87
+ "tier": "gate"
88
+ },
89
+ "hullproof-log-session-token": {
90
+ "date": "2026-10-10",
91
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
92
+ "judged": 2,
93
+ "precision": 0,
94
+ "tier": "gate"
95
+ },
96
+ "hullproof-math-random-token": {
97
+ "date": null,
98
+ "evidence": "not measured yet",
99
+ "judged": 0,
100
+ "precision": null,
101
+ "tier": "gate"
102
+ },
103
+ "hullproof-next-public-secret-name": {
104
+ "date": null,
105
+ "evidence": "not measured yet",
106
+ "judged": 0,
107
+ "precision": null,
108
+ "tier": "gate"
109
+ },
110
+ "hullproof-postgrest-filter-string": {
111
+ "date": null,
112
+ "evidence": "not measured yet",
113
+ "judged": 0,
114
+ "precision": null,
115
+ "tier": "gate"
116
+ },
117
+ "hullproof-postgrest-interpolated-filter": {
118
+ "date": null,
119
+ "evidence": "not measured yet",
120
+ "judged": 0,
121
+ "precision": null,
122
+ "tier": "gate"
123
+ },
124
+ "hullproof-raw-sql-concat": {
125
+ "date": "2026-10-10",
126
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
127
+ "judged": 2,
128
+ "precision": 1,
129
+ "tier": "gate"
130
+ },
131
+ "hullproof-read-by-id-no-owner": {
132
+ "date": null,
133
+ "evidence": "not measured yet",
134
+ "judged": 0,
135
+ "precision": null,
136
+ "tier": "gate"
137
+ },
138
+ "hullproof-server-action-no-auth": {
139
+ "date": null,
140
+ "evidence": "not measured yet",
141
+ "judged": 0,
142
+ "precision": null,
143
+ "tier": "gate"
144
+ },
145
+ "hullproof-sql-built-string-reaches-query": {
146
+ "date": "2026-10-10",
147
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
148
+ "judged": 4,
149
+ "precision": 1,
150
+ "tier": "gate"
151
+ },
152
+ "hullproof-sql-raw-non-literal": {
153
+ "date": null,
154
+ "evidence": "not measured yet",
155
+ "judged": 0,
156
+ "precision": null,
157
+ "tier": "gate"
158
+ },
159
+ "hullproof-sql-string-built-in-variable": {
160
+ "date": "2026-10-10",
161
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
162
+ "judged": 4,
163
+ "precision": 1,
164
+ "tier": "gate"
165
+ },
166
+ "hullproof-sql-tagged-template-misuse": {
167
+ "date": null,
168
+ "evidence": "not measured yet",
169
+ "judged": 0,
170
+ "precision": null,
171
+ "tier": "gate"
172
+ },
173
+ "hullproof-ssrf-request-data-to-url": {
174
+ "date": "2026-10-10",
175
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
176
+ "judged": 1,
177
+ "precision": 1,
178
+ "tier": "gate"
179
+ },
180
+ "hullproof-ssrf-stored-url": {
181
+ "date": null,
182
+ "evidence": "not measured yet",
183
+ "judged": 0,
184
+ "precision": null,
185
+ "tier": "gate"
186
+ },
187
+ "hullproof-ssrf-url-built-from-base": {
188
+ "date": null,
189
+ "evidence": "not measured yet",
190
+ "judged": 0,
191
+ "precision": null,
192
+ "tier": "gate"
193
+ },
194
+ "hullproof-subprocess-arg-no-separator": {
195
+ "date": null,
196
+ "evidence": "not measured yet",
197
+ "judged": 0,
198
+ "precision": null,
199
+ "tier": "gate"
200
+ },
201
+ "hullproof-subprocess-request-data": {
202
+ "date": null,
203
+ "evidence": "not measured yet",
204
+ "judged": 0,
205
+ "precision": null,
206
+ "tier": "gate"
207
+ },
208
+ "hullproof-subprocess-shell-interpreter": {
209
+ "date": null,
210
+ "evidence": "not measured yet",
211
+ "judged": 0,
212
+ "precision": null,
213
+ "tier": "gate"
214
+ },
215
+ "hullproof-subprocess-shell-string": {
216
+ "date": null,
217
+ "evidence": "not measured yet",
218
+ "judged": 0,
219
+ "precision": null,
220
+ "tier": "gate"
221
+ },
222
+ "hullproof-taint-go-command-injection": {
223
+ "date": null,
224
+ "evidence": "not measured yet",
225
+ "judged": 0,
226
+ "precision": null,
227
+ "tier": "lead"
228
+ },
229
+ "hullproof-taint-go-path-traversal": {
230
+ "date": null,
231
+ "evidence": "not measured yet",
232
+ "judged": 0,
233
+ "precision": null,
234
+ "tier": "lead"
235
+ },
236
+ "hullproof-taint-go-sql-injection": {
237
+ "date": null,
238
+ "evidence": "not measured yet",
239
+ "judged": 0,
240
+ "precision": null,
241
+ "tier": "lead"
242
+ },
243
+ "hullproof-taint-go-ssrf": {
244
+ "date": null,
245
+ "evidence": "not measured yet",
246
+ "judged": 0,
247
+ "precision": null,
248
+ "tier": "lead"
249
+ },
250
+ "hullproof-taint-go-xss": {
251
+ "date": null,
252
+ "evidence": "not measured yet",
253
+ "judged": 0,
254
+ "precision": null,
255
+ "tier": "lead"
256
+ },
257
+ "hullproof-taint-java-command-injection": {
258
+ "date": null,
259
+ "evidence": "not measured yet",
260
+ "judged": 0,
261
+ "precision": null,
262
+ "tier": "lead"
263
+ },
264
+ "hullproof-taint-java-path-traversal": {
265
+ "date": null,
266
+ "evidence": "not measured yet",
267
+ "judged": 0,
268
+ "precision": null,
269
+ "tier": "lead"
270
+ },
271
+ "hullproof-taint-java-sql-injection": {
272
+ "date": null,
273
+ "evidence": "not measured yet",
274
+ "judged": 0,
275
+ "precision": null,
276
+ "tier": "lead"
277
+ },
278
+ "hullproof-taint-java-ssrf": {
279
+ "date": null,
280
+ "evidence": "not measured yet",
281
+ "judged": 0,
282
+ "precision": null,
283
+ "tier": "lead"
284
+ },
285
+ "hullproof-taint-java-xss": {
286
+ "date": null,
287
+ "evidence": "not measured yet",
288
+ "judged": 0,
289
+ "precision": null,
290
+ "tier": "lead"
291
+ },
292
+ "hullproof-taint-js-command-injection": {
293
+ "date": null,
294
+ "evidence": "not measured yet",
295
+ "judged": 0,
296
+ "precision": null,
297
+ "tier": "lead"
298
+ },
299
+ "hullproof-taint-js-path-traversal": {
300
+ "date": "2026-10-10",
301
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
302
+ "judged": 3,
303
+ "precision": 0,
304
+ "tier": "lead"
305
+ },
306
+ "hullproof-taint-js-sql-injection": {
307
+ "date": "2026-10-10",
308
+ "evidence": "Juice Shop 0e6d909, hand checked records in shipped code, pro run samples with seeds 20261010 and 20261011 (before and after)",
309
+ "judged": 2,
310
+ "precision": 1,
311
+ "tier": "lead"
312
+ },
313
+ "hullproof-taint-js-ssrf": {
314
+ "date": null,
315
+ "evidence": "not measured yet",
316
+ "judged": 0,
317
+ "precision": null,
318
+ "tier": "lead"
319
+ },
320
+ "hullproof-taint-js-xss": {
321
+ "date": null,
322
+ "evidence": "not measured yet",
323
+ "judged": 0,
324
+ "precision": null,
325
+ "tier": "lead"
326
+ },
327
+ "hullproof-taint-php-command-injection": {
328
+ "date": null,
329
+ "evidence": "not measured yet",
330
+ "judged": 0,
331
+ "precision": null,
332
+ "tier": "lead"
333
+ },
334
+ "hullproof-taint-php-path-traversal": {
335
+ "date": null,
336
+ "evidence": "not measured yet",
337
+ "judged": 0,
338
+ "precision": null,
339
+ "tier": "lead"
340
+ },
341
+ "hullproof-taint-php-sql-injection": {
342
+ "date": null,
343
+ "evidence": "not measured yet",
344
+ "judged": 0,
345
+ "precision": null,
346
+ "tier": "lead"
347
+ },
348
+ "hullproof-taint-php-ssrf": {
349
+ "date": null,
350
+ "evidence": "not measured yet",
351
+ "judged": 0,
352
+ "precision": null,
353
+ "tier": "lead"
354
+ },
355
+ "hullproof-taint-php-xss": {
356
+ "date": null,
357
+ "evidence": "not measured yet",
358
+ "judged": 0,
359
+ "precision": null,
360
+ "tier": "lead"
361
+ },
362
+ "hullproof-taint-py-command-injection": {
363
+ "date": "2026-10-10",
364
+ "evidence": "BenchmarkPython f129148, cases flagged in the rule's own category",
365
+ "judged": 7,
366
+ "precision": 0.71,
367
+ "tier": "lead"
368
+ },
369
+ "hullproof-taint-py-path-traversal": {
370
+ "date": "2026-10-10",
371
+ "evidence": "BenchmarkPython f129148, cases flagged in the rule's own category",
372
+ "judged": 53,
373
+ "precision": 0.43,
374
+ "tier": "lead"
375
+ },
376
+ "hullproof-taint-py-sql-injection": {
377
+ "date": "2026-10-10",
378
+ "evidence": "BenchmarkPython f129148, cases flagged in the rule's own category",
379
+ "judged": 2,
380
+ "precision": 1,
381
+ "tier": "lead"
382
+ },
383
+ "hullproof-taint-py-ssrf": {
384
+ "date": null,
385
+ "evidence": "not measured yet",
386
+ "judged": 0,
387
+ "precision": null,
388
+ "tier": "lead"
389
+ },
390
+ "hullproof-taint-py-xss": {
391
+ "date": "2026-10-10",
392
+ "evidence": "BenchmarkPython f129148, cases flagged in the rule's own category",
393
+ "judged": 37,
394
+ "precision": 0.38,
395
+ "tier": "lead"
396
+ },
397
+ "hullproof-tool-handler-admin-client-no-scope": {
398
+ "date": null,
399
+ "evidence": "not measured yet",
400
+ "judged": 0,
401
+ "precision": null,
402
+ "tier": "gate"
403
+ },
404
+ "hullproof-user-metadata-authz": {
405
+ "date": null,
406
+ "evidence": "not measured yet",
407
+ "judged": 0,
408
+ "precision": null,
409
+ "tier": "gate"
410
+ },
411
+ "hullproof-verify-result-unused": {
412
+ "date": null,
413
+ "evidence": "not measured yet",
414
+ "judged": 0,
415
+ "precision": null,
416
+ "tier": "gate"
417
+ },
418
+ "hullproof-webhook-parse-before-verify": {
419
+ "date": null,
420
+ "evidence": "not measured yet",
421
+ "judged": 0,
422
+ "precision": null,
423
+ "tier": "gate"
424
+ }
425
+ },
426
+ "threshold": 0.8
427
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hullproof.invalid/engine/check-results.schema.json",
4
+ "title": "Hullproof Engine executable check results (checks.json)",
5
+ "description": "Results sorted by check_id, evidence by file then line, not_run by check_id. No timestamp.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema_version", "commit", "results", "not_run"],
9
+ "properties": {
10
+ "schema_version": {"const": "1.0.0"},
11
+ "commit": {"type": ["string", "null"], "pattern": "^[0-9a-f]{40}$"},
12
+ "results": {
13
+ "type": "array",
14
+ "items": {
15
+ "type": "object", "additionalProperties": false,
16
+ "required": ["check_id", "sec_ids", "result", "evidence", "absence_search", "message_key"],
17
+ "properties": {
18
+ "check_id": {"type": "string", "pattern": "^check\\.[a-z0-9-]+\\.[a-z0-9-]+$"},
19
+ "sec_ids": {"type": "array", "minItems": 1, "items": {"type": "string", "pattern": "^SEC-[A-Z]+-[0-9]{3}$"}},
20
+ "result": {"type": "string", "pattern": "^(FAIL|PASS \\(static\\)|NOT APPLICABLE|NOT ASSESSED: (NEEDS DASHBOARD|NEEDS BUILD|NEEDS DYNAMIC TEST|ASK OWNER|ATTESTATION|UNKNOWN))$"},
21
+ "evidence": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "object", "additionalProperties": false, "required": ["file", "note"],
25
+ "properties": {
26
+ "file": {"type": "string", "minLength": 1, "maxLength": 300, "pattern": "^[^/\\\\]"},
27
+ "line": {"type": "integer", "minimum": 1},
28
+ "key": {"type": "string", "minLength": 1},
29
+ "note": {"type": "string", "minLength": 1, "maxLength": 300}
30
+ }
31
+ }
32
+ },
33
+ "absence_search": {
34
+ "type": ["object", "null"], "additionalProperties": false,
35
+ "required": ["pattern", "files_searched", "file_globs", "matches"],
36
+ "properties": {
37
+ "pattern": {"type": "string", "minLength": 1},
38
+ "files_searched": {"type": "integer", "minimum": 0},
39
+ "file_globs": {"type": "array", "items": {"type": "string", "minLength": 1}},
40
+ "matches": {"type": "integer", "minimum": 0}
41
+ }
42
+ },
43
+ "message_key": {"type": "string", "minLength": 1, "maxLength": 240}
44
+ }
45
+ }
46
+ },
47
+ "not_run": {
48
+ "type": "array",
49
+ "items": {
50
+ "type": "object", "additionalProperties": false, "required": ["check_id", "reason"],
51
+ "properties": {"check_id": {"type": "string", "minLength": 1}, "reason": {"type": "string", "minLength": 1}}
52
+ }
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hullproof.invalid/engine/check.schema.json",
4
+ "title": "Hullproof Engine executable check definition (checks/*.json)",
5
+ "description": "Data only, no code. One interpreter in the engine runs the op. Every check ships a pass fixture and a fail fixture.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["id", "sec_ids", "applies_when", "op", "on_true", "on_false", "fixtures"],
9
+ "oneOf": [
10
+ {"description": "A declarative check: one of the ten ops, with its params.", "required": ["params"], "properties": {"op": {"enum": ["file_exists", "file_exists_for_each", "file_absent", "regex_present", "regex_absent", "json_value", "sql_every_table_has", "workflow_uses_pinned_sha", "workflow_permissions", "version_in_table"]}}},
11
+ {"description": "A code check: op code, module names the TypeScript file in src/checks/code/ that holds run(). No params.", "required": ["module"], "properties": {"op": {"const": "code"}}}
12
+ ],
13
+ "properties": {
14
+ "id": {"type": "string", "pattern": "^check\\.[a-z0-9-]+\\.[a-z0-9-]+$"},
15
+ "sec_ids": {"type": "array", "minItems": 1, "items": {"type": "string", "pattern": "^SEC-[A-Z]+-[0-9]{3}$"}},
16
+ "applies_when": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "description": "Stack categories from stack.json. The check runs when every named category has an item whose id is listed, or any item when the value is \"*\". An empty object means always.",
20
+ "properties": {
21
+ "languages": {"$ref": "#/$defs/match"}, "runtimes": {"$ref": "#/$defs/match"}, "frameworks": {"$ref": "#/$defs/match"},
22
+ "package_managers": {"$ref": "#/$defs/match"}, "data_stores": {"$ref": "#/$defs/match"}, "auth": {"$ref": "#/$defs/match"},
23
+ "payments": {"$ref": "#/$defs/match"}, "ai": {"$ref": "#/$defs/match"}, "hosting": {"$ref": "#/$defs/match"},
24
+ "iac": {"$ref": "#/$defs/match"}, "containers": {"$ref": "#/$defs/match"}, "ci": {"$ref": "#/$defs/match"}, "mobile": {"$ref": "#/$defs/match"}
25
+ }
26
+ },
27
+ "op": {"enum": ["file_exists", "file_exists_for_each", "file_absent", "regex_present", "regex_absent", "json_value", "sql_every_table_has", "workflow_uses_pinned_sha", "workflow_permissions", "version_in_table", "code"]},
28
+ "params": {"type": "object"},
29
+ "module": {"type": "string", "pattern": "^src/checks/code/[a-z0-9-]+\\.ts$"},
30
+ "on_true": {"$ref": "#/$defs/result"},
31
+ "on_false": {"$ref": "#/$defs/result"},
32
+ "fixtures": {
33
+ "type": "object", "additionalProperties": false, "required": ["pass", "fail"],
34
+ "properties": {"pass": {"type": "string", "minLength": 1}, "fail": {"type": "string", "minLength": 1}}
35
+ }
36
+ },
37
+ "$defs": {
38
+ "match": {"oneOf": [{"const": "*"}, {"type": "array", "minItems": 1, "items": {"type": "string", "pattern": "^[a-z0-9][a-z0-9.-]*$"}}]},
39
+ "result": {"type": "string", "pattern": "^(FAIL|PASS \\(static\\)|NOT APPLICABLE|NOT ASSESSED: (NEEDS DASHBOARD|NEEDS BUILD|NEEDS DYNAMIC TEST|ASK OWNER|ATTESTATION|UNKNOWN))$"}
40
+ }
41
+ }