Skip to content

Commit e592dd3

Browse files
committed
fix(config): reject malformed domain labels
1 parent c30ca23 commit e592dd3

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

lib/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ export function safeDomain(dn: unknown): string | null {
133133
.replace(/^https?:\/\//, "")
134134
.replace(/[/?#&].*$/, "");
135135
if (!/^[a-z0-9.-]{3,253}$/.test(d) || !d.includes(".") || d.includes("..")) return null;
136+
if (d.startsWith(".") || d.endsWith(".")) return null;
137+
if (d.split(".").some((label) => label.startsWith("-") || label.endsWith("-"))) return null;
136138
return d;
137139
}
138140

tests/safe-domain.test.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import assert from "node:assert/strict";
2+
import test from "node:test";
3+
4+
import { safeDomain } from "../lib/config.ts";
5+
6+
test("safeDomain strips forwarded paths and accepts ordinary domains", () => {
7+
assert.equal(safeDomain("https://example.com/path?ref=abc"), "example.com");
8+
assert.equal(safeDomain("Sub.Example.COM#top"), "sub.example.com");
9+
});
10+
11+
test("safeDomain rejects empty labels and edge punctuation", () => {
12+
assert.equal(safeDomain(".example.com"), null);
13+
assert.equal(safeDomain("example.com."), null);
14+
assert.equal(safeDomain("example..com"), null);
15+
assert.equal(safeDomain("-example.com"), null);
16+
assert.equal(safeDomain("example-.com"), null);
17+
assert.equal(safeDomain("example.-com"), null);
18+
assert.equal(safeDomain("example.com-"), null);
19+
});

0 commit comments

Comments
 (0)