Skip to content

Commit e59f1d7

Browse files
committed
fix(feature-flags): redact agentless base URL telemetry and reject malformed sites safely
1 parent ac79e9b commit e59f1d7

3 files changed

Lines changed: 43 additions & 6 deletions

File tree

tracer/src/Datadog.Trace/FeatureFlags/Agentless/AgentlessEndpoint.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,25 @@ public static bool TryCreate(string? site, string? env, string? baseUrl, out Age
7272
return false;
7373
}
7474

75-
var managed = new UriBuilder("https", ManagedHostPrefix + trimmedSite!.ToLowerInvariant()) { Path = DefaultPath };
75+
var managedHost = ManagedHostPrefix + trimmedSite!.ToLowerInvariant();
76+
if (managedHost.Contains("://") || HasWhitespace(managedHost))
77+
{
78+
error = "The configured Datadog site is not valid";
79+
return false;
80+
}
81+
82+
if (!Uri.TryCreate($"https://{managedHost}{DefaultPath}", UriKind.Absolute, out var managedUri))
83+
{
84+
error = "The configured Datadog site is not valid";
85+
return false;
86+
}
87+
7688
if (!StringUtil.IsNullOrEmpty(env))
7789
{
78-
managed.Query = "dd_env=" + Uri.EscapeDataString(env!);
90+
managedUri = new UriBuilder(managedUri) { Query = "dd_env=" + Uri.EscapeDataString(env!) }.Uri;
7991
}
8092

81-
endpoint = new AgentlessEndpoint(managed.Uri, isManaged: true);
93+
endpoint = new AgentlessEndpoint(managedUri, isManaged: true);
8294
return true;
8395
}
8496

@@ -113,4 +125,17 @@ public static bool TryCreate(string? site, string? env, string? baseUrl, out Age
113125
endpoint = new AgentlessEndpoint(custom, isManaged: false);
114126
return true;
115127
}
128+
129+
private static bool HasWhitespace(string value)
130+
{
131+
foreach (var c in value)
132+
{
133+
if (char.IsWhiteSpace(c))
134+
{
135+
return true;
136+
}
137+
}
138+
139+
return false;
140+
}
116141
}

tracer/src/Datadog.Trace/FeatureFlags/FeatureFlagsSettings.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ public FeatureFlagsSettings(IConfigurationSource? source, IConfigurationTelemetr
6262

6363
Source = ResolveSource(enabled, configuredSource, legacyEnabled);
6464

65-
AgentlessBaseUrl = config
66-
.WithKeys(ConfigurationKeys.FeatureFlags.FeatureFlagsConfigurationSourceAgentlessBaseUrl)
67-
.AsString(url => !StringUtil.IsNullOrEmpty(url?.Trim()));
65+
var agentlessBaseUrl = config
66+
.WithKeys(ConfigurationKeys.FeatureFlags.FeatureFlagsConfigurationSourceAgentlessBaseUrl)
67+
.AsRedactedString();
68+
AgentlessBaseUrl = !StringUtil.IsNullOrEmpty(agentlessBaseUrl?.Trim()) ? agentlessBaseUrl : null;
6869

6970
PollInterval = TimeSpan.FromSeconds(
7071
InRangeOrDefault(

tracer/test/Datadog.Trace.Tests/FeatureFlags/AgentlessEndpointTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ public void RejectsWhitespaceOnlySiteWithoutBaseUrl()
104104
error.Should().Be("No Datadog site is configured");
105105
}
106106

107+
[Theory]
108+
[InlineData("https://datadoghq.com")] // user accidentally includes the scheme
109+
[InlineData("data dog hq.com")] // internal spaces
110+
[InlineData("datadoghq.com:99999")] // invalid port
111+
public void RejectsMalformedSiteWithoutThrowing(string site)
112+
{
113+
AgentlessEndpoint.TryCreate(site, env: null, baseUrl: null, out var endpoint, out var error)
114+
.Should().BeFalse();
115+
error.Should().Be("The configured Datadog site is not valid");
116+
}
117+
107118
[Fact]
108119
public void ErrorNeverContainsUrl()
109120
{

0 commit comments

Comments
 (0)