Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/sim/lib/core/security/input-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,8 @@ describe('typed base URLs', () => {
['//evil.com', 'a protocol-relative URL'],
['//user:pass@evil.com', 'a protocol-relative URL with credentials'],
['/\\evil.com', 'a slash and backslash the parser reads as an authority'],
['https:///user:pass@evil.com', 'an extra slash hiding credentials from the authority'],
['https:///evil.com', 'an extra slash after the scheme'],
])('refuses %j (%s) in both helpers', (typed) => {
expect(() => refuseUnsafeTypedUrl(typed)).toThrow()
expect(() => normalizeHttpBaseUrl(typed)).toThrow()
Expand Down
9 changes: 5 additions & 4 deletions apps/sim/lib/core/security/input-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1412,13 +1412,14 @@ export function validateDatabaseIdentifier(
/**
* Drops the tabs and newlines the URL parser ignores, then refuses every typed form the parser
* would read as a host other than the one typed: a malformed `https:/host` (which would get a
* second scheme and parse as a host named `https`), any other scheme such as `ftp:/host`, and a
* leading slash or backslash, which the parser takes as a protocol-relative authority. A bare
* `host` or `host:port` and an `http(s)://` URL pass.
* second scheme and parse as a host named `https`), an extra slash or backslash after `https://`
* (which the parser skips, so `https:///user:pass@host` hides its credentials from the authority
* check), any other scheme such as `ftp:/host`, and a leading slash or backslash, which the parser
* takes as a protocol-relative authority. A bare `host` or `host:port` and an `http(s)://` URL pass.
*/
function refuseUnsafeUrlForm(typed: string): string {
const stripped = typed.replace(/[\t\n\r]/g, '')
if (/^https?:(?!\/\/)/i.test(stripped)) throw new Error('malformed scheme')
if (/^https?:(?!\/\/(?![/\\]))/i.test(stripped)) throw new Error('malformed scheme')
if (/^[/\\]/.test(stripped)) throw new Error('protocol-relative URL')
const hasScheme = /^[a-z][a-z\d+.-]*:/i.test(stripped)
const isHostWithPort = /^[a-z\d.-]+:\d+(?:[/?#]|$)/i.test(stripped)
Expand Down
Loading