Skip to content

Commit 28becff

Browse files
Reject mongolian-vowel-separator baseURL invisible whitespace
Co-authored-by: Eric Allam <eric@trigger.dev>
1 parent d1e9220 commit 28becff

File tree

6 files changed

+53
-1
lines changed

6 files changed

+53
-1
lines changed

.changeset/curly-radios-visit.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ Add a new `@trigger.dev/ai` package with:
1616
values that normalize to empty after trimming
1717
- expanded unicode whitespace handling coverage to include figure space (`\u2007`) and medium
1818
mathematical space (`\u205F`) for both wrapper trimming and internal-whitespace rejection
19+
- expanded invisible-separator rejection coverage to include mongolian vowel separator (`\u180E`)
20+
in both wrapper and internal `baseURL` positions
1921
- deterministic baseURL validation error ordering for multi-issue inputs (internal whitespace → protocol → query/hash → credentials)
2022
- explicit default `baseURL` behavior (`https://api.trigger.dev`) and case-insensitive `HTTP(S)` protocol acceptance

docs/tasks/streams.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,7 @@ Examples:
679679
-`\u200Bhttps://api.trigger.dev/custom-prefix/\u200B` (zero-width-space wrappers are rejected)
680680
-`\u200Chttps://api.trigger.dev/custom-prefix/\u200C` (zero-width-non-joiner wrappers are rejected)
681681
-`\u200Dhttps://api.trigger.dev/custom-prefix/\u200D` (zero-width-joiner wrappers are rejected)
682+
-`\u180Ehttps://api.trigger.dev/custom-prefix/\u180E` (mongolian-vowel-separator wrappers are rejected)
682683
-`https://api.trigger.dev?foo=bar`
683684
-`https://api.trigger.dev#fragment`
684685
-`https://user:pass@api.trigger.dev`
@@ -705,6 +706,7 @@ Examples:
705706
-`https://api.trigger.dev/\u2007internal`
706707
-`https://api.trigger.dev/\u202Finternal`
707708
-`https://api.trigger.dev/\u205Finternal`
709+
-`https://api.trigger.dev/\u180Einternal`
708710
-`https://api.trigger.dev/\u3000internal`
709711
-`https://api.trigger.dev/\u2028internal`
710712
-`https://api.trigger.dev/\u2029internal`

packages/ai/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
confirmed empty-after-trim values still throw `baseURL must not be empty`.
3333
- Expanded unicode whitespace coverage with `\u2007` (figure space) and `\u205F` (medium mathematical space)
3434
across internal-whitespace rejection, wrapper trimming acceptance, and empty-after-trim validation.
35+
- Expanded invisible-separator coverage to reject `\u180E` (mongolian vowel separator) in both
36+
internal and wrapper `baseURL` positions.
3537
- Documented that `HTTP://` and `HTTPS://` are accepted (case-insensitive protocol matching).
3638
- Added deterministic validation ordering for multi-issue baseURL values
3739
(internal whitespace → protocol → query/hash → credentials).

packages/ai/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ Examples:
186186
-`\u200Bhttps://api.trigger.dev/custom-prefix/\u200B` (zero-width-space wrappers are rejected)
187187
-`\u200Chttps://api.trigger.dev/custom-prefix/\u200C` (zero-width-non-joiner wrappers are rejected)
188188
-`\u200Dhttps://api.trigger.dev/custom-prefix/\u200D` (zero-width-joiner wrappers are rejected)
189+
-`\u180Ehttps://api.trigger.dev/custom-prefix/\u180E` (mongolian-vowel-separator wrappers are rejected)
189190
-`https://api.trigger.dev?foo=bar` (query string)
190191
-`https://api.trigger.dev#fragment` (hash fragment)
191192
-`https://user:pass@api.trigger.dev` (credentials)
@@ -212,6 +213,7 @@ Examples:
212213
-`https://api.trigger.dev/\u2007internal` (internal figure-space characters)
213214
-`https://api.trigger.dev/\u202Finternal` (internal narrow no-break space characters)
214215
-`https://api.trigger.dev/\u205Finternal` (internal medium-mathematical-space characters)
216+
-`https://api.trigger.dev/\u180Einternal` (internal mongolian-vowel-separator characters)
215217
-`https://api.trigger.dev/\u3000internal` (internal ideographic-space characters)
216218
-`https://api.trigger.dev/\u2028internal` (internal line-separator characters)
217219
-`https://api.trigger.dev/\u2029internal` (internal paragraph-separator characters)

packages/ai/src/chatTransport.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,17 @@ describe("TriggerChatTransport", function () {
950950
}).toThrowError("baseURL must not contain internal whitespace characters");
951951
});
952952

953+
it("throws when baseURL contains internal mongolian-vowel-separator characters", function () {
954+
expect(function () {
955+
new TriggerChatTransport({
956+
task: "chat-task",
957+
accessToken: "pk_trigger",
958+
baseURL: "https://api.trigger.dev/\u180Einternal",
959+
stream: "chat-stream",
960+
});
961+
}).toThrowError("baseURL must not contain internal whitespace characters");
962+
});
963+
953964
it("throws when baseURL contains internal line-separator characters", function () {
954965
expect(function () {
955966
new TriggerChatTransport({
@@ -1027,6 +1038,17 @@ describe("TriggerChatTransport", function () {
10271038
}).toThrowError("baseURL must not contain internal whitespace characters");
10281039
});
10291040

1041+
it("throws when baseURL is wrapped with mongolian-vowel-separator characters", function () {
1042+
expect(function () {
1043+
new TriggerChatTransport({
1044+
task: "chat-task",
1045+
accessToken: "pk_trigger",
1046+
baseURL: "\u180Ehttps://api.trigger.dev/custom-prefix/\u180E",
1047+
stream: "chat-stream",
1048+
});
1049+
}).toThrowError("baseURL must not contain internal whitespace characters");
1050+
});
1051+
10301052
it("throws when baseURL contains internal zero-width-non-joiner characters", function () {
10311053
expect(function () {
10321054
new TriggerChatTransport({
@@ -4043,6 +4065,17 @@ describe("TriggerChatTransport", function () {
40434065
}).toThrowError("baseURL must not contain internal whitespace characters");
40444066
});
40454067

4068+
it("throws from factory when baseURL contains internal mongolian-vowel-separator characters", function () {
4069+
expect(function () {
4070+
createTriggerChatTransport({
4071+
task: "chat-task",
4072+
accessToken: "pk_trigger",
4073+
baseURL: "https://api.trigger.dev/\u180Einternal",
4074+
stream: "chat-stream",
4075+
});
4076+
}).toThrowError("baseURL must not contain internal whitespace characters");
4077+
});
4078+
40464079
it("throws from factory when baseURL contains internal line-separator characters", function () {
40474080
expect(function () {
40484081
createTriggerChatTransport({
@@ -4120,6 +4153,17 @@ describe("TriggerChatTransport", function () {
41204153
}).toThrowError("baseURL must not contain internal whitespace characters");
41214154
});
41224155

4156+
it("throws from factory when baseURL is wrapped with mongolian-vowel-separator characters", function () {
4157+
expect(function () {
4158+
createTriggerChatTransport({
4159+
task: "chat-task",
4160+
accessToken: "pk_trigger",
4161+
baseURL: "\u180Ehttps://api.trigger.dev/custom-prefix/\u180E",
4162+
stream: "chat-stream",
4163+
});
4164+
}).toThrowError("baseURL must not contain internal whitespace characters");
4165+
});
4166+
41234167
it("throws from factory when baseURL contains internal zero-width-non-joiner characters", function () {
41244168
expect(function () {
41254169
createTriggerChatTransport({

packages/ai/src/chatTransport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ const BASE_URL_VALIDATION_ERRORS = {
459459

460460
// Includes standard whitespace plus common invisible separator/control marks
461461
// that can make URLs look valid while behaving unexpectedly.
462-
const INTERNAL_WHITESPACE_REGEX = /[\s\u200B\u200C\u200D\u2060\uFEFF]/u;
462+
const INTERNAL_WHITESPACE_REGEX = /[\s\u180E\u200B\u200C\u200D\u2060\uFEFF]/u;
463463

464464
function resolvePayloadMapper<
465465
UI_MESSAGE extends UIMessage,

0 commit comments

Comments
 (0)