Reject credential-bearing baseURL values

Co-authored-by: Eric Allam <eric@trigger.dev>
This commit is contained in:
Cursor Agent
2026-02-15 04:31:21 +00:00
parent 7f4cca5fed
commit 39492e67ab
5 changed files with 30 additions and 1 deletions
+2 -1
View File
@@ -656,7 +656,8 @@ If `onError` is omitted, reconnect still returns `null` and continues without ca
`baseURL` supports optional path prefixes and trailing slashes; both trigger and stream URLs
are normalized consistently, surrounding whitespace is trimmed before normalization, and
the resulting value must not be empty. The value must also be a valid absolute URL using
the `http` or `https` protocol, without query parameters or hash fragments.
the `http` or `https` protocol, without query parameters, hash fragments, or embedded
username/password credentials.
For richer TypeScript ergonomics in app code, `@trigger.dev/ai` also exports:
+1
View File
@@ -25,3 +25,4 @@
- Added explicit validation that `baseURL` is a valid absolute URL.
- Added explicit validation that `baseURL` uses `http` or `https`.
- Added explicit validation that `baseURL` excludes query parameters and hash fragments.
- Added explicit validation that `baseURL` excludes username/password credentials.
+1
View File
@@ -164,6 +164,7 @@ both cleanup steps (`set` inactive state and `delete`) even if one of them fails
- `baseURL` must be a valid absolute URL.
- `baseURL` must use the `http` or `https` protocol.
- `baseURL` must not include query parameters or hash fragments.
- `baseURL` must not include username/password URL credentials.
## `ai.tool(...)` example
+22
View File
@@ -675,6 +675,17 @@ describe("TriggerChatTransport", function () {
}).toThrowError("baseURL must not include query parameters or hash fragments");
});
it("throws when baseURL includes username or password credentials", function () {
expect(function () {
new TriggerChatTransport({
task: "chat-task",
accessToken: "pk_trigger",
baseURL: "https://user:pass@example.com/base",
stream: "chat-stream",
});
}).toThrowError("baseURL must not include username or password credentials");
});
it("accepts https baseURL values without throwing", function () {
expect(function () {
new TriggerChatTransport({
@@ -2925,6 +2936,17 @@ describe("TriggerChatTransport", function () {
}).toThrowError("baseURL must not include query parameters or hash fragments");
});
it("throws from factory when baseURL includes username or password credentials", function () {
expect(function () {
createTriggerChatTransport({
task: "chat-task",
accessToken: "pk_trigger",
baseURL: "https://user:pass@example.com/base",
stream: "chat-stream",
});
}).toThrowError("baseURL must not include username or password credentials");
});
it("accepts https baseURL values from factory without throwing", function () {
expect(function () {
createTriggerChatTransport({
+4
View File
@@ -484,6 +484,10 @@ function normalizeBaseUrl(baseURL: string) {
throw new Error("baseURL must not include query parameters or hash fragments");
}
if (parsedBaseUrl.username.length > 0 || parsedBaseUrl.password.length > 0) {
throw new Error("baseURL must not include username or password credentials");
}
return normalizedBaseUrl;
}