Skip to content

Commit fde6754

Browse files
fix(core): handle malformed percent-encoding in UriTemplate.match()
1 parent 7e4fd95 commit fde6754

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

packages/core/src/shared/uriTemplate.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ const MAX_VARIABLE_LENGTH = 1_000_000; // 1MB
77
const MAX_TEMPLATE_EXPRESSIONS = 10_000;
88
const MAX_REGEX_LENGTH = 1_000_000; // 1MB
99

10+
function safeDecode(s: string): string {
11+
try {
12+
return decodeURIComponent(s);
13+
} catch {
14+
return s;
15+
}
16+
}
17+
1018
export class UriTemplate {
1119
/**
1220
* Returns true if the given string contains any URI template expressions.
@@ -302,8 +310,8 @@ export class UriTemplate {
302310
for (const pair of queryPart.split('&')) {
303311
const equalIndex = pair.indexOf('=');
304312
if (equalIndex !== -1) {
305-
const key = decodeURIComponent(pair.slice(0, equalIndex));
306-
const value = decodeURIComponent(pair.slice(equalIndex + 1));
313+
const key = safeDecode(pair.slice(0, equalIndex));
314+
const value = safeDecode(pair.slice(equalIndex + 1));
307315
queryParams.set(key, value);
308316
}
309317
}

packages/core/test/shared/uriTemplate.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ describe('UriTemplate', () => {
249249
expect(match).toEqual({ q: 'hello world' });
250250
expect(template.variableNames).toEqual(['q']);
251251
});
252+
253+
it('should not throw on malformed percent-encoding in query parameters', () => {
254+
const template = new UriTemplate('/search{?q}');
255+
expect(template.match('/search?q=100%')).toEqual({ q: '100%' });
256+
expect(template.match('/search?q=%ZZ')).toEqual({ q: '%ZZ' });
257+
});
252258
});
253259

254260
describe('security and edge cases', () => {

0 commit comments

Comments
 (0)