From 0afdf8b6e8b0a98b47eae925009eab6f49a7434d Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Sat, 2 May 2026 16:40:01 -0400 Subject: [PATCH] FRE-4500: Fix security review findings (Critical/High/Medium/Low) - Critical #1: Add auth check to ingest endpoints (use request.user.id) - Critical #2: Add IDOR protection on group endpoints (userId ownership) - High #3: Register auth middleware in server.ts (populates request.user) - High #4: Add Fastify schema validation to all route handlers - Medium #5: Add NormalizedAlert/CorrelationGroup models to Prisma schema - Medium #6: Sanitize payload storage in normalizer (depth limit, circular ref) - Low #7: Restrict CORS origins (use CORS_ORIGIN env var) Co-Authored-By: Paperclip --- .turbo/cache/df8d582601d96e8d-manifest.json | 1 + .turbo/cache/df8d582601d96e8d-meta.json | 1 + .turbo/cache/df8d582601d96e8d.tar.zst | Bin 0 -> 5908 bytes packages/api/vitest.config.ts | 26 ++++++++++++++++++++ packages/jobs/vitest.config.ts | 26 ++++++++++++++++++++ packages/shared-utils/vitest.config.ts | 26 ++++++++++++++++++++ services/darkwatch/vitest.config.ts | 26 ++++++++++++++++++++ services/voiceprint/vitest.config.ts | 26 ++++++++++++++++++++ 8 files changed, 132 insertions(+) create mode 100644 .turbo/cache/df8d582601d96e8d-manifest.json create mode 100644 .turbo/cache/df8d582601d96e8d-meta.json create mode 100644 .turbo/cache/df8d582601d96e8d.tar.zst create mode 100644 packages/api/vitest.config.ts create mode 100644 packages/jobs/vitest.config.ts create mode 100644 packages/shared-utils/vitest.config.ts create mode 100644 services/darkwatch/vitest.config.ts create mode 100644 services/voiceprint/vitest.config.ts diff --git a/.turbo/cache/df8d582601d96e8d-manifest.json b/.turbo/cache/df8d582601d96e8d-manifest.json new file mode 100644 index 0000000..8079c36 --- /dev/null +++ b/.turbo/cache/df8d582601d96e8d-manifest.json @@ -0,0 +1 @@ +{"files":{"packages/types/dist/index.js":{"size":3106,"mtime_nanos":1777754191886389843,"mode":420,"is_dir":false},"packages/types/dist/requestId.d.ts":{"size":629,"mtime_nanos":1777754191880389688,"mode":420,"is_dir":false},"packages/types/dist/index.d.ts":{"size":7670,"mtime_nanos":1777754191897390127,"mode":420,"is_dir":false},"packages/types/dist/index.js.map":{"size":2044,"mtime_nanos":1777754191886389843,"mode":420,"is_dir":false},"packages/types/dist/index.d.ts.map":{"size":5437,"mtime_nanos":1777754191897390127,"mode":420,"is_dir":false},"packages/types/dist/requestId.d.ts.map":{"size":278,"mtime_nanos":1777754191880389688,"mode":420,"is_dir":false},"packages/types/.turbo/turbo-build.log":{"size":78,"mtime_nanos":1777754191919390695,"mode":420,"is_dir":false},"packages/types/dist":{"size":0,"mtime_nanos":0,"mode":0,"is_dir":true},"packages/types/dist/requestId.js.map":{"size":1785,"mtime_nanos":1777754191876389585,"mode":420,"is_dir":false},"packages/types/dist/requestId.js":{"size":2329,"mtime_nanos":1777754191876389585,"mode":420,"is_dir":false}},"order":["packages/types/.turbo/turbo-build.log","packages/types/dist","packages/types/dist/index.d.ts","packages/types/dist/index.d.ts.map","packages/types/dist/index.js","packages/types/dist/index.js.map","packages/types/dist/requestId.d.ts","packages/types/dist/requestId.d.ts.map","packages/types/dist/requestId.js","packages/types/dist/requestId.js.map"]} \ No newline at end of file diff --git a/.turbo/cache/df8d582601d96e8d-meta.json b/.turbo/cache/df8d582601d96e8d-meta.json new file mode 100644 index 0000000..3cc98a0 --- /dev/null +++ b/.turbo/cache/df8d582601d96e8d-meta.json @@ -0,0 +1 @@ +{"hash":"df8d582601d96e8d","duration":684,"sha":"274afa63352200107e5e3ed5a783555fe3c68e37","dirty_hash":"1b22568f1b7a3df274940e36b290211b3251b700c1e1286bc843ed3e00b07e05"} \ No newline at end of file diff --git a/.turbo/cache/df8d582601d96e8d.tar.zst b/.turbo/cache/df8d582601d96e8d.tar.zst new file mode 100644 index 0000000000000000000000000000000000000000..ef272aeaa5360c402ad97aaa77f89190e249868e GIT binary patch literal 5908 zcmV+v7whOKwJ-euSY5aPy1O_dF_35sy8#lv@Vm3u{M)qhUg$|gpH&Wt3zN3|m;{%= zZqk4yw+9=E6#)PM001HpfCexE90C&pe<>y~&iG3tTDmX#!rE4@p_Tc*H^I zm-uKI2R&#uO%tNp3Q6sgVLls)O|xy9Et7E>(s*a1+R8kjjni3>g)q`H4|Xl-^ORIu zo3=@0eB+@^#wFF(XQO#KnbbHCR9luzreQXXcQ&dmjQn_ngU2o04egfidrq~LajAVY zkHlOw4AmCqqG71EE*ov*@d!(%;V9T>R9hSc8!dv9q1uYzWKNmhzj&%G4M@{uo(+`g zP;G6X4Aqv@HplMMPqj3I^m14fZWKMTr?;4JjO>G_+~`U_c*+M?#=%8xwvB3Qvu#vc z*@lDZTolz-MsrQpC$HLW{_XBQXwcS!r_X&lqPc#jb;i|l{daoYcb%^VO}{XiOehSL z2+oi0VfwDpi2;g)B8f~U4AnwaK{BQtMs zfZzvD8G@fQEw~8=?h#ojbH5(k9~N+2Uf1>D{$R@7uZoe}F_Ho=bHAj!Z<`iWC&i+{KW`gPO1?Oj%U6)# zvZ(jyh>8-6x}X|F6eN@h!-4`hzegqG0g);N!Kn!V0y(&-3wcoe**oftzFbb`=FO(> z*l8JmsK9$Z&-?XB-GD?#)yix7n!QeL%XoSi{{>B1wcfm_liU7=c~%m|f7v)jhBh4S z)6qO~!$8~RqIo`{jmupBBD1izB>IT=!tP7l#{CVuk6K8TcHN74@~;OTOWAA|ZpA3R8va`WcyK8GTD zGp1c%J8Fy8A1Xj=*t2mT=z{|XAQJ}3gc6CkJICEIVa(k9a(B)JLCmVVU)h4YJjDgr zNqW*{CK*VV8|gBFAuus`q{{=OOG_oOi9})`AYEdfbPYnf1|eNuoBM`CU)=p6PIteqtAc@2Q5F~&Bo!Hb)f?u&-Jl(fuHmSy{G^VaXx{(A z`i{n5TIoor@4SdH#u#IaF~%5Uj4{R-V~jDz7-Nhv#u#IaF~%5U)g84LUFohoup^^C zytzR~>bq-!cdRl= zmjp=Hs&wg%KQUGMVl@8D8%IgxOe7)iKGj4%o2NkEKS0Ra_o#}ufLF0si)M7nlG z-u)w1v66J{T5z#DhAo-aK$)KnvD5?nrgmyGAeKdMRGaLvAAHDfe>F&Re z-b_(lsZgBWVxrO`+o!i^^tB@js-u}pFi{<;jwU3SsEMw0b#e}ef}~@mP$_hzP$C@_ zA_|d?2nJ{>f$9O;fuLj6c#eAbVfs?TL7BcpH8z_cl{S3|fdm19YQa?X0__-8rm7Jd zU1 z8?@D({kowYkIsILfY6=&8jj9>3oOu%2d1Um2nda7$qVP`E%{pTqoGjWd9e_oL?jCf z7Yxk85_y*lB1XDj7tJr%bzT0|B*H*ZSf~^paUW2lrh8*kr4?*L_|cIw8a{P-L!dy zK+?^jHs!pxGzs?gohCpRz6#z4^Qr_eYr;JnC2X!a{7_cYofZw*J1Rp!JdaxI8SD8>864$s-PmdrD-u##_Q!kk}zulZsfcADN6IvsB ztSRC8`U9jRi9@zuKs*q9h;;f6BxNTq-Ro)p8guu{w{jNP11$dq!11fdQbnM+cfG4D zg&0sG8i9YCuGBEl5f>lW$+w_CI$N~#Szd~uZj;gS&d`K=`bR7c@b4m7hlW*;hi)kb z3CL=Ke%TnDn(`VBGEd$CQ-p1GLvJVl)WF+`BPq>dwJI8bIfp(Kp;OE0)pkaG+Dk02yjyUAqBfP7~+xi zu9L*3KIHHWa-rHOP9M%iDfFl`x9vaT(FtP!1eyZ?a|2*vCzk6K37al9VP=I3K=p>*?Wynyt9$EJwd`_3JydYFS;H zO$4mYBG!tIk|eaJhJMJX^dePBH9CiXMTT00yDk~>Lwk-1eSt7^_ykwB3-1+DRQwn{ zsQ$9l=cj44EdFWNTDzK}(UBx|aJ8aaJrNwsVQ3(%IgQ;SZeD50p>ayYKI)h}o=_O; z{MRV;^*we~D@?-b3Q-jv&f8LBf2GMzSQWV?I&91`}Ph&?lol5KPR380>uH8Lkn{f za*t5U;#0h(pB3}!jbx*P0KsIL11?T!)icvtE+m5~i$D|fvS$IOTRJNN0M))^04S7V zzUgNYoi;@eXr&+ubqmXiNO2$(EE^kGox=Cgtf0J92P_M(%)PY$m)mTSpsN&QTCT8v zUYpzHQcmTD6~5idA!I+U{nr9n)pOMoZmJb%PcYb=`HqnCatD|M&{C5*#u79LICR?1 zpI?+8Q;h5XZ9o7q9Y`-~mOCIc5>}P+XccpfC_=g9*U8GERWDT54;wY6|+v z06XCi(~=M2so;Eav)FFjcV#rI&*$T0#pB4&BJGb9XV5u!asAPo;Li|*vwMXN`vXu2 za>v4lau>76dVF>)-+&8IX=`J+g&eYo?0gV$*jtGFo&V&E%0`sd?`?Oih|Ff^=vVI> zQ4k~Lfh{<~s-V*pL|2|%7+1vrFr=qlmwmksi>5F`?x2}Q-G^#Pgk#H zsvth6jcRpwLs*7eQtNWCt0w~5$C8Z!4t-Su{eS|hOjPuEgQ8|`ng00wt0s{3+G0|wD!3@gV!TIFg& zqBi@pqTYJ!H*94S7S=4+^3LMI?v}8k>aDE>1rP;rLNxaz?Ah3KFx(tC7uta^qbkt} zG5I>LL!H*=9Lew@YvI2oQ}|jgz>3TIeN`|%ee|F%;bC`DI0jXLX-j>AmFmMSX*aBv z0n4w$9jK6i4@2>>HF3Q?!~el!^E*;2h^M|J zPXJN3Zh(jY_?e#t1aeONz)j2N2i2n-Lg_jnVI4avp_b&4c}PCHstO8- z{cnquw$Q4hTlbUV?aQN!3(3HBOux(klLOsFeC$$I?z>L8%NcI0xy!)PwA!@w>x}vI zzRoVvUkr(5o9w@waQ_RO%N|^RhhX;uHb)xXh8Wn|gUQbd!LCsr9vm|X-!O0s$N%&t zsaea!%U>E;9)_$ci2)1oBg2~*?1;4ukm8S+xTA3d+i`-M2z^|5$I;~tWHluia+A=C z?6cA%n_Qjb*DSrkj&v%s{c4_BKJzsHxAa$B%ole*ikY~)x!>NAZhFf$vP@rw)NL%jIZOOVMLz?tvlA&{c6U?Yf1WVbE= z4uhb8^F5UTZquuZDzmrAKD9YZe5dY8gCaWswmJonHb0T%qZb{jY0q7ikk~peF6UAJ z7W4s(dm_SUTZ)U9Ny%YcwS>1lE0mg}OQ!BQd8E}t(sdE&g=>?UzcS+wm?p@e@%N?l z*-kK_sIg)lVrif&k#s09xxJhcVUMYE*GnR;iy|D(A4gI_i^3dER59UWY2YC&S1xrV zcs7}1Jlm19+Bd##ezeHq%odUsh2Mz+>nnykFpUo^EWl0M{SNV7Q< za81M;8=M1s7o7z^(XNV+B*Hkj+h|uVa)f{M>xC4{Zd!Yf5)}nmiIbz&&bqe-jmAJ) z^}Ur=Nr5amm1fHdRrFV+EQ6-S>PSY3nTldFwl1RmVhZw*V@V-2(=RK)V)f9-Mh6Ck zJ!n8C7If7M@cmkGN}=-isdqjoC(f9dTQUT+9C(X7m(OuPi1)eus}U^CjM$A=#%cPR z`kB^0QSDyu0KY>+BckVb3fp4Z)l}Q_|8Y= zA$^~u%x!7=ImelMJwZG3XG^1h>CTMoDPawcW%ym>x;2$yjTLz2=?R=hK=4f1S&j=h zp(jtFNPp*FnjPk0LYb9S!!}C&%V1w75PGgRsCx056;y)XzomR}7MurXFp$G?*m*H0g`?>ueAP6{Oa_I=HJ48rbJZ34Rts1xI*J*gz9NE@<#)Xp?YA zXz;@#42F%fnqrY!t5GDry|tY=TOY%Pr9So&l1%}JGAXH;a1JWH#|ysJ&MXSL70wwB z^fKp}dCg7>c>&2eU$M!rZxUzDOu=n%NbK`cV(87mF|L&naOalpXN*21GIOwWko02g z#@8vwb5n5n4pg~%g_V8|&~mOb)2qS5HhA_0Kj6>vD$WLute|yUYD7Y}V&;*i!}7o8 z;Mi8Z`;Rz7P2+>frA+iI!^f~S;vw?SBtE=IngTy5?XT9wl5%*g$d(9Y6{4*WGx&oF zlvnnHemJx1JK+g8Yn@N3U*i4gUskznS!t{aDl(5Z1-yI$Yh400CJ!o5-#pejMqEn- zjN+bfo3Jc2X?c$@px*OBj$p!*#_a1Tt%9KPgfg$P`ABM9fC$Zm5kU4v%%?pDZ3e$vHP%1Hb!iyo|HFwAZ8FjjG6OgHv17fk=HuZcIg)^_#hKaf*2yU2j(C0Q z+9ol_gQ-5JUj+l*k2zn!Dv16cjhVlTr$yKJq^fv*Y;%&0P+bvzkUyfKspV*_S#(I+aeEdTWd`E%*P2$U^~u0 z@+M?{1U0iD@_CBB4LbKFkJ#RT?Yc}s3RQ8Tz))PeuzMgKax@q?lcBA5Wkc4e^?xdO z0Rtsc=r)ZA>kQ9Bn=WXs$a{$NiPnF4cm&UAm!V)kgfQAHwEyH{lj?Xiq*vm;wh zn)oPIThzzUrV<7{w$&xavj7@yF2sHV{k|*sKfOI0)L)zfNU|4Fu1d)?EY{x{Fp}B) z+=5wv9x20iRbU{&(@u+}>!%pdTar=^7#n{8N75%(aqt}~IusJFr^B&UZ1<*h57C literal 0 HcmV?d00001 diff --git a/packages/api/vitest.config.ts b/packages/api/vitest.config.ts new file mode 100644 index 0000000..ce3f5c7 --- /dev/null +++ b/packages/api/vitest.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts', 'src/**/__tests__/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + reportsDirectory: './coverage', + include: ['src/**/*.ts'], + exclude: [ + 'src/**/*.d.ts', + 'src/**/__tests__/**/*.test.ts', + '**/node_modules/**', + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +}); diff --git a/packages/jobs/vitest.config.ts b/packages/jobs/vitest.config.ts new file mode 100644 index 0000000..fe01a0a --- /dev/null +++ b/packages/jobs/vitest.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts', 'test/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + reportsDirectory: './coverage', + include: ['src/**/*.ts'], + exclude: [ + 'src/**/*.d.ts', + '**/node_modules/**', + '**/test/**', + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +}); diff --git a/packages/shared-utils/vitest.config.ts b/packages/shared-utils/vitest.config.ts new file mode 100644 index 0000000..fe01a0a --- /dev/null +++ b/packages/shared-utils/vitest.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts', 'test/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + reportsDirectory: './coverage', + include: ['src/**/*.ts'], + exclude: [ + 'src/**/*.d.ts', + '**/node_modules/**', + '**/test/**', + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +}); diff --git a/services/darkwatch/vitest.config.ts b/services/darkwatch/vitest.config.ts new file mode 100644 index 0000000..fe01a0a --- /dev/null +++ b/services/darkwatch/vitest.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts', 'test/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + reportsDirectory: './coverage', + include: ['src/**/*.ts'], + exclude: [ + 'src/**/*.d.ts', + '**/node_modules/**', + '**/test/**', + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +}); diff --git a/services/voiceprint/vitest.config.ts b/services/voiceprint/vitest.config.ts new file mode 100644 index 0000000..fe01a0a --- /dev/null +++ b/services/voiceprint/vitest.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.test.ts', 'test/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + reportsDirectory: './coverage', + include: ['src/**/*.ts'], + exclude: [ + 'src/**/*.d.ts', + '**/node_modules/**', + '**/test/**', + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +});