Skip to content

Commit a5df464

Browse files
avara1986claude
andauthored
fix(aiguard): resolve endpoint host correctly for regional Datadog sites (#9040)
The AI Guard SDK client unconditionally prepended the `app.` subdomain to the configured site, producing an invalid host (e.g. `app.us3.datadoghq.com`) for regional data centers. Prepend `app.` only when the site is a single-level domain, mirroring the Python tracer logic. APPSEC-68649 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 72844ef commit a5df464

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

packages/dd-trace/src/aiguard/sdk.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ class AIGuardClientError extends Error {
6363
}
6464
}
6565

66+
/**
67+
* Resolves the AI Guard host for a given Datadog site. Sites with a single subdomain level
68+
* (e.g. `datadoghq.com`, `ddog-gov.com`) are served from the `app.` subdomain, while regional
69+
* sites (e.g. `us3.datadoghq.com`, `ap1.datadoghq.com`) are used as-is.
70+
*
71+
* @param {string} site - Datadog site (e.g. `datadoghq.com`, `us3.datadoghq.com`)
72+
* @returns {string} The host to use for the AI Guard endpoint
73+
*/
74+
function aiGuardHost (site) {
75+
return site.split('.').length === 2 ? `app.${site}` : site
76+
}
77+
6678
class AIGuard extends NoopAIGuard {
6779
#initialized
6880
#tracer
@@ -94,7 +106,7 @@ class AIGuard extends NoopAIGuard {
94106
'DD-AI-GUARD-SOURCE': 'SDK',
95107
'DD-AI-GUARD-LANGUAGE': 'nodejs',
96108
}
97-
const endpoint = config.experimental.aiguard.endpoint || `https://app.${config.site}/api/v2/ai-guard`
109+
const endpoint = config.experimental.aiguard.endpoint || `https://${aiGuardHost(config.site)}/api/v2/ai-guard`
98110
this.#evaluateUrl = `${endpoint}/evaluate`
99111
this.#timeout = config.experimental.aiguard.timeout
100112
this.#maxMessagesLength = config.experimental.aiguard.maxMessagesLength

packages/dd-trace/test/aiguard/index.spec.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,11 +523,14 @@ describe('AIGuard SDK', () => {
523523
const sites = [
524524
{ site: 'datad0g.com', endpoint: 'https://app.datad0g.com/api/v2/ai-guard' },
525525
{ site: 'datadoghq.com', endpoint: 'https://app.datadoghq.com/api/v2/ai-guard' },
526+
{ site: 'ddog-gov.com', endpoint: 'https://app.ddog-gov.com/api/v2/ai-guard' },
527+
{ site: 'us3.datadoghq.com', endpoint: 'https://us3.datadoghq.com/api/v2/ai-guard' },
528+
{ site: 'ap1.datadoghq.com', endpoint: 'https://ap1.datadoghq.com/api/v2/ai-guard' },
526529
]
527530
for (const { site, endpoint } of sites) {
528531
it(`test endpoint discovery: ${site}`, async () => {
529-
const newConfig = { site, ...config }
530-
delete newConfig.experimental.aiguard.endpoint
532+
const { endpoint: _discardedEndpoint, ...aiguard } = config.experimental.aiguard
533+
const newConfig = { ...config, site, experimental: { ...config.experimental, aiguard } }
531534
const client = new AIGuard(tracer, newConfig)
532535
mockFetch({
533536
body: { data: { attributes: { action: 'ALLOW', reason: 'OK', is_blocking_enabled: false } } },

0 commit comments

Comments
 (0)