Skip to content

Commit 4ea86a1

Browse files
committed
fix: Remove auto-trimming of input
BREAKING CHANGE: parseDomain won't .trim() the given input. The input is interpreted as it is. If you want to trim the input, you need to call .trim() before passing it to parseDomain. Auto-trimming the input changes the domain and might not be desired if any character (such as whitespace) is allowed (e.g. when using lax validation).
1 parent a5fa416 commit 4ea86a1

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

src/parse-domain.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,20 @@ describe(parseDomain.name, () => {
583583
});
584584
});
585585

586+
// The hostname should be interpreted as it is.
587+
// Auto-trimming the input changes the domain and might not be
588+
// desired if any character (such as whitespace) is allowed
589+
// (e.g. when using lax validation).
590+
// Trimming can always happen on the caller side.
591+
test("does not trim the hostname", () => {
592+
expect(parseDomain(" com", { validation: Validation.Lax })).toMatchObject({
593+
type: ParseResultType.NotListed,
594+
});
595+
expect(parseDomain("com ", { validation: Validation.Lax })).toMatchObject({
596+
type: ParseResultType.NotListed,
597+
});
598+
});
599+
586600
test("returns the input hostname in the result", () => {
587601
expect(parseDomain("www.EXAMPLE.com")).toMatchObject({
588602
hostname: "www.EXAMPLE.com",

src/sanitize.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,17 @@ export const sanitize = (
147147
};
148148
}
149149

150-
const inputTrimmed = input.trim();
151-
152-
if (inputTrimmed === "") {
150+
if (input === "") {
153151
return {
154152
type: SanitizationResultType.ValidDomain,
155-
domain: inputTrimmed,
153+
domain: input,
156154
labels: [],
157155
};
158156
}
159157

160158
// IPv6 addresses are surrounded by square brackets in URLs
161159
// See https://tools.ietf.org/html/rfc3986#section-3.2.2
162-
const inputTrimmedAsIp = inputTrimmed.replace(/^\[|]$/g, "");
160+
const inputTrimmedAsIp = input.replace(/^\[|]$/g, "");
163161
const ipVersionOfInput = ipVersion(inputTrimmedAsIp);
164162

165163
if (ipVersionOfInput !== undefined) {
@@ -170,15 +168,15 @@ export const sanitize = (
170168
};
171169
}
172170

173-
const lastChar = inputTrimmed.charAt(inputTrimmed.length - 1);
171+
const lastChar = input.charAt(input.length - 1);
174172
const canonicalInput =
175-
lastChar === LABEL_SEPARATOR ? inputTrimmed.slice(0, -1) : inputTrimmed;
173+
lastChar === LABEL_SEPARATOR ? input.slice(0, -1) : input;
176174
const octets = new TextEncoder().encode(canonicalInput);
177175

178176
if (octets.length > DOMAIN_LENGTH_MAX) {
179177
return {
180178
type: SanitizationResultType.Error,
181-
errors: [createDomainMaxLengthError(inputTrimmed, octets.length)],
179+
errors: [createDomainMaxLengthError(input, octets.length)],
182180
};
183181
}
184182

@@ -196,7 +194,7 @@ export const sanitize = (
196194

197195
return {
198196
type: SanitizationResultType.ValidDomain,
199-
domain: inputTrimmed,
197+
domain: input,
200198
labels,
201199
};
202200
};

0 commit comments

Comments
 (0)