CVE-2022-0528 (JavaScript, published 2022-03-03T07:15Z)
Description: value: Server-Side Request Forgery (SSRF) in GitHub repository transloadit/uppy prior to 3.3.1.


Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-918 \u2014 Server-Side Request Forgery (SSRF)
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
Repository: https://github.com/transloadit/uppy
Files changed:
.env.example
bin/companion.sh
packages/@uppy/companion/src/companion.js
packages/@uppy/companion/src/server/controllers/url.js
packages/@uppy/companion/src/server/logger.js
packages/@uppy/companion/src/server/provider/facebook/index.js
packages/@uppy/companion/src/server/provider/instagram/graph/index.js
packages/@uppy/companion/src/server/provider/unsplash/index.js
packages/@uppy/companion/src/standalone/helper.js
packages/@uppy/companion/test/__tests__/companion.js
packages/@uppy/companion/test/mockserver.js
website/src/docs/companion.md
Commit message: replace debug

remove debug flag
instead add allowLocalUrls (COMPANION_ALLOW_LOCAL_URLS)
which defaults to false
this fixes https://huntr.dev/bounties/8b060cc3-2420-468e-8293-b9216620175b/

also don't allow localhost for any providers getURLMeta


Vulnerable code:
  debug: true,
 * @param {boolean} debug whether the server is running in debug mode
const validateURL = (url, debug) => {
    require_tld: !debug,
    const { debug } = req.companion.options
    if (!validateURL(req.body.url, debug)) {
    const urlMeta = await getURLMeta(req.body.url, !debug)
  const { debug } = req.companion.options
  if (!validateURL(req.body.url, debug)) {
    const { size } = await getURLMeta(req.body.url, !debug)
    return downloadURL(req.body.url, !debug, req.id)
  // @todo: this function should depend on companion's debug option instead
        getURLMeta(this._getMediaUrl(body))
        getURLMeta(body.media_url)
      getURLMeta(body.links.download)
    debug: process.env.NODE_ENV && process.env.NODE_ENV !== 'production',

Fixed code:
# NOTE: Only enable this in development. Enabling it in production is a security risk
COMPANION_ALLOW_LOCAL_URLS=true

    COMPANION_ALLOW_LOCAL_URLS="true" \
  allowLocalUrls: false,
 * @param {boolean} ignoreTld whether to allow local addresses
const validateURL = (url, ignoreTld) => {
    require_tld: !ignoreTld,
    const { allowLocalUrls } = req.companion.options
    if (!validateURL(req.body.url, allowLocalUrls)) {
    const urlMeta = await getURLMeta(req.body.url, !allowLocalUrls)
  const { allowLocalUrls } = req.companion.options
  if (!validateURL(req.body.url, allowLocalUrls)) {
    const { size } = await getURLMeta(req.body.url, !allowLocalUrls)
    return downloadURL(req.body.url, !allowLocalUrls, req.id)
        getURLMeta(this._getMediaUrl(body), true)
        getURLMeta(body.media_url, true)
      getURLMeta(body.links.download, true)
    allowLocalUrls: process.env.COMPANION_ALLOW_LOCAL_URLS === 'true',
it('respects allowLocalUrls', async () => {
  const server = getServer()
  const url = 'http://localhost/'

  let res

  res = await request(server)
    .post('/url/meta')
    .send({ url })
    .expect(400)

  expect(res.body).toEqual({ error: 'Invalid request body' })

  res = await request(server)
    .post('/url/get')
    .send({
      fileId: url,
      metadata: {},
      endpoint: 'http://url.myendpoint.com/files',
      protocol: 'tus',
      size: null,
      url,
    })
    .expect(400)

  expect(res.body).toEqual({ error: 'Invalid request body' })
}, 1000)

  COMPANION_ALLOW_LOCAL_URLS : 'false',
# corresponds to the allowLocalUrls option
export COMPANION_ALLOW_LOCAL_URLS=false

  allowLocalUrls: false,
19. **allowLocalUrls(optional)** - A boolean flag to tell Companion whether to allow requesting local URLs. Note: Only enable this in development. **Enabling it in production is a security risk.**