Skip to content

Commit b7aeec9

Browse files
authored
Improve host.json sanitization on v3.x (#9624)
* Improve host.json sanitization (#9459) * Contains -> IndexOf
1 parent 450b886 commit b7aeec9

File tree

3 files changed

+88
-5
lines changed

3 files changed

+88
-5
lines changed

src/WebJobs.Script/Config/HostJsonFileConfigurationSource.cs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class HostJsonFileConfigurationProvider : ConfigurationProvider
5454
"customHandler", "httpWorker", "extensions", "concurrency"
5555
};
5656

57+
private static readonly string[] CredentialNameFragments = new[] { "password", "pwd", "key", "secret", "token", "sas" };
58+
5759
private readonly HostJsonFileConfigurationSource _configurationSource;
5860
private readonly Stack<string> _path;
5961
private readonly ILogger _logger;
@@ -275,14 +277,65 @@ private JObject TryAddBundleConfiguration(JObject content, string bundleId, stri
275277

276278
internal static string SanitizeHostJson(JObject hostJsonObject)
277279
{
278-
JObject sanitizedObject = new JObject();
280+
static bool IsPotentialCredential(string name)
281+
{
282+
foreach (string fragment in CredentialNameFragments)
283+
{
284+
if (name.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) != -1)
285+
{
286+
return true;
287+
}
288+
}
289+
290+
return false;
291+
}
292+
293+
static JToken Sanitize(JToken token)
294+
{
295+
if (token is JObject obj)
296+
{
297+
JObject sanitized = new JObject();
298+
foreach (var prop in obj)
299+
{
300+
if (IsPotentialCredential(prop.Key))
301+
{
302+
sanitized[prop.Key] = Sanitizer.SecretReplacement;
303+
}
304+
else
305+
{
306+
sanitized[prop.Key] = Sanitize(prop.Value);
307+
}
308+
}
279309

310+
return sanitized;
311+
}
312+
313+
if (token is JArray arr)
314+
{
315+
JArray sanitized = new JArray();
316+
foreach (var value in arr)
317+
{
318+
sanitized.Add(Sanitize(value));
319+
}
320+
321+
return sanitized;
322+
}
323+
324+
if (token.Type == JTokenType.String)
325+
{
326+
return Sanitizer.Sanitize(token.ToString());
327+
}
328+
329+
return token;
330+
}
331+
332+
JObject sanitizedObject = new JObject();
280333
foreach (var propName in WellKnownHostJsonProperties)
281334
{
282335
var propValue = hostJsonObject[propName];
283336
if (propValue != null)
284337
{
285-
sanitizedObject[propName] = propValue;
338+
sanitizedObject[propName] = Sanitize(propValue);
286339
}
287340
}
288341

src/WebJobs.Script/Sanitizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.Azure.WebJobs.Logging
1111
// Note: This file is shared between the WebJobs SDK and Script repos. Update both if changes are needed.
1212
internal static class Sanitizer
1313
{
14-
private const string SecretReplacement = "[Hidden Credential]";
14+
public const string SecretReplacement = "[Hidden Credential]";
1515
private static readonly char[] ValueTerminators = new char[] { '<', '"', '\'' };
1616

1717
// List of keywords that should not be replaced with [Hidden Credential]

test/WebJobs.Script.Tests/Configuration/HostJsonFileConfigurationSourceTests.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,22 @@ public void Initialize_Sanitizes_HostJsonLog()
160160
'logging': {
161161
'categoryFilter': {
162162
'defaultLevel': 'Information'
163-
}
163+
},
164+
'applicationInsights': {
165+
'prop': 'Hey=AS1$@%#$%W-k2j"";SharedAccessKey=foo,Data Source=barzons,Server=bathouse""testing',
166+
'values': [ 'plain', 10, 'Password=hunter2' ],
167+
'sampleSettings': {
168+
'my-password': 'hunter2',
169+
'service_token': 'token',
170+
'StorageSas': 'access'
171+
}
172+
},
173+
'prop': 'Hey=AS1$@%#$%W-k2j"";SharedAccessKey=foo,Data Source=barzons,Server=bathouse""testing',
174+
'values': [ 'plain', 10, 'Password=hunter2' ],
175+
'my-password': 'hunter2',
176+
'service_token': 'token',
177+
'StorageSas': 'access',
178+
'aSecret': { 'value1': 'value' }
164179
},
165180
'Values': {
166181
'MyCustomValue': 'abc'
@@ -182,7 +197,22 @@ public void Initialize_Sanitizes_HostJsonLog()
182197
'logging': {
183198
'categoryFilter': {
184199
'defaultLevel': 'Information'
185-
}
200+
},
201+
'applicationInsights': {
202+
'prop': 'Hey=AS1$@%#$%W-k2j"";[Hidden Credential]""testing',
203+
'values': [ 'plain', 10, '[Hidden Credential]' ],
204+
'sampleSettings': {
205+
'my-password': '[Hidden Credential]',
206+
'service_token': '[Hidden Credential]',
207+
'StorageSas': '[Hidden Credential]'
208+
}
209+
},
210+
'prop': 'Hey=AS1$@%#$%W-k2j"";[Hidden Credential]""testing',
211+
'values': [ 'plain', 10, '[Hidden Credential]' ],
212+
'my-password': '[Hidden Credential]',
213+
'service_token': '[Hidden Credential]',
214+
'StorageSas': '[Hidden Credential]',
215+
'aSecret': '[Hidden Credential]'
186216
}
187217
}";
188218

0 commit comments

Comments
 (0)