diff --git a/core/server/lib/request-external.js b/core/server/lib/request-external.js index c7b9b7e573..a8a603b125 100644 --- a/core/server/lib/request-external.js +++ b/core/server/lib/request-external.js @@ -12,8 +12,9 @@ function isPrivateIp(addr) { /^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) || /^f[cd][0-9a-f]{2}:/i.test(addr) || /^fe80:/i.test(addr) || - /^::1$/.test(addr) || - /^::$/.test(addr); + /^::[10]$/.test(addr) || + /^::$/.test(addr) || + /^0/.test(addr); } async function errorIfHostnameResolvesToPrivateIp(options) { diff --git a/core/server/services/oembed.js b/core/server/services/oembed.js index 766359e450..e381cd386f 100644 --- a/core/server/services/oembed.js +++ b/core/server/services/oembed.js @@ -101,8 +101,13 @@ class OEmbed { try { const cookieJar = new CookieJar(); const response = await this.externalRequest(url, {cookieJar}); - const html = response.body; - scraperResponse = await metascraper({html, url}); + + if (this.isIpOrLocalhost(response.url)) { + scraperResponse = {}; + } else { + const html = response.body; + scraperResponse = await metascraper({html, url}); + } } catch (err) { return Promise.reject(err); } diff --git a/test/api-acceptance/admin/oembed.test.js b/test/api-acceptance/admin/oembed.test.js index 9c4137fa21..2ac9ce5835 100644 --- a/test/api-acceptance/admin/oembed.test.js +++ b/test/api-acceptance/admin/oembed.test.js @@ -126,6 +126,31 @@ describe('Oembed API', function () { should.exist(res.body.errors); res.body.errors[0].context.should.match(/insufficient metadata/i); }); + + it('errors when fetched url is an IP address', async function () { + const redirectMock = nock('http://test.com/') + .get('/') + .reply(302, undefined, {Location: 'http://0.0.0.0:8080'}); + + const pageMock = nock('http://0.0.0.0:8080') + .get('/') + .reply( + 200, + 'TESTING', + {'content-type': 'text/html'} + ); + + const url = encodeURIComponent('http://test.com'); + const res = await request.get(localUtils.API.getApiQuery(`oembed/?type=bookmark&url=${url}`)) + .set('Origin', config.get('url')) + .expect('Content-Type', /json/) + .expect('Cache-Control', testUtils.cacheRules.private) + .expect(422); + + pageMock.isDone().should.be.true(); + should.exist(res.body.errors); + res.body.errors[0].context.should.match(/insufficient metadata/i); + }); }); describe('with unknown provider', function () { diff --git a/test/unit/lib/external-request.test.js b/test/unit/lib/request-external.test.js similarity index 100% rename from test/unit/lib/external-request.test.js rename to test/unit/lib/request-external.test.js