@skillsmith/mcp-server 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 (306) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/src/__tests__/get-skill.test.d.ts +6 -0
  3. package/dist/src/__tests__/get-skill.test.d.ts.map +1 -0
  4. package/dist/src/__tests__/get-skill.test.js +88 -0
  5. package/dist/src/__tests__/get-skill.test.js.map +1 -0
  6. package/dist/src/__tests__/middleware/errorFormatter.test.d.ts +7 -0
  7. package/dist/src/__tests__/middleware/errorFormatter.test.d.ts.map +1 -0
  8. package/dist/src/__tests__/middleware/errorFormatter.test.js +304 -0
  9. package/dist/src/__tests__/middleware/errorFormatter.test.js.map +1 -0
  10. package/dist/src/__tests__/middleware/license.test.d.ts +7 -0
  11. package/dist/src/__tests__/middleware/license.test.d.ts.map +1 -0
  12. package/dist/src/__tests__/middleware/license.test.js +500 -0
  13. package/dist/src/__tests__/middleware/license.test.js.map +1 -0
  14. package/dist/src/__tests__/search.test.d.ts +6 -0
  15. package/dist/src/__tests__/search.test.d.ts.map +1 -0
  16. package/dist/src/__tests__/search.test.js +86 -0
  17. package/dist/src/__tests__/search.test.js.map +1 -0
  18. package/dist/src/__tests__/test-utils.d.ts +19 -0
  19. package/dist/src/__tests__/test-utils.d.ts.map +1 -0
  20. package/dist/src/__tests__/test-utils.js +87 -0
  21. package/dist/src/__tests__/test-utils.js.map +1 -0
  22. package/dist/src/context/index.d.ts +19 -0
  23. package/dist/src/context/index.d.ts.map +1 -0
  24. package/dist/src/context/index.js +25 -0
  25. package/dist/src/context/index.js.map +1 -0
  26. package/dist/src/context/project-detector.d.ts +145 -0
  27. package/dist/src/context/project-detector.d.ts.map +1 -0
  28. package/dist/src/context/project-detector.js +321 -0
  29. package/dist/src/context/project-detector.js.map +1 -0
  30. package/dist/src/context.d.ts +100 -0
  31. package/dist/src/context.d.ts.map +1 -0
  32. package/dist/src/context.js +157 -0
  33. package/dist/src/context.js.map +1 -0
  34. package/dist/src/core-shim.d.ts +7 -0
  35. package/dist/src/core-shim.d.ts.map +1 -0
  36. package/dist/src/core-shim.js +9 -0
  37. package/dist/src/core-shim.js.map +1 -0
  38. package/dist/src/health/healthCheck.d.ts +88 -0
  39. package/dist/src/health/healthCheck.d.ts.map +1 -0
  40. package/dist/src/health/healthCheck.js +117 -0
  41. package/dist/src/health/healthCheck.js.map +1 -0
  42. package/dist/src/health/index.d.ts +21 -0
  43. package/dist/src/health/index.d.ts.map +1 -0
  44. package/dist/src/health/index.js +21 -0
  45. package/dist/src/health/index.js.map +1 -0
  46. package/dist/src/health/readinessCheck.d.ts +139 -0
  47. package/dist/src/health/readinessCheck.d.ts.map +1 -0
  48. package/dist/src/health/readinessCheck.js +266 -0
  49. package/dist/src/health/readinessCheck.js.map +1 -0
  50. package/dist/src/index.d.ts +8 -0
  51. package/dist/src/index.d.ts.map +1 -0
  52. package/dist/src/index.js +178 -0
  53. package/dist/src/index.js.map +1 -0
  54. package/dist/src/index.test.d.ts +2 -0
  55. package/dist/src/index.test.d.ts.map +1 -0
  56. package/dist/src/index.test.js +43 -0
  57. package/dist/src/index.test.js.map +1 -0
  58. package/dist/src/logger.d.ts +26 -0
  59. package/dist/src/logger.d.ts.map +1 -0
  60. package/dist/src/logger.js +179 -0
  61. package/dist/src/logger.js.map +1 -0
  62. package/dist/src/middleware/__tests__/csp.test.d.ts +2 -0
  63. package/dist/src/middleware/__tests__/csp.test.d.ts.map +1 -0
  64. package/dist/src/middleware/__tests__/csp.test.js +389 -0
  65. package/dist/src/middleware/__tests__/csp.test.js.map +1 -0
  66. package/dist/src/middleware/csp.d.ts +87 -0
  67. package/dist/src/middleware/csp.d.ts.map +1 -0
  68. package/dist/src/middleware/csp.js +273 -0
  69. package/dist/src/middleware/csp.js.map +1 -0
  70. package/dist/src/middleware/degradation.d.ts +99 -0
  71. package/dist/src/middleware/degradation.d.ts.map +1 -0
  72. package/dist/src/middleware/degradation.js +315 -0
  73. package/dist/src/middleware/degradation.js.map +1 -0
  74. package/dist/src/middleware/errorFormatter.d.ts +119 -0
  75. package/dist/src/middleware/errorFormatter.d.ts.map +1 -0
  76. package/dist/src/middleware/errorFormatter.js +294 -0
  77. package/dist/src/middleware/errorFormatter.js.map +1 -0
  78. package/dist/src/middleware/index.d.ts +10 -0
  79. package/dist/src/middleware/index.d.ts.map +1 -0
  80. package/dist/src/middleware/index.js +14 -0
  81. package/dist/src/middleware/index.js.map +1 -0
  82. package/dist/src/middleware/license.d.ts +161 -0
  83. package/dist/src/middleware/license.d.ts.map +1 -0
  84. package/dist/src/middleware/license.js +281 -0
  85. package/dist/src/middleware/license.js.map +1 -0
  86. package/dist/src/middleware/toolFeatureMapping.d.ts +36 -0
  87. package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -0
  88. package/dist/src/middleware/toolFeatureMapping.js +90 -0
  89. package/dist/src/middleware/toolFeatureMapping.js.map +1 -0
  90. package/dist/src/onboarding/first-run.d.ts +64 -0
  91. package/dist/src/onboarding/first-run.d.ts.map +1 -0
  92. package/dist/src/onboarding/first-run.js +77 -0
  93. package/dist/src/onboarding/first-run.js.map +1 -0
  94. package/dist/src/onboarding/index.d.ts +7 -0
  95. package/dist/src/onboarding/index.d.ts.map +1 -0
  96. package/dist/src/onboarding/index.js +7 -0
  97. package/dist/src/onboarding/index.js.map +1 -0
  98. package/dist/src/suggestions/index.d.ts +21 -0
  99. package/dist/src/suggestions/index.d.ts.map +1 -0
  100. package/dist/src/suggestions/index.js +20 -0
  101. package/dist/src/suggestions/index.js.map +1 -0
  102. package/dist/src/suggestions/suggestion-engine.d.ts +185 -0
  103. package/dist/src/suggestions/suggestion-engine.d.ts.map +1 -0
  104. package/dist/src/suggestions/suggestion-engine.js +352 -0
  105. package/dist/src/suggestions/suggestion-engine.js.map +1 -0
  106. package/dist/src/suggestions/types.d.ts +88 -0
  107. package/dist/src/suggestions/types.d.ts.map +1 -0
  108. package/dist/src/suggestions/types.js +21 -0
  109. package/dist/src/suggestions/types.js.map +1 -0
  110. package/dist/src/tools/analyze.d.ts +151 -0
  111. package/dist/src/tools/analyze.d.ts.map +1 -0
  112. package/dist/src/tools/analyze.js +205 -0
  113. package/dist/src/tools/analyze.js.map +1 -0
  114. package/dist/src/tools/compare.d.ts +149 -0
  115. package/dist/src/tools/compare.d.ts.map +1 -0
  116. package/dist/src/tools/compare.js +464 -0
  117. package/dist/src/tools/compare.js.map +1 -0
  118. package/dist/src/tools/get-skill.d.ts +116 -0
  119. package/dist/src/tools/get-skill.d.ts.map +1 -0
  120. package/dist/src/tools/get-skill.js +224 -0
  121. package/dist/src/tools/get-skill.js.map +1 -0
  122. package/dist/src/tools/index.d.ts +20 -0
  123. package/dist/src/tools/index.d.ts.map +1 -0
  124. package/dist/src/tools/index.js +20 -0
  125. package/dist/src/tools/index.js.map +1 -0
  126. package/dist/src/tools/install.d.ts +122 -0
  127. package/dist/src/tools/install.d.ts.map +1 -0
  128. package/dist/src/tools/install.js +314 -0
  129. package/dist/src/tools/install.js.map +1 -0
  130. package/dist/src/tools/recommend.d.ts +171 -0
  131. package/dist/src/tools/recommend.d.ts.map +1 -0
  132. package/dist/src/tools/recommend.js +325 -0
  133. package/dist/src/tools/recommend.js.map +1 -0
  134. package/dist/src/tools/search.d.ts +121 -0
  135. package/dist/src/tools/search.d.ts.map +1 -0
  136. package/dist/src/tools/search.js +249 -0
  137. package/dist/src/tools/search.js.map +1 -0
  138. package/dist/src/tools/suggest.d.ts +181 -0
  139. package/dist/src/tools/suggest.d.ts.map +1 -0
  140. package/dist/src/tools/suggest.js +342 -0
  141. package/dist/src/tools/suggest.js.map +1 -0
  142. package/dist/src/tools/uninstall.d.ts +123 -0
  143. package/dist/src/tools/uninstall.d.ts.map +1 -0
  144. package/dist/src/tools/uninstall.js +250 -0
  145. package/dist/src/tools/uninstall.js.map +1 -0
  146. package/dist/src/tools/validate.d.ts +122 -0
  147. package/dist/src/tools/validate.d.ts.map +1 -0
  148. package/dist/src/tools/validate.js +497 -0
  149. package/dist/src/tools/validate.js.map +1 -0
  150. package/dist/src/utils/installed-skills.d.ts +101 -0
  151. package/dist/src/utils/installed-skills.d.ts.map +1 -0
  152. package/dist/src/utils/installed-skills.js +220 -0
  153. package/dist/src/utils/installed-skills.js.map +1 -0
  154. package/dist/src/utils/validation.d.ts +76 -0
  155. package/dist/src/utils/validation.d.ts.map +1 -0
  156. package/dist/src/utils/validation.js +153 -0
  157. package/dist/src/utils/validation.js.map +1 -0
  158. package/dist/src/webhooks/index.d.ts +8 -0
  159. package/dist/src/webhooks/index.d.ts.map +1 -0
  160. package/dist/src/webhooks/index.js +9 -0
  161. package/dist/src/webhooks/index.js.map +1 -0
  162. package/dist/src/webhooks/webhook-endpoint.d.ts +149 -0
  163. package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -0
  164. package/dist/src/webhooks/webhook-endpoint.js +339 -0
  165. package/dist/src/webhooks/webhook-endpoint.js.map +1 -0
  166. package/dist/tests/compare.test.d.ts +6 -0
  167. package/dist/tests/compare.test.d.ts.map +1 -0
  168. package/dist/tests/compare.test.js +225 -0
  169. package/dist/tests/compare.test.js.map +1 -0
  170. package/dist/tests/context/project-detector.test.d.ts +6 -0
  171. package/dist/tests/context/project-detector.test.d.ts.map +1 -0
  172. package/dist/tests/context/project-detector.test.js +719 -0
  173. package/dist/tests/context/project-detector.test.js.map +1 -0
  174. package/dist/tests/e2e/compare.e2e.test.d.ts +10 -0
  175. package/dist/tests/e2e/compare.e2e.test.d.ts.map +1 -0
  176. package/dist/tests/e2e/compare.e2e.test.js +286 -0
  177. package/dist/tests/e2e/compare.e2e.test.js.map +1 -0
  178. package/dist/tests/e2e/install-flow.e2e.test.d.ts +10 -0
  179. package/dist/tests/e2e/install-flow.e2e.test.d.ts.map +1 -0
  180. package/dist/tests/e2e/install-flow.e2e.test.js +209 -0
  181. package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -0
  182. package/dist/tests/e2e/recommend.e2e.test.d.ts +12 -0
  183. package/dist/tests/e2e/recommend.e2e.test.d.ts.map +1 -0
  184. package/dist/tests/e2e/recommend.e2e.test.js +347 -0
  185. package/dist/tests/e2e/recommend.e2e.test.js.map +1 -0
  186. package/dist/tests/e2e/skill-flow.e2e.test.d.ts +10 -0
  187. package/dist/tests/e2e/skill-flow.e2e.test.d.ts.map +1 -0
  188. package/dist/tests/e2e/skill-flow.e2e.test.js +280 -0
  189. package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -0
  190. package/dist/tests/e2e/suggest.e2e.test.d.ts +13 -0
  191. package/dist/tests/e2e/suggest.e2e.test.d.ts.map +1 -0
  192. package/dist/tests/e2e/suggest.e2e.test.js +347 -0
  193. package/dist/tests/e2e/suggest.e2e.test.js.map +1 -0
  194. package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
  195. package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
  196. package/dist/tests/e2e/utils/baseline-collector.js +211 -0
  197. package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
  198. package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
  199. package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
  200. package/dist/tests/e2e/utils/hardcoded-detector.js +255 -0
  201. package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
  202. package/dist/tests/e2e/utils/index.d.ts +7 -0
  203. package/dist/tests/e2e/utils/index.d.ts.map +1 -0
  204. package/dist/tests/e2e/utils/index.js +7 -0
  205. package/dist/tests/e2e/utils/index.js.map +1 -0
  206. package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
  207. package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
  208. package/dist/tests/e2e/utils/linear-reporter.js +232 -0
  209. package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
  210. package/dist/tests/health.test.d.ts +9 -0
  211. package/dist/tests/health.test.d.ts.map +1 -0
  212. package/dist/tests/health.test.js +308 -0
  213. package/dist/tests/health.test.js.map +1 -0
  214. package/dist/tests/integration/analyze.integration.test.d.ts +2 -0
  215. package/dist/tests/integration/analyze.integration.test.d.ts.map +1 -0
  216. package/dist/tests/integration/analyze.integration.test.js +244 -0
  217. package/dist/tests/integration/analyze.integration.test.js.map +1 -0
  218. package/dist/tests/integration/compare.integration.test.d.ts +2 -0
  219. package/dist/tests/integration/compare.integration.test.d.ts.map +1 -0
  220. package/dist/tests/integration/compare.integration.test.js +120 -0
  221. package/dist/tests/integration/compare.integration.test.js.map +1 -0
  222. package/dist/tests/integration/fixtures/test-skills.d.ts +62 -0
  223. package/dist/tests/integration/fixtures/test-skills.d.ts.map +1 -0
  224. package/dist/tests/integration/fixtures/test-skills.js +644 -0
  225. package/dist/tests/integration/fixtures/test-skills.js.map +1 -0
  226. package/dist/tests/integration/get-skill.integration.test.d.ts +6 -0
  227. package/dist/tests/integration/get-skill.integration.test.d.ts.map +1 -0
  228. package/dist/tests/integration/get-skill.integration.test.js +203 -0
  229. package/dist/tests/integration/get-skill.integration.test.js.map +1 -0
  230. package/dist/tests/integration/github-api.integration.test.d.ts +14 -0
  231. package/dist/tests/integration/github-api.integration.test.d.ts.map +1 -0
  232. package/dist/tests/integration/github-api.integration.test.js +190 -0
  233. package/dist/tests/integration/github-api.integration.test.js.map +1 -0
  234. package/dist/tests/integration/install.integration.test.d.ts +6 -0
  235. package/dist/tests/integration/install.integration.test.d.ts.map +1 -0
  236. package/dist/tests/integration/install.integration.test.js +282 -0
  237. package/dist/tests/integration/install.integration.test.js.map +1 -0
  238. package/dist/tests/integration/recommend.integration.test.d.ts +2 -0
  239. package/dist/tests/integration/recommend.integration.test.d.ts.map +1 -0
  240. package/dist/tests/integration/recommend.integration.test.js +215 -0
  241. package/dist/tests/integration/recommend.integration.test.js.map +1 -0
  242. package/dist/tests/integration/search.integration.test.d.ts +6 -0
  243. package/dist/tests/integration/search.integration.test.d.ts.map +1 -0
  244. package/dist/tests/integration/search.integration.test.js +229 -0
  245. package/dist/tests/integration/search.integration.test.js.map +1 -0
  246. package/dist/tests/integration/setup.d.ts +71 -0
  247. package/dist/tests/integration/setup.d.ts.map +1 -0
  248. package/dist/tests/integration/setup.js +124 -0
  249. package/dist/tests/integration/setup.js.map +1 -0
  250. package/dist/tests/integration/uninstall.integration.test.d.ts +6 -0
  251. package/dist/tests/integration/uninstall.integration.test.d.ts.map +1 -0
  252. package/dist/tests/integration/uninstall.integration.test.js +296 -0
  253. package/dist/tests/integration/uninstall.integration.test.js.map +1 -0
  254. package/dist/tests/integration/validate.integration.test.d.ts +2 -0
  255. package/dist/tests/integration/validate.integration.test.d.ts.map +1 -0
  256. package/dist/tests/integration/validate.integration.test.js +181 -0
  257. package/dist/tests/integration/validate.integration.test.js.map +1 -0
  258. package/dist/tests/onboarding/first-run.test.d.ts +7 -0
  259. package/dist/tests/onboarding/first-run.test.d.ts.map +1 -0
  260. package/dist/tests/onboarding/first-run.test.js +258 -0
  261. package/dist/tests/onboarding/first-run.test.js.map +1 -0
  262. package/dist/tests/performance/search-performance.test.d.ts +10 -0
  263. package/dist/tests/performance/search-performance.test.d.ts.map +1 -0
  264. package/dist/tests/performance/search-performance.test.js +218 -0
  265. package/dist/tests/performance/search-performance.test.js.map +1 -0
  266. package/dist/tests/recommend.test.d.ts +6 -0
  267. package/dist/tests/recommend.test.d.ts.map +1 -0
  268. package/dist/tests/recommend.test.js +208 -0
  269. package/dist/tests/recommend.test.js.map +1 -0
  270. package/dist/tests/suggestions/suggestion-engine.test.d.ts +6 -0
  271. package/dist/tests/suggestions/suggestion-engine.test.d.ts.map +1 -0
  272. package/dist/tests/suggestions/suggestion-engine.test.js +448 -0
  273. package/dist/tests/suggestions/suggestion-engine.test.js.map +1 -0
  274. package/dist/tests/test-utils.d.ts +74 -0
  275. package/dist/tests/test-utils.d.ts.map +1 -0
  276. package/dist/tests/test-utils.js +98 -0
  277. package/dist/tests/test-utils.js.map +1 -0
  278. package/dist/tests/tools.test.d.ts +5 -0
  279. package/dist/tests/tools.test.d.ts.map +1 -0
  280. package/dist/tests/tools.test.js +138 -0
  281. package/dist/tests/tools.test.js.map +1 -0
  282. package/dist/tests/unit/installed-skills.test.d.ts +6 -0
  283. package/dist/tests/unit/installed-skills.test.d.ts.map +1 -0
  284. package/dist/tests/unit/installed-skills.test.js +285 -0
  285. package/dist/tests/unit/installed-skills.test.js.map +1 -0
  286. package/dist/tests/unit/logger.test.d.ts +6 -0
  287. package/dist/tests/unit/logger.test.d.ts.map +1 -0
  288. package/dist/tests/unit/logger.test.js +281 -0
  289. package/dist/tests/unit/logger.test.js.map +1 -0
  290. package/dist/tests/validate.test.d.ts +5 -0
  291. package/dist/tests/validate.test.d.ts.map +1 -0
  292. package/dist/tests/validate.test.js +303 -0
  293. package/dist/tests/validate.test.js.map +1 -0
  294. package/dist/tests/webhooks/proxy-trust.security.test.d.ts +8 -0
  295. package/dist/tests/webhooks/proxy-trust.security.test.d.ts.map +1 -0
  296. package/dist/tests/webhooks/proxy-trust.security.test.js +145 -0
  297. package/dist/tests/webhooks/proxy-trust.security.test.js.map +1 -0
  298. package/dist/tests/webhooks/rate-limiter.security.test.d.ts +8 -0
  299. package/dist/tests/webhooks/rate-limiter.security.test.d.ts.map +1 -0
  300. package/dist/tests/webhooks/rate-limiter.security.test.js +122 -0
  301. package/dist/tests/webhooks/rate-limiter.security.test.js.map +1 -0
  302. package/dist/vitest.config.d.ts +6 -0
  303. package/dist/vitest.config.d.ts.map +1 -0
  304. package/dist/vitest.config.js +13 -0
  305. package/dist/vitest.config.js.map +1 -0
  306. package/package.json +63 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * SMI-583: Logging utility for MCP server
3
+ * SMI-883: Sanitizes sensitive data before logging to prevent data leakage
4
+ * Logs errors to ~/.skillsmith/logs/
5
+ */
6
+ /**
7
+ * SMI-883: Redact sensitive data from text before logging
8
+ * Exported for testing purposes
9
+ */
10
+ export declare function redactSensitiveData(text: string): string;
11
+ /**
12
+ * SMI-883: Recursively redact sensitive data from objects
13
+ * Exported for testing purposes
14
+ */
15
+ export declare function redactSensitiveObject(obj: unknown): unknown;
16
+ /**
17
+ * Logger interface
18
+ */
19
+ export declare const logger: {
20
+ info(message: string, details?: unknown): void;
21
+ warn(message: string, details?: unknown): void;
22
+ error(message: string, details?: unknown): void;
23
+ debug(message: string, details?: unknown): void;
24
+ };
25
+ export default logger;
26
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuEH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASxD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAY3D;AA2DD;;GAEG;AACH,eAAO,MAAM,MAAM;kBACH,MAAM,YAAY,OAAO,GAAG,IAAI;kBAIhC,MAAM,YAAY,OAAO,GAAG,IAAI;mBAI/B,MAAM,YAAY,OAAO,GAAG,IAAI;mBAIhC,MAAM,YAAY,OAAO,GAAG,IAAI;CAKhD,CAAA;AAED,eAAe,MAAM,CAAA"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * SMI-583: Logging utility for MCP server
3
+ * SMI-883: Sanitizes sensitive data before logging to prevent data leakage
4
+ * Logs errors to ~/.skillsmith/logs/
5
+ */
6
+ import { existsSync, mkdirSync, appendFileSync } from 'node:fs';
7
+ import { homedir } from 'node:os';
8
+ import { join } from 'node:path';
9
+ /**
10
+ * SMI-883: Sensitive data patterns to redact before logging
11
+ * Prevents API keys, tokens, passwords, and secrets from being written to disk
12
+ */
13
+ const SENSITIVE_PATTERNS = [
14
+ // GitHub tokens
15
+ { pattern: /\b(ghp_[a-zA-Z0-9]{36})\b/g, replacement: 'ghp_[REDACTED]' },
16
+ { pattern: /\b(github_pat_[a-zA-Z0-9_]{22,})\b/g, replacement: 'github_pat_[REDACTED]' },
17
+ { pattern: /\b(gho_[a-zA-Z0-9]{36})\b/g, replacement: 'gho_[REDACTED]' },
18
+ { pattern: /\b(ghs_[a-zA-Z0-9]{36})\b/g, replacement: 'ghs_[REDACTED]' },
19
+ { pattern: /\b(ghu_[a-zA-Z0-9]{36})\b/g, replacement: 'ghu_[REDACTED]' },
20
+ { pattern: /\b(ghr_[a-zA-Z0-9]{36})\b/g, replacement: 'ghr_[REDACTED]' },
21
+ // Linear API keys
22
+ { pattern: /\b(lin_api_[a-zA-Z0-9]{32,})\b/g, replacement: 'lin_api_[REDACTED]' },
23
+ // Stripe keys
24
+ { pattern: /\b(sk_live_[a-zA-Z0-9]{24,})\b/g, replacement: 'sk_live_[REDACTED]' },
25
+ { pattern: /\b(sk_test_[a-zA-Z0-9]{24,})\b/g, replacement: 'sk_test_[REDACTED]' },
26
+ { pattern: /\b(pk_live_[a-zA-Z0-9]{24,})\b/g, replacement: 'pk_live_[REDACTED]' },
27
+ { pattern: /\b(pk_test_[a-zA-Z0-9]{24,})\b/g, replacement: 'pk_test_[REDACTED]' },
28
+ // OpenAI API keys
29
+ { pattern: /\b(sk-[a-zA-Z0-9]{48,})\b/g, replacement: 'sk-[REDACTED]' },
30
+ // Anthropic API keys
31
+ { pattern: /\b(sk-ant-[a-zA-Z0-9-]{32,})\b/g, replacement: 'sk-ant-[REDACTED]' },
32
+ // AWS keys
33
+ { pattern: /\b(AKIA[A-Z0-9]{16})\b/g, replacement: 'AKIA[REDACTED]' },
34
+ // Slack tokens
35
+ { pattern: /\b(xox[boaprs]-[a-zA-Z0-9-]{10,})\b/g, replacement: 'xox*-[REDACTED]' },
36
+ // npm tokens
37
+ { pattern: /\b(npm_[a-zA-Z0-9]{36})\b/g, replacement: 'npm_[REDACTED]' },
38
+ // Bearer tokens
39
+ { pattern: /\bBearer\s+([a-zA-Z0-9_\-.]{20,})/gi, replacement: 'Bearer [REDACTED]' },
40
+ // Basic auth
41
+ { pattern: /\bBasic\s+([a-zA-Z0-9+/=]{20,})/gi, replacement: 'Basic [REDACTED]' },
42
+ // JWT tokens
43
+ {
44
+ pattern: /\beyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]+\b/g,
45
+ replacement: '[JWT_REDACTED]',
46
+ },
47
+ // Generic API key patterns
48
+ {
49
+ pattern: /\b(api[_-]?key|apikey)\s*[=:]\s*["']?([a-zA-Z0-9_-]{8,})["']?/gi,
50
+ replacement: 'api_key=[REDACTED]',
51
+ },
52
+ {
53
+ pattern: /\b(token|auth[_-]?token)\s*[=:]\s*["']?([a-zA-Z0-9_-]{8,})["']?/gi,
54
+ replacement: 'token=[REDACTED]',
55
+ },
56
+ {
57
+ pattern: /\b(password|passwd|pwd)\s*[=:]\s*["']?([^"'\s]{4,})["']?/gi,
58
+ replacement: 'password=[REDACTED]',
59
+ },
60
+ {
61
+ pattern: /\b(secret|client[_-]?secret)\s*[=:]\s*["']?([a-zA-Z0-9_-]{8,})["']?/gi,
62
+ replacement: 'secret=[REDACTED]',
63
+ },
64
+ // Connection strings with passwords
65
+ { pattern: /(:\/\/[^:]+:)([^@]+)(@)/gi, replacement: '$1[REDACTED]$3' },
66
+ // Private keys
67
+ {
68
+ pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(RSA\s+)?PRIVATE\s+KEY-----/gi,
69
+ replacement: '-----[PRIVATE KEY REDACTED]-----',
70
+ },
71
+ ];
72
+ /**
73
+ * SMI-883: Redact sensitive data from text before logging
74
+ * Exported for testing purposes
75
+ */
76
+ export function redactSensitiveData(text) {
77
+ if (!text)
78
+ return text;
79
+ let redacted = text;
80
+ for (const { pattern, replacement } of SENSITIVE_PATTERNS) {
81
+ // Reset lastIndex for global regex patterns to ensure all matches are found
82
+ pattern.lastIndex = 0;
83
+ redacted = redacted.replace(pattern, replacement);
84
+ }
85
+ return redacted;
86
+ }
87
+ /**
88
+ * SMI-883: Recursively redact sensitive data from objects
89
+ * Exported for testing purposes
90
+ */
91
+ export function redactSensitiveObject(obj) {
92
+ if (obj === null || obj === undefined)
93
+ return obj;
94
+ if (typeof obj === 'string')
95
+ return redactSensitiveData(obj);
96
+ if (Array.isArray(obj))
97
+ return obj.map(redactSensitiveObject);
98
+ if (typeof obj === 'object') {
99
+ const result = {};
100
+ for (const [key, value] of Object.entries(obj)) {
101
+ result[key] = redactSensitiveObject(value);
102
+ }
103
+ return result;
104
+ }
105
+ return obj;
106
+ }
107
+ const LOG_DIR = join(homedir(), '.skillsmith', 'logs');
108
+ /**
109
+ * Ensure log directory exists
110
+ */
111
+ function ensureLogDir() {
112
+ if (!existsSync(LOG_DIR)) {
113
+ mkdirSync(LOG_DIR, { recursive: true });
114
+ }
115
+ }
116
+ /**
117
+ * Format date for log filename
118
+ */
119
+ function getLogFilename() {
120
+ const date = new Date();
121
+ const dateStr = date.toISOString().split('T')[0];
122
+ return join(LOG_DIR, 'mcp-server-' + dateStr + '.log');
123
+ }
124
+ /**
125
+ * Format log entry
126
+ * SMI-883: Sanitizes message and details to prevent sensitive data leakage
127
+ */
128
+ function formatLogEntry(level, message, details) {
129
+ const timestamp = new Date().toISOString();
130
+ // SMI-883: Redact sensitive data from message
131
+ const sanitizedMessage = redactSensitiveData(message);
132
+ let entry = '[' + timestamp + '] [' + level + '] ' + sanitizedMessage;
133
+ if (details !== undefined) {
134
+ try {
135
+ // SMI-883: Redact sensitive data from details object before serialization
136
+ const sanitizedDetails = redactSensitiveObject(details);
137
+ entry += '\n Details: ' + JSON.stringify(sanitizedDetails, null, 2).replace(/\n/g, '\n ');
138
+ }
139
+ catch {
140
+ entry += '\n Details: [Unable to serialize]';
141
+ }
142
+ }
143
+ return entry + '\n';
144
+ }
145
+ /**
146
+ * Write log entry to file
147
+ */
148
+ function writeLog(level, message, details) {
149
+ try {
150
+ ensureLogDir();
151
+ const entry = formatLogEntry(level, message, details);
152
+ appendFileSync(getLogFilename(), entry);
153
+ }
154
+ catch {
155
+ // Silently fail if unable to write logs
156
+ // Don't want logging failures to break the application
157
+ }
158
+ }
159
+ /**
160
+ * Logger interface
161
+ */
162
+ export const logger = {
163
+ info(message, details) {
164
+ writeLog('INFO', message, details);
165
+ },
166
+ warn(message, details) {
167
+ writeLog('WARN', message, details);
168
+ },
169
+ error(message, details) {
170
+ writeLog('ERROR', message, details);
171
+ },
172
+ debug(message, details) {
173
+ if (process.env.DEBUG) {
174
+ writeLog('DEBUG', message, details);
175
+ }
176
+ },
177
+ };
178
+ export default logger;
179
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=csp.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csp.test.d.ts","sourceRoot":"","sources":["../../../../src/middleware/__tests__/csp.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,389 @@
1
+ /**
2
+ * Tests for Content Security Policy middleware and utilities
3
+ */
4
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
5
+ import { DEFAULT_CSP_DIRECTIVES, STRICT_CSP_DIRECTIVES, generateNonce, buildCspHeader, validateCspHeader, validateCspHeaderDetailed, cspMiddleware, getCspForEnvironment, } from '../csp.js';
6
+ describe('CSP Utilities', () => {
7
+ describe('generateNonce', () => {
8
+ it('should generate a nonce', () => {
9
+ const nonce = generateNonce();
10
+ expect(nonce).toBeDefined();
11
+ expect(typeof nonce).toBe('string');
12
+ });
13
+ it('should generate nonces of sufficient length', () => {
14
+ const nonce = generateNonce();
15
+ expect(nonce.length).toBeGreaterThanOrEqual(16);
16
+ });
17
+ it('should generate unique nonces', () => {
18
+ const nonce1 = generateNonce();
19
+ const nonce2 = generateNonce();
20
+ expect(nonce1).not.toBe(nonce2);
21
+ });
22
+ it('should generate valid base64 nonces', () => {
23
+ const nonce = generateNonce();
24
+ // Base64 can include A-Z, a-z, 0-9, +, /, and = for padding
25
+ expect(nonce).toMatch(/^[A-Za-z0-9+/]+=*$/);
26
+ });
27
+ });
28
+ describe('buildCspHeader', () => {
29
+ it('should build a basic CSP header', () => {
30
+ const directives = {
31
+ 'default-src': ["'self'"],
32
+ 'script-src': ["'self'"],
33
+ };
34
+ const header = buildCspHeader(directives);
35
+ expect(header).toContain("default-src 'self'");
36
+ expect(header).toContain("script-src 'self'");
37
+ });
38
+ it('should add nonce to script-src', () => {
39
+ const directives = {
40
+ 'script-src': ["'self'"],
41
+ };
42
+ // Use valid base64 nonce (no hyphens)
43
+ const nonce = 'dGVzdG5vbmNlMTIz';
44
+ const header = buildCspHeader(directives, nonce);
45
+ expect(header).toContain(`'nonce-${nonce}'`);
46
+ });
47
+ it('should add nonce to style-src', () => {
48
+ const directives = {
49
+ 'style-src': ["'self'"],
50
+ };
51
+ // Use valid base64 nonce (no hyphens)
52
+ const nonce = 'dGVzdG5vbmNlMTIz';
53
+ const header = buildCspHeader(directives, nonce);
54
+ expect(header).toContain(`'nonce-${nonce}'`);
55
+ });
56
+ it('should handle boolean directives', () => {
57
+ const directives = {
58
+ 'upgrade-insecure-requests': true,
59
+ 'block-all-mixed-content': true,
60
+ };
61
+ const header = buildCspHeader(directives);
62
+ expect(header).toContain('upgrade-insecure-requests');
63
+ expect(header).toContain('block-all-mixed-content');
64
+ });
65
+ it('should not include false boolean directives', () => {
66
+ const directives = {
67
+ 'upgrade-insecure-requests': false,
68
+ };
69
+ const header = buildCspHeader(directives);
70
+ expect(header).not.toContain('upgrade-insecure-requests');
71
+ });
72
+ it('should handle multiple sources', () => {
73
+ const directives = {
74
+ 'img-src': ["'self'", 'data:', 'https:'],
75
+ };
76
+ const header = buildCspHeader(directives);
77
+ expect(header).toContain("img-src 'self' data: https:");
78
+ });
79
+ it('should use DEFAULT_CSP_DIRECTIVES', () => {
80
+ const header = buildCspHeader(DEFAULT_CSP_DIRECTIVES);
81
+ expect(header).toContain("default-src 'self'");
82
+ expect(header).toContain("script-src 'self'");
83
+ expect(header).toContain("object-src 'none'");
84
+ expect(header).toContain('upgrade-insecure-requests');
85
+ });
86
+ it('should use STRICT_CSP_DIRECTIVES', () => {
87
+ const header = buildCspHeader(STRICT_CSP_DIRECTIVES);
88
+ expect(header).toContain("default-src 'none'");
89
+ expect(header).toContain("script-src 'self'");
90
+ expect(header).toContain("object-src 'none'");
91
+ });
92
+ it('should handle string directives like report-to', () => {
93
+ const directives = {
94
+ 'default-src': ["'self'"],
95
+ 'report-to': 'csp-endpoint',
96
+ };
97
+ const header = buildCspHeader(directives);
98
+ expect(header).toContain('report-to csp-endpoint');
99
+ });
100
+ it('should include all STRICT_CSP_DIRECTIVES values', () => {
101
+ const header = buildCspHeader(STRICT_CSP_DIRECTIVES);
102
+ expect(header).toContain("worker-src 'none'");
103
+ expect(header).toContain("form-action 'none'");
104
+ expect(header).toContain("frame-ancestors 'none'");
105
+ expect(header).toContain("base-uri 'none'");
106
+ expect(header).toContain("manifest-src 'self'");
107
+ expect(header).toContain("require-trusted-types-for 'script'");
108
+ });
109
+ it('should properly format nonce in script-src', () => {
110
+ const directives = {
111
+ 'script-src': ["'self'"],
112
+ };
113
+ const nonce = 'abc123XYZ';
114
+ const header = buildCspHeader(directives, nonce);
115
+ expect(header).toBe("script-src 'self' 'nonce-abc123XYZ'");
116
+ });
117
+ });
118
+ describe('validateCspHeader', () => {
119
+ it('should validate a proper CSP header', () => {
120
+ const header = "default-src 'self'; script-src 'self'";
121
+ expect(validateCspHeader(header)).toBe(true);
122
+ });
123
+ it('should reject empty CSP', () => {
124
+ expect(validateCspHeader('')).toBe(false);
125
+ });
126
+ it('should reject non-string CSP', () => {
127
+ expect(validateCspHeader(null)).toBe(false);
128
+ expect(validateCspHeader(undefined)).toBe(false);
129
+ expect(validateCspHeader(123)).toBe(false);
130
+ });
131
+ it('should warn about unsafe-eval', () => {
132
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
133
+ const header = "script-src 'self' 'unsafe-eval'";
134
+ validateCspHeader(header);
135
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('unsafe-eval'));
136
+ consoleSpy.mockRestore();
137
+ });
138
+ it('should warn about unsafe-inline without nonce', () => {
139
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
140
+ const header = "script-src 'self' 'unsafe-inline'";
141
+ validateCspHeader(header);
142
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('unsafe-inline'));
143
+ consoleSpy.mockRestore();
144
+ });
145
+ it('should not warn about unsafe-inline with nonce', () => {
146
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
147
+ const header = "script-src 'self' 'unsafe-inline' 'nonce-abc123'";
148
+ validateCspHeader(header);
149
+ expect(consoleSpy).not.toHaveBeenCalled();
150
+ consoleSpy.mockRestore();
151
+ });
152
+ it('should reject CSP without directives', () => {
153
+ const header = 'not a valid csp';
154
+ expect(validateCspHeader(header)).toBe(false);
155
+ });
156
+ it('should accept sandbox as a valid directive', () => {
157
+ const header = 'sandbox allow-scripts';
158
+ expect(validateCspHeader(header)).toBe(true);
159
+ });
160
+ });
161
+ describe('validateCspHeaderDetailed', () => {
162
+ it('should return detailed validation result for valid CSP', () => {
163
+ const header = "default-src 'self'; script-src 'self'";
164
+ const result = validateCspHeaderDetailed(header);
165
+ expect(result.valid).toBe(true);
166
+ expect(result.errors).toHaveLength(0);
167
+ });
168
+ it('should return error for empty CSP', () => {
169
+ const result = validateCspHeaderDetailed('');
170
+ expect(result.valid).toBe(false);
171
+ expect(result.errors).toContain('CSP header must be a non-empty string');
172
+ });
173
+ it('should warn about wildcard in script-src', () => {
174
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
175
+ const header = "script-src 'self' *";
176
+ const result = validateCspHeaderDetailed(header);
177
+ expect(result.warnings).toContain('Wildcard (*) in script-src is overly permissive');
178
+ consoleSpy.mockRestore();
179
+ });
180
+ it('should warn about data: URI in script-src', () => {
181
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
182
+ const header = "script-src 'self' data:";
183
+ const result = validateCspHeaderDetailed(header);
184
+ expect(result.warnings).toContain('data: URI in script-src allows XSS attacks');
185
+ consoleSpy.mockRestore();
186
+ });
187
+ it('should warn about missing default-src', () => {
188
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
189
+ const header = "script-src 'self'";
190
+ const result = validateCspHeaderDetailed(header);
191
+ expect(result.warnings).toContain('Missing default-src - other directives may fall back to permissive defaults');
192
+ consoleSpy.mockRestore();
193
+ });
194
+ it('should include warning details for unsafe-eval', () => {
195
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
196
+ const header = "default-src 'self'; script-src 'self' 'unsafe-eval'";
197
+ const result = validateCspHeaderDetailed(header);
198
+ // Updated warning message for per-directive validation
199
+ expect(result.warnings).toContain('unsafe-eval detected in script-src or default-src - allows arbitrary code execution');
200
+ consoleSpy.mockRestore();
201
+ });
202
+ it('should include warning details for unsafe-inline without nonce', () => {
203
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
204
+ const header = "default-src 'self'; script-src 'self' 'unsafe-inline'";
205
+ const result = validateCspHeaderDetailed(header);
206
+ // Updated warning message for per-directive validation
207
+ expect(result.warnings).toContain('unsafe-inline without nonce in script-src - vulnerable to XSS');
208
+ consoleSpy.mockRestore();
209
+ });
210
+ it('should not warn about unsafe-inline when nonce is present', () => {
211
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
212
+ const header = "default-src 'self'; script-src 'self' 'unsafe-inline' 'nonce-abc123'";
213
+ const result = validateCspHeaderDetailed(header);
214
+ // Updated warning message check
215
+ expect(result.warnings).not.toContain('unsafe-inline without nonce in script-src - vulnerable to XSS');
216
+ consoleSpy.mockRestore();
217
+ });
218
+ });
219
+ describe('cspMiddleware', () => {
220
+ let mockReq;
221
+ let mockRes;
222
+ let mockNext;
223
+ beforeEach(() => {
224
+ mockReq = {};
225
+ mockRes = {
226
+ setHeader: vi.fn(),
227
+ locals: {},
228
+ };
229
+ mockNext = vi.fn();
230
+ });
231
+ it('should set CSP header', () => {
232
+ const middleware = cspMiddleware();
233
+ middleware(mockReq, mockRes, mockNext);
234
+ expect(mockRes.setHeader).toHaveBeenCalledWith('Content-Security-Policy', expect.any(String));
235
+ });
236
+ it('should add nonce to response locals', () => {
237
+ const middleware = cspMiddleware();
238
+ middleware(mockReq, mockRes, mockNext);
239
+ expect(mockRes.locals.cspNonce).toBeDefined();
240
+ expect(typeof mockRes.locals.cspNonce).toBe('string');
241
+ });
242
+ it('should call next', () => {
243
+ const middleware = cspMiddleware();
244
+ middleware(mockReq, mockRes, mockNext);
245
+ expect(mockNext).toHaveBeenCalled();
246
+ });
247
+ it('should use custom directives', () => {
248
+ const customDirectives = {
249
+ 'default-src': ["'none'"],
250
+ };
251
+ const middleware = cspMiddleware(customDirectives);
252
+ middleware(mockReq, mockRes, mockNext);
253
+ const cspHeader = mockRes.setHeader.mock.calls[0][1];
254
+ expect(cspHeader).toContain("default-src 'none'");
255
+ });
256
+ it('should create locals object if missing', () => {
257
+ mockRes.locals = undefined;
258
+ const middleware = cspMiddleware();
259
+ middleware(mockReq, mockRes, mockNext);
260
+ expect(mockRes.locals).toBeDefined();
261
+ expect(mockRes.locals.cspNonce).toBeDefined();
262
+ });
263
+ });
264
+ describe('getCspForEnvironment', () => {
265
+ it('should return strict CSP for production', () => {
266
+ const csp = getCspForEnvironment('production');
267
+ expect(csp['default-src']).toEqual(["'none'"]);
268
+ });
269
+ it('should return strict CSP by default', () => {
270
+ const csp = getCspForEnvironment();
271
+ expect(csp['default-src']).toEqual(["'none'"]);
272
+ });
273
+ it('should allow unsafe-eval for development', () => {
274
+ const csp = getCspForEnvironment('development');
275
+ expect(csp['script-src']).toContain("'unsafe-eval'");
276
+ });
277
+ it('should be permissive for test environment', () => {
278
+ const csp = getCspForEnvironment('test');
279
+ expect(csp['script-src']).toContain("'unsafe-inline'");
280
+ expect(csp['script-src']).toContain("'unsafe-eval'");
281
+ expect(csp['style-src']).toContain("'unsafe-inline'");
282
+ });
283
+ });
284
+ describe('Security Requirements', () => {
285
+ it('should not allow unsafe-eval in production', () => {
286
+ const csp = getCspForEnvironment('production');
287
+ const header = buildCspHeader(csp);
288
+ expect(header).not.toContain("'unsafe-eval'");
289
+ });
290
+ it('should not allow unsafe-inline in production', () => {
291
+ const csp = getCspForEnvironment('production');
292
+ const header = buildCspHeader(csp);
293
+ expect(header).not.toContain("'unsafe-inline'");
294
+ });
295
+ it('should block object-src in all environments', () => {
296
+ const prodCsp = getCspForEnvironment('production');
297
+ const devCsp = getCspForEnvironment('development');
298
+ const testCsp = getCspForEnvironment('test');
299
+ expect(prodCsp['object-src']).toEqual(["'none'"]);
300
+ expect(devCsp['object-src']).toEqual(["'none'"]);
301
+ expect(testCsp['object-src']).toEqual(["'none'"]);
302
+ });
303
+ it('should upgrade insecure requests in production', () => {
304
+ const csp = getCspForEnvironment('production');
305
+ expect(csp['upgrade-insecure-requests']).toBe(true);
306
+ });
307
+ it('should block mixed content in production', () => {
308
+ const csp = getCspForEnvironment('production');
309
+ expect(csp['block-all-mixed-content']).toBe(true);
310
+ });
311
+ it('should prevent frame embedding in production', () => {
312
+ const csp = getCspForEnvironment('production');
313
+ expect(csp['frame-ancestors']).toEqual(["'none'"]);
314
+ });
315
+ it('should restrict base-uri in production to prevent base tag injection', () => {
316
+ const csp = getCspForEnvironment('production');
317
+ expect(csp['base-uri']).toEqual(["'none'"]);
318
+ });
319
+ it('should include require-trusted-types-for in strict mode', () => {
320
+ expect(STRICT_CSP_DIRECTIVES['require-trusted-types-for']).toEqual(["'script'"]);
321
+ });
322
+ it('should restrict manifest-src in strict mode', () => {
323
+ expect(STRICT_CSP_DIRECTIVES['manifest-src']).toEqual(["'self'"]);
324
+ });
325
+ it('should block all frame-src in strict mode', () => {
326
+ expect(STRICT_CSP_DIRECTIVES['frame-src']).toEqual(["'none'"]);
327
+ });
328
+ it('should block all workers in strict mode', () => {
329
+ expect(STRICT_CSP_DIRECTIVES['worker-src']).toEqual(["'none'"]);
330
+ });
331
+ it('should have restrictive form-action in strict mode', () => {
332
+ expect(STRICT_CSP_DIRECTIVES['form-action']).toEqual(["'none'"]);
333
+ });
334
+ it('should generate cryptographically unique nonces', () => {
335
+ // Generate multiple nonces and ensure they are all unique
336
+ const nonces = new Set();
337
+ for (let i = 0; i < 100; i++) {
338
+ nonces.add(generateNonce());
339
+ }
340
+ expect(nonces.size).toBe(100);
341
+ });
342
+ it('should have nonces with sufficient entropy', () => {
343
+ const nonce = generateNonce();
344
+ // Base64 of 16 bytes = 24 characters (with padding)
345
+ // Without padding, it could be 22 characters
346
+ expect(nonce.length).toBeGreaterThanOrEqual(22);
347
+ });
348
+ });
349
+ describe('Directive Configuration', () => {
350
+ it('should include all required security directives in DEFAULT_CSP_DIRECTIVES', () => {
351
+ const requiredDirectives = [
352
+ 'default-src',
353
+ 'script-src',
354
+ 'style-src',
355
+ 'img-src',
356
+ 'connect-src',
357
+ 'frame-ancestors',
358
+ 'base-uri',
359
+ 'form-action',
360
+ ];
361
+ for (const directive of requiredDirectives) {
362
+ expect(DEFAULT_CSP_DIRECTIVES).toHaveProperty(directive);
363
+ }
364
+ });
365
+ it('should include all required security directives in STRICT_CSP_DIRECTIVES', () => {
366
+ const requiredDirectives = [
367
+ 'default-src',
368
+ 'script-src',
369
+ 'style-src',
370
+ 'img-src',
371
+ 'connect-src',
372
+ 'frame-ancestors',
373
+ 'base-uri',
374
+ 'form-action',
375
+ 'object-src',
376
+ 'frame-src',
377
+ 'worker-src',
378
+ ];
379
+ for (const directive of requiredDirectives) {
380
+ expect(STRICT_CSP_DIRECTIVES).toHaveProperty(directive);
381
+ }
382
+ });
383
+ it('should have object-src set to none in both default and strict', () => {
384
+ expect(DEFAULT_CSP_DIRECTIVES['object-src']).toEqual(["'none'"]);
385
+ expect(STRICT_CSP_DIRECTIVES['object-src']).toEqual(["'none'"]);
386
+ });
387
+ });
388
+ });
389
+ //# sourceMappingURL=csp.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csp.test.js","sourceRoot":"","sources":["../../../../src/middleware/__tests__/csp.test.ts"],"names":[],"mappings":"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"}