0

I have the most trivial local http server which is wired to serve a single file from localhost. I can navigate to the resource from the browser just fine, but I need to be able to fetch the resource using the fetch web api from the browser console and that just does not work unless the console is from exactly the same origin.

Please, observe:

The resource is live:

C:\> (Invoke-WebRequest http://localhost:49152/C:/temp/events/62.0.0.32712-0515-834-4.build.Main_events.json).StatusCode
200
C:\>

When the console is from the same origin: enter image description here

Otherwise: enter image description here

I understand I can ignore the first error - the one mentioning http://127.0.0.1:9001. So my problem is the second error:

Refused to connect to 'http://localhost:49152/C:/temp/events/62.0.0.32712-0515-834-4.build.Main_events.json' because it violates the document's Content Security Policy.

So far I failed to figure out how to fix it. It seems to be the classical CORS issue, but when running fetch the browser does not issue any preflight OPTIONS request. I know this because I am running Fiddler. It shows the GET request from the same origin, but absolutely no request from another origin.

The original fetch code that I am trying to make work is this:

    const request = fetch(url)
                        .then(response => response.blob())
                        .then(blob => {
                          globals.dispatch(Actions.openTraceFromFile({
                            file: new File([blob], fileName),
                          }));
                        })
                        .catch(e => alert(`Could not load local trace ${e}`));

It comes from https://www.ui.perfetto.dev/ which I am trying to make load my trace file non interactively.

(This question is related to How to open a chrome trace file with ui.perfetto.dev non interactively? and How can I open chrome browser with disabled document's content security policy?)

I tried running chrome with the --disable-web-security flag, which is supposed to disable CORS validation (to the best of my understanding of this flag). To no avail.

Is there anything I can do to make it work?


The web server source code:

function NavigateToFile(
    [Parameter(Mandatory)][ValidateScript({ Test-Path $_ -PathType Leaf })]$FilePath,
    [scriptblock]$Action
)
{
    $port = Get-OpenTcpPort
    $http = [Net.HttpListener]::new()
    $http.Prefixes.Add("http://localhost:$Port/")
    $http.Start()

    $FilePath = (Get-Item $FilePath).FullName.Replace('\', '/')
    $ExpectedUrl = "$($http.Prefixes)$FilePath"
    $ExpectedUrl | ForEach-Object $Action

    try
    {
        $run = $true
        while ($http.IsListening -and $run)
        {
            $context = $http.GetContext()
            Write-Host "$($context.Request.HttpMethod) $($context.Request.Url)"
            if ($context.Request.HttpMethod -eq 'GET')
            {
                if ($context.Request.Url -eq $ExpectedUrl)
                {
                    $buffer = [IO.File]::ReadAllBytes($FilePath)
                }
                else
                {
                    $buffer = [Text.Encoding]::UTF8.GetBytes("Terminated")
                    $run = $false
                }
                $context.Response.ContentLength64 = $buffer.Length
                $context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
                $context.Response.OutputStream.Close()
            }
        } 
    }
    finally
    {
        $http.Close();
    }
}
mark
  • 59,016
  • 79
  • 296
  • 580

1 Answers1

0

This is not CORS, it's the Content Security Policy, defined here:

https://github.com/google/perfetto/blob/master/ui/src/frontend/index.ts#L127

It supports only fetch from localhost:9001 to reduce the attack surface.

If you make your webserver listen on port 9001 rather than a random port, the error should go away.

primiano
  • 78
  • 2