Search code examples
androidvisual-studiocordovacontent-security-policytaco

Content Security Policy for Google Fonts/Icons


I am having trouble whitelisting Google's material design icons to show up in a Visual Studio Cordova application (I'm targeting Android 4.x only).

The JS and CSS seem to work fine, but the icons don't show. When the CSP is commented out, they work. I thought that whitelisting the *.googleapis.com would do the trick, but apparently not.

My Index.html, which is based on the default Cordova JS Application, with my modified headers is as follows:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />

    <meta http-equiv="Content-Security-Policy"
          content="default-src 'self' data: gap: https://fonts.googleapis.com https://*.jquery.com https://*.cloudflare.com https://ssl.gstatic.com 'unsafe-inline' 'unsafe-eval';
                   style-src 'self' https://fonts.googleapis.com https://*.cloudflare.com 'unsafe-inline';
                   media-src *">
    <title>Test CSP</title>

    <!--Let browser know website is optimized for mobile-->
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- Zen references -->
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.1/css/materialize.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.1/js/materialize.min.js"></script>
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="css/index.css" />
</head>
<body>
    <nav>
        <div class="nav-wrapper">
            <a href="#!" class="brand-logo">CSP Test</a>
            <a href="#" data-activates="mobile-demo" class="button-collapse"><i class="material-icons">menu</i></a>
            <ul class="right hide-on-med-and-down">
                <li><a class="about" href="#!"><i class="material-icons right">info</i></a></li>
                <li><a class="settings" href="#!"><i class="material-icons right">settings</i></a></li>
            </ul>
            <ul class="side-nav" id="mobile-demo">
                <li><a class="about" href="#">About</a></li>
                <li><a class="settings" href="#">Settings</a></li>
            </ul>
        </div>
        <div class="fixed-action-btn" style="bottom: 45px; right: 24px;">
            <a class="btn-floating btn-large red" href="#">
                <i class="large material-icons">add</i>
            </a>
        </div>
    </nav>

    <!-- Cordova reference, this is added to your app when it's built. -->
    <script src="cordova.js"></script>
    <script src="scripts/platformOverrides.js"></script>

    <script src="scripts/index.js"></script>
</body>
</html>

My Config.Xml, which is the default config, is as follows:

<?xml version='1.0' encoding='utf-8'?>
<widget xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:vs="http://schemas.microsoft.com/appx/2014/htmlapps" id="io.cordova.myapp740f79" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" defaultlocale="en-US">
  <name>BlankCordovaApp1</name>
  <description>A blank project that uses Apache Cordova to help you build an app that targets multiple mobile platforms: Android, iOS, Windows, and Windows Phone.</description>
  <author href="http://cordova.io" email="[email protected]">Apache Cordova Team </author>
  <content src="index.html" />
  <access origin="*" />
  <vs:features />
  <preference name="SplashScreen" value="screen" />
  <preference name="windows-target-version" value="8.1" />

  <!-- Support for Cordova 5.0.0 plugin system -->
  <plugin name="cordova-plugin-whitelist" version="1" />
  <allow-intent href="http://*/*" />
  <allow-intent href="https://*/*" />
  <allow-intent href="tel:*" />
  <allow-intent href="sms:*" />
  <allow-intent href="mailto:*" />
  <allow-intent href="geo:*" />

  <platform name="android">
    <allow-intent href="market:*" />
  </platform>

  <platform name="ios">
    <allow-intent href="itms:*" />
    <allow-intent href="itms-apps:*" />
  </platform>

  <platform name="android">
    <icon src="res/icons/android/icon-36-ldpi.png" density="ldpi" />
    <icon src="res/icons/android/icon-48-mdpi.png" density="mdpi" />
    <icon src="res/icons/android/icon-72-hdpi.png" density="hdpi" />
    <icon src="res/icons/android/icon-96-xhdpi.png" density="xhdpi" />
  </platform>

  <platform name="ios">
    <!-- iOS 8.0+ -->
    <!-- iPhone 6 Plus  -->
    <icon src="res/icons/ios/icon-60-3x.png" width="180" height="180" />
    <!-- iOS 7.0+ -->
    <!-- iPhone / iPod Touch  -->
    <icon src="res/icons/ios/icon-60.png" width="60" height="60" />
    <icon src="res/icons/ios/icon-60-2x.png" width="120" height="120" />
    <!-- iPad -->
    <icon src="res/icons/ios/icon-76.png" width="76" height="76" />
    <icon src="res/icons/ios/icon-76-2x.png" width="152" height="152" />
    <!-- iOS 6.1 -->
    <!-- Spotlight Icon -->
    <icon src="res/icons/ios/icon-40.png" width="40" height="40" />
    <icon src="res/icons/ios/icon-40-2x.png" width="80" height="80" />
    <!-- iPhone / iPod Touch -->
    <icon src="res/icons/ios/icon-57.png" width="57" height="57" />
    <icon src="res/icons/ios/icon-57-2x.png" width="114" height="114" />
    <!-- iPad -->
    <icon src="res/icons/ios/icon-72.png" width="72" height="72" />
    <icon src="res/icons/ios/icon-72-2x.png" width="144" height="144" />
    <!-- iPhone Spotlight and Settings Icon -->
    <icon src="res/icons/ios/icon-small.png" width="29" height="29" />
    <icon src="res/icons/ios/icon-small-2x.png" width="58" height="58" />
    <!-- iPad Spotlight and Settings Icon -->
    <icon src="res/icons/ios/icon-50.png" width="50" height="50" />
    <icon src="res/icons/ios/icon-50-2x.png" width="100" height="100" />
  </platform>

  <platform name="windows">
    <icon src="res/icons/windows/Square150x150Logo.scale-100.png" width="150" height="150" />
    <icon src="res/icons/windows/Square150x150Logo.scale-240.png" width="360" height="360" />
    <icon src="res/icons/windows/Square30x30Logo.scale-100.png" width="30" height="30" />
    <icon src="res/icons/windows/Square310x310Logo.scale-100.png" width="310" height="310" />
    <icon src="res/icons/windows/Square44x44Logo.scale-240.png" width="106" height="106" />
    <icon src="res/icons/windows/Square70x70Logo.scale-100.png" width="70" height="70" />
    <icon src="res/icons/windows/Square71x71Logo.scale-240.png" width="170" height="170" />
    <icon src="res/icons/windows/StoreLogo.scale-100.png" width="50" height="50" />
    <icon src="res/icons/windows/StoreLogo.scale-240.png" width="120" height="120" />
    <icon src="res/icons/windows/Wide310x150Logo.scale-100.png" width="310" height="150" />
    <icon src="res/icons/windows/Wide310x150Logo.scale-240.png" width="744" height="360" />
  </platform>

  <platform name="wp8">
    <icon src="res/icons/wp8/ApplicationIcon.png" width="62" height="62" />
    <icon src="res/icons/wp8/Background.png" width="173" height="173" />
  </platform>

  <platform name="android">
    <splash src="res/screens/android/screen-hdpi-landscape.png" density="land-hdpi"/>
    <splash src="res/screens/android/screen-ldpi-landscape.png" density="land-ldpi"/>
    <splash src="res/screens/android/screen-mdpi-landscape.png" density="land-mdpi"/>
    <splash src="res/screens/android/screen-xhdpi-landscape.png" density="land-xhdpi"/>

    <splash src="res/screens/android/screen-hdpi-portrait.png" density="port-hdpi"/>
    <splash src="res/screens/android/screen-ldpi-portrait.png" density="port-ldpi"/>
    <splash src="res/screens/android/screen-mdpi-portrait.png" density="port-mdpi"/>
    <splash src="res/screens/android/screen-xhdpi-portrait.png" density="port-xhdpi"/>
  </platform>

  <platform name="ios">
    <splash src="res/screens/ios/screen-iphone-portrait.png" width="320" height="480"/>
    <splash src="res/screens/ios/screen-iphone-portrait-2x.png" width="640" height="960"/>
    <splash src="res/screens/ios/screen-ipad-portrait.png" width="768" height="1024"/>
    <splash src="res/screens/ios/screen-ipad-portrait-2x.png" width="1536" height="2048"/>
    <splash src="res/screens/ios/screen-ipad-landscape.png" width="1024" height="768"/>
    <splash src="res/screens/ios/screen-ipad-landscape-2x.png" width="2048" height="1536"/>
    <splash src="res/screens/ios/screen-iphone-568h-2x.png" width="640" height="1136"/>
    <splash src="res/screens/ios/screen-iphone-portrait-667h.png" width="750" height="1334"/>
    <splash src="res/screens/ios/screen-iphone-portrait-736h.png" width="1242" height="2208"/>
    <splash src="res/screens/ios/screen-iphone-landscape-736h.png" width="2208" height="1242"/>
  </platform>

  <platform name="windows">
    <splash src="res/screens/windows/SplashScreen.scale-100.png" width="620" height="300"/>
    <splash src="res/screens/windows/SplashScreen.scale-240.png" width="1152" height="1920"/>
    <splash src="res/screens/windows/SplashScreenPhone.scale-240.png" width="1152" height="1920"/>
  </platform>

  <platform name="wp8">
    <splash src="res/screens/wp8/SplashScreenImage.jpg" width="480" height="800"/>
  </platform>
</widget>

Solution

  • @U1199880,
    I'm going to assume this is your first or close to your first app. You will need to learn how to use parameters. You should play with the example you got from Cordova a bit before you try anything real.

    Here are you mistakes and corrections:

    1) You should get all your assets local, do not get them from the web. While this may work sometimes, if you do this, your app will behave unpredictably.

    Your new header should look like this

    <!--Let browser know website is optimized for mobile-->
    <meta name="viewport" content="width=device-width />
    
    <!-- YOUR CODE WILL NOW LOAD ANYTHING. INCLUDING TROJAN CODE -->
    <meta http-equiv="Content-Security-Policy" 
              content="default-src *; 
                       style-src 'self' 'unsafe-inline' 'unsafe-eval'; 
                       script-src 'self' 'unsafe-inline' 'unsafe-eval';">
    
    <!-- THESE js AND css FILES SHOULD LIVE LOCALLY -->
    <!-- Zen references -->
    <script type="text/javascript" src="jquery-2.1.1.min.js"></script>
    <link rel="stylesheet" href="ajax/libs/materialize/0.97.1/css/materialize.min.css">
    <script src="ajax/libs/materialize/0.97.1/js/materialize.min.js"></script>
    <link rel="stylesheet" href="css/index.css" />
    

    Since you are only doing this for Android. I got rid of the garbage.

    <?xml version='1.0' encoding='utf-8'?>
    <widget xmlns:cdv="http://cordova.apache.org/ns/1.0"
        xmlns:vs="http://schemas.microsoft.com/appx/2014/htmlapps" 
        id="io.cordova.myapp740f79" 
        version="1.0.0" 
        xmlns="http://www.w3.org/ns/widgets" 
        defaultlocale="en-US">
      <name>App1</name>
      <description>A blank project </description>
      <author href="ME" 
          email="[email protected]">Me Team </author>
      <content src="index.html" />
    
    
    <!-- YOUR CODE WILL NOW LOAD ANYTHING. INCLUDING TROJAN CODE -->
      <!-- Support for Cordova 5.0.0 plugin system -->
      <plugin name="cordova-plugin-whitelist" />
      <allow-navigation href="*" />
      <allow-intent href="*" />
      <access origin="*" />
    
      <platform name="android">
        <icon src="res/icons/android/icon-36-ldpi.png" density="ldpi" />
        <icon src="res/icons/android/icon-48-mdpi.png" density="mdpi" />
        <icon src="res/icons/android/icon-72-hdpi.png" density="hdpi" />
        <icon src="res/icons/android/icon-96-xhdpi.png" density="xhdpi" />
      </platform>
      <platform name="android">
        <splash src="res/screens/android/screen-hdpi-landscape.png" density="land-hdpi"/>
        <splash src="res/screens/android/screen-ldpi-landscape.png" density="land-ldpi"/>
        <splash src="res/screens/android/screen-mdpi-landscape.png" density="land-mdpi"/>
        <splash src="res/screens/android/screen-xhdpi-landscape.png" density="land-xhdpi"/>
    
        <splash src="res/screens/android/screen-hdpi-portrait.png" density="port-hdpi"/>
        <splash src="res/screens/android/screen-ldpi-portrait.png" density="port-ldpi"/>
        <splash src="res/screens/android/screen-mdpi-portrait.png" density="port-mdpi"/>
        <splash src="res/screens/android/screen-xhdpi-portrait.png" density="port-xhdpi"/>
      </platform>
    
    </widget>