Skip to content

Commit d508a4f

Browse files
Merge pull request #949 from QueryaHub/issue/918-sandbox-sanitizer-quoted-secrets
fix(security): sanitize quoted passwords and tokens containing spaces in SandboxSanitizer (#918)
2 parents 8ebd455 + 4330800 commit d508a4f

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

‎lib/core/extensions/sandbox/sandbox_sanitizer.dart‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class SandboxSanitizer {
2222

2323
/// Common password / token assignment forms in dumps.
2424
static final _passwordAssignment = RegExp(
25-
r'''\b(password|passwd|pwd|secret|api[_-]?key|access[_-]?token|auth[_-]?token)\b(\s*[:=]\s*)(["']?)([^\s"'&,;]+)(["']?)''',
25+
r'''(['"]?)\b(password|passwd|pwd|secret|api[_-]?key|access[_-]?token|auth[_-]?token)\b\1(\s*[:=]\s*)(?:"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|([^\s"'&,;]+))''',
2626
caseSensitive: false,
2727
);
2828

@@ -48,9 +48,16 @@ class SandboxSanitizer {
4848
return '${m[1]}:$redactionToken@';
4949
});
5050
out = out.replaceAllMapped(_passwordAssignment, (m) {
51-
final quote = m[3] ?? '';
52-
final endQuote = m[5] ?? '';
53-
return '${m[1]}${m[2]}$quote$redactionToken$endQuote';
51+
final qKey = m[1] ?? '';
52+
final key = m[2] ?? '';
53+
final sep = m[3] ?? '';
54+
if (m[4] != null) {
55+
return '$qKey$key$qKey$sep"$redactionToken"';
56+
} else if (m[5] != null) {
57+
return "$qKey$key$qKey$sep'$redactionToken'";
58+
} else {
59+
return '$qKey$key$qKey$sep$redactionToken';
60+
}
5461
});
5562
out = out.replaceAllMapped(_bearer, (m) {
5663
return '${m[1]}$redactionToken';

‎test/core/extensions/sandbox/sandbox_sanitization_pipe_test.dart‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,36 @@ QyNTUxOQAAACBA1m7X8J9H6P8Q9J8H6P8Q9J8H6P8Q9J8H6P8Q9J8H6Q==
102102
expect(out, contains('mysql://root:${SandboxSanitizer.redactionToken}@'));
103103
expect(out, contains('mongodb+srv://admin:${SandboxSanitizer.redactionToken}@'));
104104
});
105+
106+
test('redacts quoted passwords and tokens containing spaces (#918)', () {
107+
final input = [
108+
'{"password": "correct horse battery staple"}',
109+
"val = {'api_key': 'super secret key with spaces'};",
110+
'password: "my secret password123"',
111+
"access_token: 'token with multiple spaces inside'",
112+
'auth-token = "auth token with spaces"',
113+
'password=plainSecret&other=1',
114+
'{"secret": "nested \\"quoted\\" secret", "status": "ok"}',
115+
].join('\n');
116+
117+
final out = SandboxSanitizer.sanitize(input);
118+
119+
expect(out, isNot(contains('correct horse battery staple')));
120+
expect(out, isNot(contains('super secret key with spaces')));
121+
expect(out, isNot(contains('my secret password123')));
122+
expect(out, isNot(contains('token with multiple spaces inside')));
123+
expect(out, isNot(contains('auth token with spaces')));
124+
expect(out, isNot(contains('plainSecret')));
125+
expect(out, isNot(contains('nested \\"quoted\\" secret')));
126+
127+
expect(out, contains('{"password": "${SandboxSanitizer.redactionToken}"}'));
128+
expect(out, contains("{'api_key': '${SandboxSanitizer.redactionToken}'}"));
129+
expect(out, contains('password: "${SandboxSanitizer.redactionToken}"'));
130+
expect(out, contains("access_token: '${SandboxSanitizer.redactionToken}'"));
131+
expect(out, contains('auth-token = "${SandboxSanitizer.redactionToken}"'));
132+
expect(out, contains('password=${SandboxSanitizer.redactionToken}&other=1'));
133+
expect(out, contains('{"secret": "${SandboxSanitizer.redactionToken}", "status": "ok"}'));
134+
});
105135
});
106136

107137
group('SandboxRotatingLog', () {

0 commit comments

Comments
 (0)