Skip to content

Commit

Permalink
make sure protocol relative URLs are not treated as actual relative U…
Browse files Browse the repository at this point in the history
…RLs (#712)

---------

Co-authored-by: Gabriel Falkenberg <[email protected]>
  • Loading branch information
dario-piotrowicz and gabrielf authored Mar 22, 2024
1 parent 82aa1a4 commit 8da9da2
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/healthy-ads-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudflare/next-on-pages': patch
---

Make sure protocol relative URLs are not treated as actual relative URLs
4 changes: 3 additions & 1 deletion packages/next-on-pages/templates/_worker.js/utils/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ export function getResizingProperties(
return undefined;
}

const isRelative = rawUrl.startsWith('/') || rawUrl.startsWith('%2F');
const isProtocolRelative = rawUrl.startsWith('//');
const isRelative = rawUrl.startsWith('/') && !isProtocolRelative;

if (
// Relative URL means same origin as deployment and is allowed.
!isRelative &&
Expand Down
42 changes: 42 additions & 0 deletions packages/next-on-pages/tests/templates/utils/images.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ describe('getResizingProperties', () => {
});
});

['/', '%2f', '%2F'].forEach(char => {
test(`image with valid request options succeeds (using '${char}'s)`, () => {
const baseValidUrl = `${baseUrl}${char}images${char}1.jpg`;
const url = new URL(`${baseValidUrl}&w=640`);
const req = new Request(url);

const result = getResizingProperties(req, baseConfig);
expect(result).toEqual({
isRelative: true,
imageUrl: new URL('https://localhost/images/1.jpg'),
options: { format: undefined, width: 640, quality: 75 },
});
});
});

test('svg image fails when config disallows svgs', () => {
const url = new URL(`${baseValidUrl.replace('jpg', 'svg')}&w=640`);
const req = new Request(url);
Expand Down Expand Up @@ -167,6 +182,33 @@ describe('getResizingProperties', () => {
});
});

describe('protocol relative (potentially another origin) image', () => {
const protocolRelativePrefixes = ['%2F%2F', '//', '%2f%2f', '%2f/', '/%2f'];

protocolRelativePrefixes.forEach(prefix => {
test(`image with valid request options succeeds (with ${prefix} prefix)`, () => {
const url = new URL(
`${baseUrl}${prefix}via.placeholder.com%2Fimage.jpg&w=640`,
);
const req = new Request(url);
const result = getResizingProperties(req, baseConfig);
expect(result).toEqual({
isRelative: false,
imageUrl: new URL('https://via.placeholder.com/image.jpg'),
options: { format: undefined, width: 640, quality: 75 },
});
});
});

protocolRelativePrefixes.forEach(prefix => {
test(`image with disallowed domain fails (with "${prefix}" prefix)`, () => {
const url = new URL(`${baseUrl}${prefix}invalid.com%2Fimage.jpg&w=640`);
const req = new Request(url);
expect(getResizingProperties(req, baseConfig)).toEqual(undefined);
});
});
});

describe('external image', () => {
test('external image fails with disallowed domain', () => {
const url = new URL(
Expand Down

0 comments on commit 8da9da2

Please sign in to comment.