iOS Refused to connect because it appears in neither the connect-src directive nor the default-src directive of the Content Security Policy

ErikBrandsma picture ErikBrandsma · Dec 12, 2016 · Viewed 18k times · Source

So I made a phonegap app which uses socket.io to do stuff.
I have the following Content-Security-Policy (CSP)

<meta http-equiv="Content-Security-Policy" content="
                                default-src * data: blob: ws: wss:;
                                style-src * 'unsafe-inline'; 
                                script-src * 'unsafe-inline' 'unsafe-eval';
                                connect-src * ws: wss:;">

When I start the app on safari / iOS I get the following error:

Refused to connect to ws://10.0.1.63:3000/socket.io/?EIO=3&transport=websocket&sid=xTaMJwP3rVy3UnIBAAAi 
because it appears in neither the connect-src directive nor the default-src directive of the Content Security Policy.

AND:

SecurityError (DOM Exception 18): The operation is insecure.

The same app with the same CSP works just fine on Chrome / Android but not on Safari / iOS.
I think this has something to do with:
a refined content security policy (WebKit)

Resources that seem to come up a lot:

Why is it saying "Refused to connect to "URL starting with ws:" because it appears in neither the connect-src directive nor the default-src directive of the Content-Security-Policy even though it is mentioned in both?

Okay, safari / iOS is more strict than chrome / Android when it comes to this, all fine, but it still needs to enable me to allow the connection through. This is really frustrating for an app developer! Solutions?

EDIT: Made a bug report on bugs.webkit.org: https://bugs.webkit.org/show_bug.cgi?id=165754

Answer

ErikBrandsma picture ErikBrandsma · Dec 15, 2016

Okay so this is kind of dumb, but OK, i'll keep this answer so future people can see it and don't have to deal with this problem

What I did wrong was:
I had the following head:

<head>
    <meta charset="utf-8" />
    <!--<meta http-equiv="Content-Security-Policy" 
    content="default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline' 'unsafe-eval'" />-->
    <meta http-equiv="Content-Security-Policy" content="
                            default-src * data: blob: ws: wss: gap://ready file://*;
                            style-src * 'unsafe-inline'; 
                            script-src * 'unsafe-inline' 'unsafe-eval';
                            connect-src * ws: wss:;">
    <meta name="format-detection" content="telephone=no" />
    <meta name="msapplication-tap-highlight" content="no" />
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
    <meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src"/>
    <link rel="stylesheet" type="text/css" href="css/reset.css" />
    <link rel="stylesheet" type="text/css" href="css/index.css" />
    <title>Kerst app!</title>
</head>

And I didn't notice that I had the "Content-Security-Policy" meta tag twice
I know right? The duplicate caused iOS to just take the latest one which was more strict. Removed the duplicate, worked the first time around.

And finally the corect Code

<head>
    <meta charset="utf-8" />
    <!--<meta http-equiv="Content-Security-Policy" 
    content="default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline' 'unsafe-eval'" />-->
    <meta http-equiv="Content-Security-Policy" content="
                            default-src * data: blob: ws: wss: gap://ready file://*;
                            style-src * 'unsafe-inline'; 
                            script-src * 'unsafe-inline' 'unsafe-eval';
                            connect-src * ws: wss:;">
    <meta name="format-detection" content="telephone=no" />
    <meta name="msapplication-tap-highlight" content="no" />
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
    <link rel="stylesheet" type="text/css" href="css/reset.css" />
    <link rel="stylesheet" type="text/css" href="css/index.css" />
    <title>Kerst app!</title>
</head>