CVE-2022-24856 (Markdown, published 2022-05-17T16:15Z)
Description: value: FlyteConsole is the web user interface for the Flyte platform. FlyteConsole prior to version 0.52.0 is vulnerable to server-side request forgery (SSRF) when FlyteConsole is open to the general internet. An attacker can exploit any user of a vulnerable instance to access the internal metadata server or other unauthenticated URLs. Passing of headers to an unauthorized actor may occur. The patch for this issue deletes the entire `cors_proxy`, as this is not required for console anymore. A patch is available in FlyteConsole version 0.52.0. Disable FlyteConsole availability on the internet as a workaround.
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/flyteorg/flyteconsole
Files changed:
CONTRIBUTING.md
Dockerfile
README.md
index.js
Commit message: feat: cleanup (#389)

Signed-off-by: Carina Ursu <carina@union.ai>

Co-authored-by: Carina Ursu <carina@union.ai>

Vulnerable code:
## CORS Proxying: Recommended Setup

In the common hosting arrangement, all API requests will be to the same origin
serving the client application, making CORS unnecessary. However, if you would like
to setup your local dev enviornment to target a FlyteAdmin service running on a different
domain you will need to configure your enviornment to support CORS. One example would be
hosting the Admin API on a different domain than the console. Another example is
when fetching execution data from external storage such as S3.

The fastest (recommended) way to setup a CORS solution is to do so within the browser.
If you would like to handle this at the Node level you will need to disable authentication
(see below).

_NOTE:_ Do not configure for both browser and Node solutions.

These instructions require using Google Chrome. You will also need to identify the
URL of your target FlyteAdmin API instance. These instructions will use
`https://different.admin.service.com` as an example.

  && mv dist corsProxy.js index.js env.js plugins.js /app
* `CORS_PROXY_PREFIX` (default: `/cors_proxy`)

    Sets the local endpoint for [CORS request proxying](CONTRIBUTING.md#cors-proxying-recommended-setup).

### CORS Proxying: Recommended setup

In the common hosting arrangement, all API requests will be to the same origin
serving the client application, making CORS unnecessary. However, if you would like
to setup your local dev enviornment to target a FlyteAdmin service running on a different
domain you will need to configure your enviornment support CORS. One example would be
hosting the Admin API on a different domain than the console. Another example is
when fetching execution data from external storage such as S3.

The fastest (recommended) way to setup a CORS solution is to do so within the browser. 
If you would like to handle this at the Node level you will need to disable authentication
(see below)

> Do not configure for both browser and Node solutions. 

These instructions require using Google Chrome. You will also need to identify the 
URL of your target FlyteAdmin API instance. These instructions will use
`https://different.admin.service.com` as an example.


const http = require('http');
const https = require('https');
const url = require('url');

/** Mounts a proxy at `basePath` such that requests of the form
 * `${basePath}/http://www.example.com?queryString=value` will be converted to
 * `http://www.example.com?queryString=value`, preserving any request headers.
 * The response is piped directly to the client with no processing.
 */
module.exports = function corsProxy(basePath) {
  const pathOffset = basePath.length;
  return function (req, res, next) {
    const pathIndex = req.url.indexOf(basePath);
    // base path doesn't match, ignore
    if (pathIndex < 0) {
      return next();
    }

    const targetUrl = req.url.substring(pathIndex + pathOffset + 1);
    const config = url.parse(targetUrl);
    config.method = req.method;

    // We need to use a different request class depending on the
    // protocol
    const handler = config.protocol === 'https:' ? https : http;

    const proxyReq = handler.request(config, function (proxyRes) {
      res.writeHead(proxyRes.statusCode, proxyRes.headers);
      proxyRes.pipe(res, {
        end: true,
      });
    });

    proxyReq.on('error', (err) => res.status(500).send(err));

    // Copy over all headers except for 'Host', since that value would
    // point to *this* server, and not the remote server.
    Object.keys(req.headers).forEach((key) => {
      if (key.toLowerCase() === 'host') {
        return;
      }
      proxyReq.setHeader(key, req.headers[key]);
    });

    req.pipe(proxyReq, {
      end: true,
    });
  };
};
const corsProxy = require('./corsProxy.js');
app.use(corsProxy(`${env.BASE_URL}${env.CORS_PROXY_PREFIX}`));

Fixed code:
  && mv dist index.js env.js plugins.js /app