insa-check-core 0.1.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 (258) hide show
  1. package/LICENSE +24 -0
  2. package/dist/annex-b.d.ts +6 -0
  3. package/dist/annex-b.d.ts.map +1 -0
  4. package/dist/annex-b.js +152 -0
  5. package/dist/annex-b.js.map +1 -0
  6. package/dist/checks/content/page.d.ts +7 -0
  7. package/dist/checks/content/page.d.ts.map +1 -0
  8. package/dist/checks/content/page.js +133 -0
  9. package/dist/checks/content/page.js.map +1 -0
  10. package/dist/checks/cookies/cookie-flags.d.ts +3 -0
  11. package/dist/checks/cookies/cookie-flags.d.ts.map +1 -0
  12. package/dist/checks/cookies/cookie-flags.js +41 -0
  13. package/dist/checks/cookies/cookie-flags.js.map +1 -0
  14. package/dist/checks/cookies/cookie-scope.d.ts +6 -0
  15. package/dist/checks/cookies/cookie-scope.d.ts.map +1 -0
  16. package/dist/checks/cookies/cookie-scope.js +60 -0
  17. package/dist/checks/cookies/cookie-scope.js.map +1 -0
  18. package/dist/checks/deployment/server-banner.d.ts +4 -0
  19. package/dist/checks/deployment/server-banner.d.ts.map +1 -0
  20. package/dist/checks/deployment/server-banner.js +60 -0
  21. package/dist/checks/deployment/server-banner.js.map +1 -0
  22. package/dist/checks/deployment/trace.d.ts +3 -0
  23. package/dist/checks/deployment/trace.d.ts.map +1 -0
  24. package/dist/checks/deployment/trace.js +30 -0
  25. package/dist/checks/deployment/trace.js.map +1 -0
  26. package/dist/checks/headers/clickjacking.d.ts +5 -0
  27. package/dist/checks/headers/clickjacking.d.ts.map +1 -0
  28. package/dist/checks/headers/clickjacking.js +57 -0
  29. package/dist/checks/headers/clickjacking.js.map +1 -0
  30. package/dist/checks/headers/content-type-options.d.ts +3 -0
  31. package/dist/checks/headers/content-type-options.d.ts.map +1 -0
  32. package/dist/checks/headers/content-type-options.js +17 -0
  33. package/dist/checks/headers/content-type-options.js.map +1 -0
  34. package/dist/checks/headers/cors.d.ts +4 -0
  35. package/dist/checks/headers/cors.d.ts.map +1 -0
  36. package/dist/checks/headers/cors.js +38 -0
  37. package/dist/checks/headers/cors.js.map +1 -0
  38. package/dist/checks/html.d.ts +11 -0
  39. package/dist/checks/html.d.ts.map +1 -0
  40. package/dist/checks/html.js +30 -0
  41. package/dist/checks/html.js.map +1 -0
  42. package/dist/checks/index.d.ts +7 -0
  43. package/dist/checks/index.d.ts.map +1 -0
  44. package/dist/checks/index.js +48 -0
  45. package/dist/checks/index.js.map +1 -0
  46. package/dist/checks/info-disclosure/directory-listing.d.ts +6 -0
  47. package/dist/checks/info-disclosure/directory-listing.d.ts.map +1 -0
  48. package/dist/checks/info-disclosure/directory-listing.js +60 -0
  49. package/dist/checks/info-disclosure/directory-listing.js.map +1 -0
  50. package/dist/checks/info-disclosure/exposed-files.d.ts +4 -0
  51. package/dist/checks/info-disclosure/exposed-files.d.ts.map +1 -0
  52. package/dist/checks/info-disclosure/exposed-files.js +56 -0
  53. package/dist/checks/info-disclosure/exposed-files.js.map +1 -0
  54. package/dist/checks/info-disclosure/more.d.ts +8 -0
  55. package/dist/checks/info-disclosure/more.d.ts.map +1 -0
  56. package/dist/checks/info-disclosure/more.js +186 -0
  57. package/dist/checks/info-disclosure/more.js.map +1 -0
  58. package/dist/checks/tls/certificate.d.ts +3 -0
  59. package/dist/checks/tls/certificate.d.ts.map +1 -0
  60. package/dist/checks/tls/certificate.js +49 -0
  61. package/dist/checks/tls/certificate.js.map +1 -0
  62. package/dist/checks/tls/hsts.d.ts +5 -0
  63. package/dist/checks/tls/hsts.d.ts.map +1 -0
  64. package/dist/checks/tls/hsts.js +35 -0
  65. package/dist/checks/tls/hsts.js.map +1 -0
  66. package/dist/checks/tls/https-redirect.d.ts +3 -0
  67. package/dist/checks/tls/https-redirect.d.ts.map +1 -0
  68. package/dist/checks/tls/https-redirect.js +46 -0
  69. package/dist/checks/tls/https-redirect.js.map +1 -0
  70. package/dist/checks/tls/legacy-protocols.d.ts +3 -0
  71. package/dist/checks/tls/legacy-protocols.d.ts.map +1 -0
  72. package/dist/checks/tls/legacy-protocols.js +27 -0
  73. package/dist/checks/tls/legacy-protocols.js.map +1 -0
  74. package/dist/checks/util.d.ts +22 -0
  75. package/dist/checks/util.d.ts.map +1 -0
  76. package/dist/checks/util.js +63 -0
  77. package/dist/checks/util.js.map +1 -0
  78. package/dist/code/checks/crypto.d.ts +5 -0
  79. package/dist/code/checks/crypto.d.ts.map +1 -0
  80. package/dist/code/checks/crypto.js +100 -0
  81. package/dist/code/checks/crypto.js.map +1 -0
  82. package/dist/code/checks/django.d.ts +14 -0
  83. package/dist/code/checks/django.d.ts.map +1 -0
  84. package/dist/code/checks/django.js +313 -0
  85. package/dist/code/checks/django.js.map +1 -0
  86. package/dist/code/checks/flask.d.ts +6 -0
  87. package/dist/code/checks/flask.d.ts.map +1 -0
  88. package/dist/code/checks/flask.js +100 -0
  89. package/dist/code/checks/flask.js.map +1 -0
  90. package/dist/code/checks/index.d.ts +9 -0
  91. package/dist/code/checks/index.d.ts.map +1 -0
  92. package/dist/code/checks/index.js +126 -0
  93. package/dist/code/checks/index.js.map +1 -0
  94. package/dist/code/checks/injection.d.ts +27 -0
  95. package/dist/code/checks/injection.d.ts.map +1 -0
  96. package/dist/code/checks/injection.js +189 -0
  97. package/dist/code/checks/injection.js.map +1 -0
  98. package/dist/code/checks/javascript-config.d.ts +14 -0
  99. package/dist/code/checks/javascript-config.d.ts.map +1 -0
  100. package/dist/code/checks/javascript-config.js +251 -0
  101. package/dist/code/checks/javascript-config.js.map +1 -0
  102. package/dist/code/checks/javascript.d.ts +34 -0
  103. package/dist/code/checks/javascript.d.ts.map +1 -0
  104. package/dist/code/checks/javascript.js +333 -0
  105. package/dist/code/checks/javascript.js.map +1 -0
  106. package/dist/code/checks/php.d.ts +27 -0
  107. package/dist/code/checks/php.d.ts.map +1 -0
  108. package/dist/code/checks/php.js +433 -0
  109. package/dist/code/checks/php.js.map +1 -0
  110. package/dist/code/checks/secrets.d.ts +10 -0
  111. package/dist/code/checks/secrets.d.ts.map +1 -0
  112. package/dist/code/checks/secrets.js +140 -0
  113. package/dist/code/checks/secrets.js.map +1 -0
  114. package/dist/code/checks/shared.d.ts +25 -0
  115. package/dist/code/checks/shared.d.ts.map +1 -0
  116. package/dist/code/checks/shared.js +57 -0
  117. package/dist/code/checks/shared.js.map +1 -0
  118. package/dist/code/checks/treesitter.d.ts +15 -0
  119. package/dist/code/checks/treesitter.d.ts.map +1 -0
  120. package/dist/code/checks/treesitter.js +322 -0
  121. package/dist/code/checks/treesitter.js.map +1 -0
  122. package/dist/code/checks/xml.d.ts +9 -0
  123. package/dist/code/checks/xml.d.ts.map +1 -0
  124. package/dist/code/checks/xml.js +78 -0
  125. package/dist/code/checks/xml.js.map +1 -0
  126. package/dist/code/context.d.ts +6 -0
  127. package/dist/code/context.d.ts.map +1 -0
  128. package/dist/code/context.js +92 -0
  129. package/dist/code/context.js.map +1 -0
  130. package/dist/code/detect.d.ts +3 -0
  131. package/dist/code/detect.d.ts.map +1 -0
  132. package/dist/code/detect.js +118 -0
  133. package/dist/code/detect.js.map +1 -0
  134. package/dist/code/django/settings.d.ts +46 -0
  135. package/dist/code/django/settings.d.ts.map +1 -0
  136. package/dist/code/django/settings.js +154 -0
  137. package/dist/code/django/settings.js.map +1 -0
  138. package/dist/code/findings.d.ts +18 -0
  139. package/dist/code/findings.d.ts.map +1 -0
  140. package/dist/code/findings.js +63 -0
  141. package/dist/code/findings.js.map +1 -0
  142. package/dist/code/javascript/ast.d.ts +46 -0
  143. package/dist/code/javascript/ast.d.ts.map +1 -0
  144. package/dist/code/javascript/ast.js +166 -0
  145. package/dist/code/javascript/ast.js.map +1 -0
  146. package/dist/code/javascript/index.d.ts +3 -0
  147. package/dist/code/javascript/index.d.ts.map +1 -0
  148. package/dist/code/javascript/index.js +3 -0
  149. package/dist/code/javascript/index.js.map +1 -0
  150. package/dist/code/javascript/module.d.ts +59 -0
  151. package/dist/code/javascript/module.d.ts.map +1 -0
  152. package/dist/code/javascript/module.js +250 -0
  153. package/dist/code/javascript/module.js.map +1 -0
  154. package/dist/code/php/index.d.ts +92 -0
  155. package/dist/code/php/index.d.ts.map +1 -0
  156. package/dist/code/php/index.js +316 -0
  157. package/dist/code/php/index.js.map +1 -0
  158. package/dist/code/project.d.ts +13 -0
  159. package/dist/code/project.d.ts.map +1 -0
  160. package/dist/code/project.js +69 -0
  161. package/dist/code/project.js.map +1 -0
  162. package/dist/code/python/ast.d.ts +47 -0
  163. package/dist/code/python/ast.d.ts.map +1 -0
  164. package/dist/code/python/ast.js +193 -0
  165. package/dist/code/python/ast.js.map +1 -0
  166. package/dist/code/python/index.d.ts +3 -0
  167. package/dist/code/python/index.d.ts.map +1 -0
  168. package/dist/code/python/index.js +3 -0
  169. package/dist/code/python/index.js.map +1 -0
  170. package/dist/code/python/module.d.ts +55 -0
  171. package/dist/code/python/module.d.ts.map +1 -0
  172. package/dist/code/python/module.js +215 -0
  173. package/dist/code/python/module.js.map +1 -0
  174. package/dist/code/scan.d.ts +24 -0
  175. package/dist/code/scan.d.ts.map +1 -0
  176. package/dist/code/scan.js +159 -0
  177. package/dist/code/scan.js.map +1 -0
  178. package/dist/code/treesitter/index.d.ts +83 -0
  179. package/dist/code/treesitter/index.d.ts.map +1 -0
  180. package/dist/code/treesitter/index.js +243 -0
  181. package/dist/code/treesitter/index.js.map +1 -0
  182. package/dist/code/types.d.ts +48 -0
  183. package/dist/code/types.d.ts.map +1 -0
  184. package/dist/code/types.js +2 -0
  185. package/dist/code/types.js.map +1 -0
  186. package/dist/content/en.d.ts +3 -0
  187. package/dist/content/en.d.ts.map +1 -0
  188. package/dist/content/en.js +722 -0
  189. package/dist/content/en.js.map +1 -0
  190. package/dist/content/index.d.ts +15 -0
  191. package/dist/content/index.d.ts.map +1 -0
  192. package/dist/content/index.js +21 -0
  193. package/dist/content/index.js.map +1 -0
  194. package/dist/content/types.d.ts +87 -0
  195. package/dist/content/types.d.ts.map +1 -0
  196. package/dist/content/types.js +2 -0
  197. package/dist/content/types.js.map +1 -0
  198. package/dist/engine.d.ts +52 -0
  199. package/dist/engine.d.ts.map +1 -0
  200. package/dist/engine.js +120 -0
  201. package/dist/engine.js.map +1 -0
  202. package/dist/index.d.ts +12 -0
  203. package/dist/index.d.ts.map +1 -0
  204. package/dist/index.js +11 -0
  205. package/dist/index.js.map +1 -0
  206. package/dist/meta.d.ts +4 -0
  207. package/dist/meta.d.ts.map +1 -0
  208. package/dist/meta.js +4 -0
  209. package/dist/meta.js.map +1 -0
  210. package/dist/net/context.d.ts +9 -0
  211. package/dist/net/context.d.ts.map +1 -0
  212. package/dist/net/context.js +62 -0
  213. package/dist/net/context.js.map +1 -0
  214. package/dist/net/guard.d.ts +16 -0
  215. package/dist/net/guard.d.ts.map +1 -0
  216. package/dist/net/guard.js +70 -0
  217. package/dist/net/guard.js.map +1 -0
  218. package/dist/net/http.d.ts +22 -0
  219. package/dist/net/http.d.ts.map +1 -0
  220. package/dist/net/http.js +114 -0
  221. package/dist/net/http.js.map +1 -0
  222. package/dist/net/tls.d.ts +15 -0
  223. package/dist/net/tls.d.ts.map +1 -0
  224. package/dist/net/tls.js +103 -0
  225. package/dist/net/tls.js.map +1 -0
  226. package/dist/report/html.d.ts +14 -0
  227. package/dist/report/html.d.ts.map +1 -0
  228. package/dist/report/html.js +210 -0
  229. package/dist/report/html.js.map +1 -0
  230. package/dist/report/index.d.ts +10 -0
  231. package/dist/report/index.d.ts.map +1 -0
  232. package/dist/report/index.js +10 -0
  233. package/dist/report/index.js.map +1 -0
  234. package/dist/report/manual.d.ts +62 -0
  235. package/dist/report/manual.d.ts.map +1 -0
  236. package/dist/report/manual.js +190 -0
  237. package/dist/report/manual.js.map +1 -0
  238. package/dist/report/merge.d.ts +8 -0
  239. package/dist/report/merge.d.ts.map +1 -0
  240. package/dist/report/merge.js +135 -0
  241. package/dist/report/merge.js.map +1 -0
  242. package/dist/report/summary.d.ts +10 -0
  243. package/dist/report/summary.d.ts.map +1 -0
  244. package/dist/report/summary.js +27 -0
  245. package/dist/report/summary.js.map +1 -0
  246. package/dist/report/validate.d.ts +3 -0
  247. package/dist/report/validate.d.ts.map +1 -0
  248. package/dist/report/validate.js +78 -0
  249. package/dist/report/validate.js.map +1 -0
  250. package/dist/types.d.ts +244 -0
  251. package/dist/types.d.ts.map +1 -0
  252. package/dist/types.js +2 -0
  253. package/dist/types.js.map +1 -0
  254. package/dist/validate.d.ts +4 -0
  255. package/dist/validate.d.ts.map +1 -0
  256. package/dist/validate.js +24 -0
  257. package/dist/validate.js.map +1 -0
  258. package/package.json +40 -0
@@ -0,0 +1,251 @@
1
+ import { jsFinding, locations, outcomeFromFindings } from "../findings.js";
2
+ import { isJsFalse, isJsTrue, jsArgs, jsDotted, jsString, objectProp, unwrap, walkJs, } from "../javascript/index.js";
3
+ import { codeCheck } from "./shared.js";
4
+ /**
5
+ * Configuration rules for Node server frameworks. They only run when one is detected, so
6
+ * front-end JavaScript inside (say) a Django project is not judged as if it were a server.
7
+ */
8
+ const SERVER = ["express", "koa", "fastify", "next", "nestjs"];
9
+ function serverCheck(key, run) {
10
+ return codeCheck(key, SERVER, async (ctx) => run(await ctx.javascript(), ctx));
11
+ }
12
+ const numeric = (node) => {
13
+ const n = unwrap(node);
14
+ if (!n)
15
+ return undefined;
16
+ if (n.type === "NumericLiteral")
17
+ return n["value"];
18
+ if (n.type === "BinaryExpression" && ["*", "+"].includes(n["operator"])) {
19
+ const l = numeric(n["left"]);
20
+ const r = numeric(n["right"]);
21
+ if (l === undefined || r === undefined)
22
+ return undefined;
23
+ return n["operator"] === "*" ? l * r : l + r;
24
+ }
25
+ return undefined;
26
+ };
27
+ // --- #3 Debug functionality ----------------------------------------------------------
28
+ export const jsDebug = serverCheck("js-debug", (index) => {
29
+ const out = [];
30
+ for (const s of index.calls()) {
31
+ if (s.name === "errorhandler") {
32
+ out.push(jsFinding(s.module, s.node, "express-errorhandler", "medium", "The errorhandler middleware sends stack traces to clients; it is for development only."));
33
+ }
34
+ const args = jsArgs(s.node);
35
+ if (s.method === "set" && jsString(args[0]) === "env" && jsString(args[1]) === "development") {
36
+ out.push(jsFinding(s.module, s.node, "express-env-development", "medium", "Forcing the development environment enables verbose errors in production."));
37
+ }
38
+ }
39
+ for (const module of index.modules) {
40
+ for (const n of walkJs(module.tree)) {
41
+ if (n.type !== "ObjectProperty")
42
+ continue;
43
+ const key = n["key"]["name"] ?? jsString(n["key"]);
44
+ if ((key === "playground" || key === "introspection") && isJsTrue(n["value"])) {
45
+ out.push(jsFinding(module, n, "graphql-introspection", "low", "GraphQL playground/introspection exposes the full API schema; disable it in production."));
46
+ }
47
+ }
48
+ }
49
+ return outcomeFromFindings(out, `No development-only error handlers or debug settings found in ${index.modules.length} JavaScript/TypeScript file(s).`);
50
+ });
51
+ // --- #61 CSRF --------------------------------------------------------------------------
52
+ const CSRF_PACKAGES = ["csurf", "csrf-csrf", "csrf-sync", "lusca", "@fastify/csrf-protection", "koa-csrf", "tiny-csrf"];
53
+ const SESSION_PACKAGES = ["express-session", "cookie-session", "koa-session", "@fastify/session", "@fastify/secure-session", "iron-session", "next-auth"];
54
+ export const jsCsrf = serverCheck("js-csrf", (index) => {
55
+ const csrf = CSRF_PACKAGES.filter((p) => index.imports(p));
56
+ if (csrf.length)
57
+ return { status: "pass", detail: `CSRF protection middleware is used (${csrf.join(", ")}). Confirm it covers every state-changing route.` };
58
+ const sessions = SESSION_PACKAGES.filter((p) => index.imports(p));
59
+ return {
60
+ status: "manual",
61
+ detail: sessions.length
62
+ ? `Cookie sessions are used (${sessions.join(", ")}) but no CSRF middleware was found. Confirm state-changing requests are protected (anti-CSRF token or SameSite cookies).`
63
+ : "No CSRF middleware and no cookie-session library found. If the API authenticates with headers/tokens only, CSRF does not apply; otherwise review manually.",
64
+ };
65
+ });
66
+ const cache = new WeakMap();
67
+ /** express-session({ cookie: {...} }) and cookie-session({...}) calls. */
68
+ function sessionConfigs(index) {
69
+ let configs = cache.get(index);
70
+ if (!configs) {
71
+ configs = [];
72
+ for (const s of index.calls()) {
73
+ const options = unwrap(jsArgs(s.node)[0]);
74
+ if (s.name === "express-session" || s.name === "@fastify/session")
75
+ configs.push({ site: s, cookie: objectProp(options, "cookie") });
76
+ else if (s.name === "cookie-session" || s.name === "koa-session")
77
+ configs.push({ site: s, cookie: options?.type === "ObjectExpression" ? options : undefined });
78
+ }
79
+ cache.set(index, configs);
80
+ }
81
+ return configs;
82
+ }
83
+ const NO_SESSION = {
84
+ status: "manual",
85
+ detail: "No express-session / cookie-session configuration found in the code. Review how session cookies are set (framework, proxy or identity provider).",
86
+ };
87
+ function sessionFlag(key, option, label, defaultSecure, why) {
88
+ return serverCheck(key, (index) => {
89
+ const configs = sessionConfigs(index);
90
+ if (configs.length === 0)
91
+ return NO_SESSION;
92
+ const findings = [];
93
+ const dynamic = [];
94
+ for (const { site, cookie } of configs) {
95
+ const value = objectProp(cookie, option);
96
+ const where = `${site.module.path}:${site.module.lineOf(site.node)}`;
97
+ if (!value) {
98
+ if (!defaultSecure)
99
+ findings.push(jsFinding(site.module, site.node, `${key}-missing`, "medium", `${label} is not set (default: off). ${why}`));
100
+ }
101
+ else if (isJsFalse(value))
102
+ findings.push(jsFinding(site.module, value, `${key}-false`, "high", why));
103
+ else if (!isJsTrue(value) && jsString(value) !== "auto")
104
+ dynamic.push(where);
105
+ }
106
+ if (findings.length === 0 && dynamic.length) {
107
+ return { status: "manual", detail: `${label} is computed at runtime (${dynamic.join(", ")}); confirm the production value.` };
108
+ }
109
+ return outcomeFromFindings(findings, `Session cookies set ${label} in ${configs.length} session configuration(s).`);
110
+ });
111
+ }
112
+ export const jsSessionSecure = sessionFlag("js-session-cookie-secure", "secure", "the Secure flag", false, "The session cookie can be sent over plain HTTP and intercepted.");
113
+ export const jsSessionHttpOnly = sessionFlag("js-session-cookie-httponly", "httpOnly", "HttpOnly", true, "JavaScript (including injected scripts) can read the session cookie.");
114
+ export const jsSessionDomain = serverCheck("js-session-cookie-domain", (index) => {
115
+ const configs = sessionConfigs(index);
116
+ if (configs.length === 0)
117
+ return NO_SESSION;
118
+ const findings = [];
119
+ const review = [];
120
+ for (const { site, cookie } of configs) {
121
+ const value = objectProp(cookie, "domain");
122
+ if (!value)
123
+ continue;
124
+ const domain = jsString(value);
125
+ if (domain?.startsWith("."))
126
+ findings.push(jsFinding(site.module, value, "js-session-cookie-domain", "medium", "A leading-dot domain shares the session cookie with every subdomain."));
127
+ else
128
+ review.push(`${site.module.path}:${site.module.lineOf(value)}`);
129
+ }
130
+ if (findings.length === 0 && review.length) {
131
+ return { status: "manual", detail: `A session cookie domain is set (${review.join(", ")}); it also covers subdomains. Confirm it is the site's exact host.` };
132
+ }
133
+ return outcomeFromFindings(findings, "No session cookie domain is set, so session cookies are host-only (most restrictive).");
134
+ });
135
+ export const jsSessionPath = serverCheck("js-session-cookie-path", (index) => {
136
+ const configs = sessionConfigs(index);
137
+ if (configs.length === 0)
138
+ return NO_SESSION;
139
+ const paths = configs.map((c) => jsString(objectProp(c.cookie, "path")) ?? "/ (default)");
140
+ // Whether "/" is restrictive enough depends on where the app is mounted, which the code does not say.
141
+ return { status: "manual", detail: `Session cookie path: ${[...new Set(paths)].join(", ")}. Restrictive only if it matches the path the application is mounted at.` };
142
+ });
143
+ const MAX_SESSION_MS = 24 * 60 * 60 * 1000;
144
+ export const jsSessionExpiry = serverCheck("js-session-expiry", (index) => {
145
+ const configs = sessionConfigs(index);
146
+ if (configs.length === 0)
147
+ return NO_SESSION;
148
+ const findings = [];
149
+ const unknown = [];
150
+ for (const { site, cookie } of configs) {
151
+ const value = objectProp(cookie, "maxAge");
152
+ const ms = numeric(value);
153
+ if (!value || ms === undefined)
154
+ unknown.push(`${site.module.path}:${site.module.lineOf(site.node)}`);
155
+ else if (ms > MAX_SESSION_MS) {
156
+ findings.push(jsFinding(site.module, value, "js-session-age", "medium", `Sessions stay valid for ${Math.round(ms / 3_600_000)} hours; this tool expects at most 24h as INSA sets no figure.`));
157
+ }
158
+ }
159
+ if (findings.length === 0 && unknown.length) {
160
+ return { status: "manual", detail: `No fixed session lifetime (cookie maxAge) found in ${unknown.join(", ")}; confirm idle and absolute timeouts are enforced.` };
161
+ }
162
+ return outcomeFromFindings(findings, "Session cookies expire within 24 hours.");
163
+ });
164
+ // --- #64 / #73 Session regeneration on login ---------------------------------------------
165
+ const USER_KEY = /^(user|userId|user_id|uid|account|accountId|loggedIn|isLoggedIn|authenticated|auth)$/i;
166
+ export const jsLoginRotation = serverCheck("js-login-session-rotation", (index) => {
167
+ const findings = [];
168
+ const regenerates = new Set(index.calls().filter((s) => s.method === "regenerate").map((s) => s.module.path));
169
+ for (const module of index.modules) {
170
+ for (const n of walkJs(module.tree)) {
171
+ if (n.type !== "AssignmentExpression")
172
+ continue;
173
+ const m = /^(?:req|request)\.session\.(\w+)$/.exec(jsDotted(n["left"]) ?? "");
174
+ if (!m || !USER_KEY.test(m[1]) || regenerates.has(module.path))
175
+ continue;
176
+ findings.push(jsFinding(module, n, "js-session-login-no-regenerate", "medium", "The user is stored in the existing session without regenerating its ID (session fixation); call req.session.regenerate() on login."));
177
+ }
178
+ }
179
+ if (findings.length)
180
+ return outcomeFromFindings(findings, "");
181
+ if (regenerates.size)
182
+ return { status: "pass", detail: "Sessions are regenerated on login (req.session.regenerate is called where the user is stored)." };
183
+ if (index.imports("passport"))
184
+ return { status: "pass", detail: "Logins go through Passport, which regenerates the session on login (passport >= 0.6). Confirm the installed version." };
185
+ return { status: "manual", detail: "No session-based login found in the code (no req.session user assignment, no Passport); review how users are authenticated." };
186
+ });
187
+ // --- #37 Rate limiting on authentication ---------------------------------------------------
188
+ const RATE_PACKAGES = ["express-rate-limit", "rate-limiter-flexible", "express-slow-down", "express-brute", "@nestjs/throttler", "@fastify/rate-limit", "koa-ratelimit", "@upstash/ratelimit"];
189
+ export const jsAuthRateLimit = serverCheck("js-auth-rate-limit", (index) => {
190
+ const used = RATE_PACKAGES.filter((p) => index.imports(p));
191
+ if (used.length)
192
+ return { status: "pass", detail: `Rate limiting is used (${used.join(", ")}). Confirm it is applied to login, password-reset and token endpoints.`, evidence: used };
193
+ return { status: "manual", detail: "No application-level rate limiting library found. It may be enforced by a reverse proxy or WAF; verify there." };
194
+ });
195
+ // --- #80 - #82 File uploads ------------------------------------------------------------------
196
+ const UPLOAD_PACKAGES = ["multer", "formidable", "busboy", "express-fileupload", "@fastify/multipart", "multiparty"];
197
+ const handlesUploads = (index) => UPLOAD_PACKAGES.some((p) => index.imports(p));
198
+ const NO_UPLOADS = (n) => ({ status: "pass", detail: `No file upload handling found in ${n} JavaScript/TypeScript file(s) (no multer, formidable, busboy or similar).` });
199
+ const multerCalls = (index) => index.calls().filter((s) => s.name === "multer");
200
+ export const jsUploadPath = serverCheck("js-upload-path", (index) => {
201
+ if (!handlesUploads(index))
202
+ return NO_UPLOADS(index.modules.length);
203
+ const findings = [];
204
+ for (const module of index.modules) {
205
+ for (const n of walkJs(module.tree)) {
206
+ // file.originalname / files.x.name used to build the stored path or name.
207
+ if (n.type !== "CallExpression")
208
+ continue;
209
+ const name = module.qualify(jsDotted(n["callee"])) ?? "";
210
+ const usesClientName = jsArgs(n).some((a) => [...walkJs(a)].some((x) => /MemberExpression$/.test(x.type) && /\.(originalname|originalFilename)$|files?(\.\w+|\[\])?\.name$/.test(jsDotted(x) ?? "")));
211
+ if (!usesClientName)
212
+ continue;
213
+ if (/^path\.(join|resolve)$/.test(name) || /^(fs|fs\.promises)\./.test(name) || /\.(mv|cb|callback)$/.test(name) || name === "cb") {
214
+ findings.push(jsFinding(module, n, "js-upload-client-filename", "high", "Storing an upload under the client-supplied file name allows ../ to escape the upload directory and overwrites; generate the name or use path.basename plus an allow-list."));
215
+ }
216
+ }
217
+ }
218
+ return outcomeFromFindings(findings, "Uploads are not stored under client-supplied file names.");
219
+ });
220
+ export const jsUploadSize = serverCheck("js-upload-size", (index) => {
221
+ if (!handlesUploads(index))
222
+ return NO_UPLOADS(index.modules.length);
223
+ const limited = [];
224
+ for (const module of index.modules) {
225
+ for (const n of walkJs(module.tree)) {
226
+ if (n.type !== "ObjectProperty")
227
+ continue;
228
+ const key = n["key"]["name"] ?? jsString(n["key"]);
229
+ if (key === "fileSize" || key === "maxFileSize" || key === "maxFieldsSize")
230
+ limited.push(`${module.path}:${module.lineOf(n)}`);
231
+ }
232
+ }
233
+ if (limited.length)
234
+ return { status: "pass", detail: `Upload size limits are configured (${limited.slice(0, 3).join(", ")}).`, evidence: limited };
235
+ return { status: "manual", detail: "The project handles uploads but no size limit (e.g. multer limits.fileSize) was found in code. Confirm a limit at the web server or add one." };
236
+ });
237
+ export const jsUploadType = serverCheck("js-upload-type", (index) => {
238
+ if (!handlesUploads(index))
239
+ return NO_UPLOADS(index.modules.length);
240
+ const calls = multerCalls(index);
241
+ if (calls.length === 0) {
242
+ return { status: "manual", detail: "Uploads are handled without multer; review type validation in the handling code." };
243
+ }
244
+ const findings = calls
245
+ .filter((s) => !objectProp(jsArgs(s.node)[0], "fileFilter"))
246
+ .map((s) => jsFinding(s.module, s.node, "multer-no-filefilter", "medium", "multer accepts any file type unless a fileFilter (or later content check) restricts it."));
247
+ if (findings.length)
248
+ return { status: "fail", detail: `${findings.length} upload handler(s) without a fileFilter: ${locations(findings)}.`, findings };
249
+ return { status: "pass", detail: `All ${calls.length} multer configuration(s) define a fileFilter.` };
250
+ });
251
+ //# sourceMappingURL=javascript-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"javascript-config.js","sourceRoot":"","sources":["../../../src/code/checks/javascript-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { CodeFinding, Confidence } from "../../types.js";
2
+ import { type JsCallSite, type JsIndex, type JsNode } from "../javascript/index.js";
3
+ import type { CodeCheck, CodeContext } from "../types.js";
4
+ export declare function jsPatternCheck(key: string, find: (index: JsIndex, ctx: CodeContext) => CodeFinding[] | Promise<CodeFinding[]>, what: string): CodeCheck;
5
+ export interface SinkOptions {
6
+ /** Report values of unknown origin as low confidence (default true). */
7
+ unknownIsLow?: boolean;
8
+ /** Only report when request data reaches the sink (file paths, regexes, templates...). */
9
+ requestOnly?: boolean;
10
+ }
11
+ /**
12
+ * How risky is passing `arg` to a sink?
13
+ * high - contains request data directly, or is a string built from it
14
+ * medium - built dynamically (template literal, +), or derived from request data via local variables
15
+ * low - some other non-literal value (origin unknown)
16
+ */
17
+ export declare function jsArgRisk(site: JsCallSite, arg: JsNode | undefined, opts?: SinkOptions): Confidence | undefined;
18
+ export declare const jsHardcodedSecrets: CodeCheck;
19
+ export declare const jsWeakCrypto: CodeCheck;
20
+ export declare const jsCryptoMisuse: CodeCheck;
21
+ export declare const jsPlaintextPasswords: CodeCheck;
22
+ export declare const jsSqlInjection: CodeCheck;
23
+ export declare const jsCommandInjection: CodeCheck;
24
+ export declare const jsCodeInjection: CodeCheck;
25
+ export declare const jsPathTraversal: CodeCheck;
26
+ export declare const jsXss: CodeCheck;
27
+ export declare const jsRegexInjection: CodeCheck;
28
+ export declare const jsTemplateInjection: CodeCheck;
29
+ export declare const jsMassAssignment: CodeCheck;
30
+ export declare const jsOpenRedirect: CodeCheck;
31
+ export declare const jsSecretsInLogs: CodeCheck;
32
+ export declare const jsXxe: CodeCheck;
33
+ export declare const jsExternalDtd: CodeCheck;
34
+ //# sourceMappingURL=javascript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"javascript.d.ts","sourceRoot":"","sources":["../../../src/code/checks/javascript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAYL,KAAK,UAAU,EACf,KAAK,OAAO,EAEZ,KAAK,MAAM,EACZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAQ1D,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,KAAK,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,EAClF,IAAI,EAAE,MAAM,GACX,SAAS,CAKX;AAED,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,WAAgB,GAAG,UAAU,GAAG,SAAS,CAWnH;AAqCD,eAAO,MAAM,kBAAkB,WA4B9B,CAAC;AAGF,eAAO,MAAM,YAAY,WAsBxB,CAAC;AAEF,eAAO,MAAM,cAAc,WA0B1B,CAAC;AAKF,eAAO,MAAM,oBAAoB,WAiChC,CAAC;AAQF,eAAO,MAAM,cAAc,WAmB1B,CAAC;AAGF,eAAO,MAAM,kBAAkB,WAe9B,CAAC;AAGF,eAAO,MAAM,eAAe,WAkB3B,CAAC;AAKF,eAAO,MAAM,eAAe,WAW3B,CAAC;AAGF,eAAO,MAAM,KAAK,WAwCjB,CAAC;AAGF,eAAO,MAAM,gBAAgB,WAM5B,CAAC;AAEF,eAAO,MAAM,mBAAmB,WAM/B,CAAC;AAKF,eAAO,MAAM,gBAAgB,WAkB5B,CAAC;AAGF,eAAO,MAAM,cAAc,WAc1B,CAAC;AAMF,eAAO,MAAM,eAAe,WAsB3B,CAAC;AAWF,eAAO,MAAM,KAAK,WAIjB,CAAC;AAEF,eAAO,MAAM,aAAa,WAOzB,CAAC"}