Skip to content

Commit 663745e

Browse files
authored
feat(ai-guard): return SDS findings into SDK Response (#10821)
feat(ai-guard): return SDS findings into SDK Response add tests for sds findings in sdk response and abort error Merge branch 'master' into oceane.bordeau/sds-attach-sdk-response Merge branch 'master' into oceane.bordeau/sds-attach-sdk-response Co-authored-by: oceane.bordeau <oceane.bordeau@datadoghq.com>
1 parent a317569 commit 663745e

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ public Evaluation evaluate(final List<Message> messages, final Options options)
273273
WafMetricCollector.get().aiGuardRequest(action, shouldBlock);
274274
if (shouldBlock) {
275275
span.setTag(BLOCKED_TAG, true);
276-
throw new AIGuardAbortError(action, reason, tags);
276+
throw new AIGuardAbortError(action, reason, tags, sdsFindings);
277277
}
278-
return new Evaluation(action, reason, tags);
278+
return new Evaluation(action, reason, tags, sdsFindings);
279279
}
280280
} catch (AIGuardAbortError e) {
281281
span.addThrowable(e);

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,13 @@ class AIGuardInternalTests extends DDSpecification {
210210
error.action == suite.action
211211
error.reason == suite.reason
212212
error.tags == suite.tags
213+
error.sds == []
213214
} else {
214215
error == null
215216
eval.action == suite.action
216217
eval.reason == suite.reason
217218
eval.tags == suite.tags
219+
eval.sds == []
218220
}
219221
assertTelemetry('ai_guard.requests', "action:$suite.action", "block:$throwAbortError", 'error:false')
220222

@@ -411,14 +413,15 @@ class AIGuardInternalTests extends DDSpecification {
411413
Map<String, Object> receivedMeta
412414

413415
when:
414-
aiguard.evaluate(PROMPT, AIGuard.Options.DEFAULT)
416+
final result = aiguard.evaluate(PROMPT, AIGuard.Options.DEFAULT)
415417

416418
then:
417419
1 * span.setMetaStruct(AIGuardInternal.META_STRUCT_TAG, _) >> {
418420
receivedMeta = it[1] as Map<String, Object>
419421
return span
420422
}
421423
receivedMeta.sds == sdsFindings
424+
result.sds == sdsFindings
422425
}
423426

424427
void 'test evaluate with empty sds findings'() {
@@ -427,19 +430,41 @@ class AIGuardInternalTests extends DDSpecification {
427430
Map<String, Object> receivedMeta
428431

429432
when:
430-
aiguard.evaluate(PROMPT, AIGuard.Options.DEFAULT)
433+
final result = aiguard.evaluate(PROMPT, AIGuard.Options.DEFAULT)
431434

432435
then:
433436
1 * span.setMetaStruct(AIGuardInternal.META_STRUCT_TAG, _) >> {
434437
receivedMeta = it[1] as Map<String, Object>
435438
return span
436439
}
437440
!receivedMeta.containsKey('sds')
441+
result.sds == (sdsFindings ?: [])
438442

439443
where:
440444
sdsFindings << [null, []]
441445
}
442446

447+
void 'test evaluate with sds findings in abort error'() {
448+
given:
449+
final sdsFindings = [
450+
[
451+
rule_display_name: 'Credit Card Number',
452+
rule_tag: 'credit_card',
453+
category: 'pii',
454+
matched_text: '4111111111111111',
455+
location: [start_index: 10, end_index_exclusive: 26, path: 'messages[0].content[0].text']
456+
]
457+
]
458+
final aiguard = mockClient(200, [data: [attributes: [action: 'ABORT', reason: 'PII detected', tags: ['pii'], sds_findings: sdsFindings, is_blocking_enabled: true]]])
459+
460+
when:
461+
aiguard.evaluate(PROMPT, new AIGuard.Options().block(true))
462+
463+
then:
464+
final error = thrown(AIGuard.AIGuardAbortError)
465+
error.sds == sdsFindings
466+
}
467+
443468
void 'test missing tool name'() {
444469
given:
445470
final aiguard = mockClient(200, [data: [attributes: [action: 'ALLOW', reason: 'Just do it']]])

dd-trace-api/src/main/java/datadog/trace/api/aiguard/AIGuard.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,15 @@ public static class AIGuardAbortError extends RuntimeException {
6969
private final Action action;
7070
private final String reason;
7171
private final List<String> tags;
72+
private final List<?> sds;
7273

73-
public AIGuardAbortError(final Action action, final String reason, final List<String> tags) {
74+
public AIGuardAbortError(
75+
final Action action, final String reason, final List<String> tags, final List<?> sds) {
7476
super(reason);
7577
this.action = action;
7678
this.reason = reason;
7779
this.tags = tags;
80+
this.sds = sds != null ? sds : Collections.emptyList();
7881
}
7982

8083
public Action getAction() {
@@ -88,6 +91,10 @@ public String getReason() {
8891
public List<String> getTags() {
8992
return tags;
9093
}
94+
95+
public List<?> getSds() {
96+
return sds;
97+
}
9198
}
9299

93100
/**
@@ -149,18 +156,22 @@ public static class Evaluation {
149156
final Action action;
150157
final String reason;
151158
final List<String> tags;
159+
final List<?> sds;
152160

153161
/**
154162
* Creates a new evaluation result.
155163
*
156164
* @param action the recommended action for the evaluated content
157165
* @param reason human-readable explanation for the decision
158166
* @param tags list of tags associated with the evaluation (e.g. indirect-prompt-injection)
167+
* @param sds list of Sensitive Data Scanner findings
159168
*/
160-
public Evaluation(final Action action, final String reason, final List<String> tags) {
169+
public Evaluation(
170+
final Action action, final String reason, final List<String> tags, final List<?> sds) {
161171
this.action = action;
162172
this.reason = reason;
163173
this.tags = tags;
174+
this.sds = sds != null ? sds : Collections.emptyList();
164175
}
165176

166177
/**
@@ -189,6 +200,15 @@ public String getReason() {
189200
public List<String> getTags() {
190201
return tags;
191202
}
203+
204+
/**
205+
* Returns the list of Sensitive Data Scanner findings.
206+
*
207+
* @return list of SDS findings.
208+
*/
209+
public List<?> getSds() {
210+
return sds;
211+
}
192212
}
193213

194214
/**

dd-trace-api/src/main/java/datadog/trace/api/aiguard/noop/NoOpEvaluator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ public final class NoOpEvaluator implements Evaluator {
1313

1414
@Override
1515
public Evaluation evaluate(final List<Message> messages, final Options options) {
16-
return new Evaluation(ALLOW, "AI Guard is not enabled", emptyList());
16+
return new Evaluation(ALLOW, "AI Guard is not enabled", emptyList(), emptyList());
1717
}
1818
}

0 commit comments

Comments
 (0)