Skip to content

Commit 082fd30

Browse files
authored
feat: add url validation to oembed api (#290)
1 parent f644db9 commit 082fd30

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

src/lambda/oembed/oembed.js

+24-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const URL = require('url');
2+
13
function incorrectParams(error) {
24
return {
35
statusCode: 501, // oembed status // 422, // Unprocessable Entity
@@ -8,19 +10,23 @@ function incorrectParams(error) {
810

911
function getHostname(event, context) {
1012
if (event.headers.host) {
11-
return `http://${event.headers.host}`;
13+
return `https://${event.headers.host}`;
1214
}
1315

1416
const { netlify } = context.clientContext.custom || {};
1517

1618
return JSON.parse(Buffer.from(netlify, 'base64').toString('utf-8')).site_url;
1719
}
1820

21+
const allowedPathsRegexp = new RegExp(/^\/(gist|embed)\/.*/);
22+
1923
function handler(event, context, callback) {
2024
const host = getHostname(event, context);
25+
2126
const params = event.queryStringParameters;
27+
const { format, referrer, maxwidth = 900, maxheight = 450 } = params;
2228

23-
if (params.format === 'xml') {
29+
if (format && format !== 'json') {
2430
return callback(
2531
null,
2632
incorrectParams('unsupported format, only json is supported'),
@@ -34,7 +40,22 @@ function handler(event, context, callback) {
3440
);
3541
}
3642

37-
const { url, referrer, maxwidth = 900, maxheight = 450 } = params;
43+
const { hostname, pathname } = URL.parse(params.url);
44+
45+
// verify if the url is supported, basically we only allow localhost if we're
46+
// running at localhost, and testing-playground.com as host. And either no
47+
// path or /gist and /embed paths.
48+
if (
49+
(!host.includes(hostname) && hostname !== 'testing-playground.com') ||
50+
(pathname && !allowedPathsRegexp.test(pathname))
51+
) {
52+
return callback(null, incorrectParams('unsupported url provided :/'));
53+
}
54+
55+
// map /gist urls to /embed
56+
const url = pathname.startsWith('/gist/')
57+
? params.url.replace('/gist/', '/embed/')
58+
: params.url;
3859

3960
callback(null, {
4061
statusCode: 200,

src/lambda/server/server.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@ function handler(event, context, callback) {
2525
const host = getHostname(event, context);
2626

2727
const embedPath = event.path.replace('/gist/', '/embed/');
28-
const frameSrc = `${host}${embedPath}?${queryString.stringify({
29-
panes,
30-
markup,
31-
query,
32-
})}`;
28+
const frameSearch = queryString.stringify({ panes, markup, query });
29+
const frameSrc = host + embedPath + (frameSearch ? `?${frameSearch}` : '');
3330

3431
const oembedSearch = queryString.stringify({ url: frameSrc });
3532

0 commit comments

Comments
 (0)