Skip to content

Commit 39d55ab

Browse files
authored
Attach SDS findings to ai_guard spans (#10721)
Attach SDS findings to ai_guard spans Co-authored-by: oceane.bordeau <oceane.bordeau@datadoghq.com>
1 parent 6282d6b commit 39d55ab

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

dd-java-agent/agent-aiguard/src/main/java/com/datadog/aiguard/AIGuardInternal.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public BadConfigurationException(final String message) {
7272
static final String META_STRUCT_TAG = "ai_guard";
7373
static final String META_STRUCT_MESSAGES = "messages";
7474
static final String META_STRUCT_CATEGORIES = "attack_categories";
75+
static final String META_STRUCT_SDS = "sds";
7576

7677
public static void install() {
7778
final Config config = Config.get();
@@ -252,13 +253,18 @@ public Evaluation evaluate(final List<Message> messages, final Options options)
252253
final String reason = (String) result.get("reason");
253254
@SuppressWarnings("unchecked")
254255
final List<String> tags = (List<String>) result.get("tags");
256+
@SuppressWarnings("unchecked")
257+
final List<?> sdsFindings = (List<?>) result.get("sds_findings");
255258
span.setTag(ACTION_TAG, action);
256259
if (reason != null) {
257260
span.setTag(REASON_TAG, reason);
258261
}
259262
if (tags != null && !tags.isEmpty()) {
260263
metaStruct.put(META_STRUCT_CATEGORIES, tags);
261264
}
265+
if (sdsFindings != null && !sdsFindings.isEmpty()) {
266+
metaStruct.put(META_STRUCT_SDS, sdsFindings);
267+
}
262268
final boolean shouldBlock =
263269
isBlockingEnabled(options, result.get("is_blocking_enabled")) && action != Action.ALLOW;
264270
WafMetricCollector.get().aiGuardRequest(action, shouldBlock);

dd-java-agent/agent-aiguard/src/test/groovy/com/datadog/aiguard/AIGuardInternalTests.groovy

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,57 @@ class AIGuardInternalTests extends DDSpecification {
344344
messages << [[], null]
345345
}
346346

347+
void 'test evaluate with sds findings'() {
348+
given:
349+
final sdsFindings = [
350+
[
351+
rule_display_name: 'Credit Card Number',
352+
rule_tag: 'credit_card',
353+
category: 'pii',
354+
matched_text: '4111111111111111',
355+
location: [start_index: 10, end_index_exclusive: 26, path: 'messages[0].content[0].text']
356+
],
357+
[
358+
rule_display_name: 'Social Security Number',
359+
rule_tag: 'ssn',
360+
category: 'pii',
361+
matched_text: '123-45-6789',
362+
location: [start_index: 30, end_index_exclusive: 41, path: 'messages[1].tool_calls[0].function.arguments']
363+
]
364+
]
365+
final aiguard = mockClient(200, [data: [attributes: [action: 'ALLOW', reason: 'It is fine', sds_findings: sdsFindings]]])
366+
Map<String, Object> receivedMeta
367+
368+
when:
369+
aiguard.evaluate(PROMPT, AIGuard.Options.DEFAULT)
370+
371+
then:
372+
1 * span.setMetaStruct(AIGuardInternal.META_STRUCT_TAG, _) >> {
373+
receivedMeta = it[1] as Map<String, Object>
374+
return span
375+
}
376+
receivedMeta.sds == sdsFindings
377+
}
378+
379+
void 'test evaluate with empty sds findings'() {
380+
given:
381+
final aiguard = mockClient(200, [data: [attributes: [action: 'ALLOW', reason: 'It is fine', sds_findings: sdsFindings]]])
382+
Map<String, Object> receivedMeta
383+
384+
when:
385+
aiguard.evaluate(PROMPT, AIGuard.Options.DEFAULT)
386+
387+
then:
388+
1 * span.setMetaStruct(AIGuardInternal.META_STRUCT_TAG, _) >> {
389+
receivedMeta = it[1] as Map<String, Object>
390+
return span
391+
}
392+
!receivedMeta.containsKey('sds')
393+
394+
where:
395+
sdsFindings << [null, []]
396+
}
397+
347398
void 'test missing tool name'() {
348399
given:
349400
final aiguard = mockClient(200, [data: [attributes: [action: 'ALLOW', reason: 'Just do it']]])

0 commit comments

Comments
 (0)