11'use strict'
22
3+ const rfdc = require ( 'rfdc' ) ( { proto : false , circles : false } )
34const NoopAIGuard = require ( './noop' )
45const executeRequest = require ( './client' )
56const {
@@ -22,10 +23,11 @@ const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
2223const ALLOW = 'ALLOW'
2324
2425class AIGuardAbortError extends Error {
25- constructor ( reason ) {
26+ constructor ( reason , tags ) {
2627 super ( reason )
2728 this . name = 'AIGuardAbortError'
2829 this . reason = reason
30+ this . tags = tags
2931 }
3032}
3133
@@ -77,20 +79,26 @@ class AIGuard extends NoopAIGuard {
7779 this . #initialized = true
7880 }
7981
80- #truncate ( messages ) {
82+ /**
83+ * Returns a safe copy of the messages to be serialized into the meta struct.
84+ *
85+ * - Clones each message so callers cannot mutate the data set in the meta struct.
86+ * - Truncates the list of messages and `content` fields emitting metrics accordingly.
87+ */
88+ #buildMessagesForMetaStruct ( messages ) {
8189 const size = Math . min ( messages . length , this . #maxMessagesLength)
8290 if ( messages . length > size ) {
8391 appsecMetrics . count ( AI_GUARD_TELEMETRY_TRUNCATED , { type : 'messages' } ) . inc ( 1 )
8492 }
85- const result = messages . slice ( - size )
86-
93+ const result = [ ]
8794 let contentTruncated = false
88- for ( let i = 0 ; i < size ; i ++ ) {
89- const message = result [ i ]
95+ for ( let i = messages . length - size ; i < messages . length ; i ++ ) {
96+ const message = rfdc ( messages [ i ] )
9097 if ( message . content ?. length > this . #maxContentSize) {
9198 contentTruncated = true
92- result [ i ] = { ... message , content : message . content . slice ( 0 , this . #maxContentSize) }
99+ message . content = message . content . slice ( 0 , this . #maxContentSize)
93100 }
101+ result . push ( message )
94102 }
95103 if ( contentTruncated ) {
96104 appsecMetrics . count ( AI_GUARD_TELEMETRY_TRUNCATED , { type : 'content' } ) . inc ( 1 )
@@ -139,7 +147,7 @@ class AIGuard extends NoopAIGuard {
139147 }
140148 }
141149 const metaStruct = {
142- messages : this . #truncate ( messages )
150+ messages : this . #buildMessagesForMetaStruct ( messages )
143151 }
144152 span . meta_struct = {
145153 [ AI_GUARD_META_STRUCT_KEY ] : metaStruct
@@ -192,9 +200,9 @@ class AIGuard extends NoopAIGuard {
192200 }
193201 if ( shouldBlock ) {
194202 span . setTag ( AI_GUARD_BLOCKED_TAG_KEY , 'true' )
195- throw new AIGuardAbortError ( reason )
203+ throw new AIGuardAbortError ( reason , tags )
196204 }
197- return { action, reason }
205+ return { action, reason, tags }
198206 } )
199207 }
200208}
0 commit comments