Content security policy in React app didn't block online script - reactjs

I followed this article to add CSP to my existing react app. I did all the steps written in "Using inline script or style" there and here is my config-overrides.js file:
const { override } = require('customize-cra');
const cspHtmlWebpackPlugin = require('csp-html-webpack-plugin');
const cspConfigPolicy = {
'default-src': "'none'",
'base-uri': "'self'",
'object-src': "'none'",
'script-src': ["'self'"],
'style-src': ["'self'"],
'img-src': ["'self'"],
};
function addCspHtmlWebpackPlugin(config) {
if (process.env.NODE_ENV === 'production') {
config.plugins.push(new cspHtmlWebpackPlugin(cspConfigPolicy));
}
return config;
}
module.exports = {
webpack: override(addCspHtmlWebpackPlugin),
};
To test if it works I built the app with npm run build (as CSP is just added to production build) but before, to test if it works I added jquery to the script inside index.html:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Unfortunatey the jquery is added to build, CSP didn't block it.
Am I doing something wrong? Or I misunderstand the content security policy?

Actually you don't need a Package to achieve that, you can just add a <meta> tag as your first element to <head> block inside index.html founded in public folder.
As for jQuery issue, my guess that maybe a hash or nonce that auto generated by csp-html-webpack-plugin is referring to jQuery which could lead to allow it?
Also, please note that using unsafe-eval eval is considered unsafe. And should be avoided.
With that in mind, please note that if you're going to test your site security in some online security tools, it will basically Fail. Yes, adding a <meta> security tags could be enough for basic protection though, you may consider using server-side HTTP Headers for other security vulnerabilities. Actually meta tag is not needed, it's optional.
For instance, as for CSP policies, I've deployed a test react app using <meta> method, when testing on immuniweb.com or gf.dev, you'll see that there is No CSP policy! though, it works fine, see test Here
So if you can configure your server environment, I encourage you to do that. You could use Express with express-csp-header and/or using Nginx as a reverse proxy
If you can't, try setting your <meta> its fairly easy:
Syntax will be:
<meta http-equiv="Content-Security-Policy" content="directive 'source';">
Just like key-value pair where directives are the keys i.e. base-uri, script-src, style-src and sources (with single quotations marks) are the values i.e. self, none, unsafe-inline
See Directive Reference List | Source Reference List
For example since you are using React and React is using inline scripts <script></script>, you'll need to add 'unsafe-inline' to your script directive like so:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self'; base-uri 'self';">
If you were to add some inline CSS or going to use a library like styled-components, you'll need to add 'unsafe-inline' to your style directive as well:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; base-uri 'self';">
If you like to allow some external URLs like google font or analytics:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' www.google-analytics.com 'unsafe-inline'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; font-src 'self' https://fonts.gstatic.com; base-uri 'self';">
Read more about directive and rules here You can also generate your own policy Here

Related

Safe CSP with React inline chunk

I would like to have the safest possible setup for my React front-end. Currently I run server.js out of the /build folder in deployment, so it is in a compiled, production state.
However, I can't use the following CSP which is fairly restrictive, if the js is bundled and inlined:
<meta http-equiv="Content-Security-Policy" content=
"default-src 'none';
object-src 'self';
script-src 'self';
worker-src 'self';
connect-src 'self';
img-src 'self' data:;
style-src 'self';
font-src 'self';
manifest-src 'self';">
I also get
Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'".
Since some node_modules like Draggable seem to dynamically inline styles.
What is an approach for me so that I can keep my code fairly obfuscated to deter attackers as well as a strong CSP? I've heard a webpack plugin might help but I don't really understand how that works in the build pipeline.
I believe I resolved this by changing from true to false the INLINE_RUNTIME_CHUNK value in .env. There is a little more info in this answer: How to use React without unsafe inline JavaScript/CSS code?
Also consider breaking up into .env.development and .env.production: What is the difference between .env.local and .env.development.local?
You can use this approach too https://cssinjs.org/csp/?v=v10.8.2. Implement a ExpressJs server that generates the headers and inject them into the react application. Keep in mind that many libraries already come with csp support and you must apply the generated nonce.

Phonegap Ionic app not working from device with rest API

Now I'm trying to make login call to express rest API with passport Basic Strategy, and on browser everything working fine but from device from Phonegap it's not working. I tried to remove and add cordova-plugin-whitelist plugin. Added following tag to config.xml <allow-navigation href="http://*/*" />. And added to index.html <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'"> I made cors setup. But it didn't help. Also I found out that my requests contains "/proxy/" inside of call.
Here is example: http://192.168.1.189:3000/proxy/http%3A%2F%2F127.0.0.1%3A8080%2Fapi%2Fauth%2Flogin
is it ok? And here is what I'm getting from server:
Thanks in advance.
I spent some time for search and I found a solution:
In my ionic app.js file I just changed the following line:
const BASE_URL = 'http://127.0.0.1:8080/api';
to:
const BASE_URL = 'http://192.168.1.102:8080/api';
and it works for me.

Base64 encoded image is not displaying in ionic framework apps

Iam trying to show base64 encoded image in my ionic app i tried various things with angular binding finally i just put the following code, but it is not working in ionic app it just simply displays:
<img ng-src="data:image/gif;base64,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" style="height: 100px;width:100px">
I have added whitelist to my app.js
.config([
'$compileProvider',
function($compileProvider){
$compileProvider.imgSrcSanitizationWhitelist(/^\s(https|file|blob|cdvfile):|data:image\//);
}
])
and tried with <img src=""> and <img data-ng-src=""> but none of them is working.
Ionic version used is:v 1.2.4. I verified base64 encoded string as well its showing fine on normal webpage. How can i show it in a right way.
I solved it by the following security policy tag in index.html.
<meta http-equiv="Content-Security-Policy" content="img-src 'self' data:;default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src 'self' 'unsafe-inline' *">
try this also with security policy tag
var oldWhiteList = $compileProvider.imgSrcSanitizationWhitelist();
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob):|data:image\//);
it worked for me after long research.

Error Failed to execute 'open' on 'XMLHttpRequest' : Refused to connect 'http://192.168.XX.XXX:8080/TestApp/addRole/ : Ionic

Facing error while calling rest api in ionic.
If I run on browser firefox or chrome then it working fine..
But When I run On android device then it gives following error:
Error: Failed to execute 'open' on 'XMLHttpRequest': Refused to connectto 'http://192.168.XX.XXX:8080/TestApp/addRole/' becuase it violates the document's content security Policy
at Error (native( at file:///android_asset/www/lib/ionic/js/ionic.bundle.js:23357:16
How can I solve this issue
If I set following meta tag in index.html as follow then got error in chrome and android device..Not in firefox
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
On my rest service i set header as follow
responseHeaders.add("Access-Control-Allow-Origin", "*");
responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
I also install whitelist plugin but no luck
How can I solve this issue? please help
On Android you need to set a content-security-policy meta tag in your <head> # index.html.
It would look something like this:
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' data: gap: 'unsafe-eval'; style-src * 'self' 'unsafe-inline'; connect-src * ; script-src * 'self' 'unsafe-inline'; media-src *">
In this occasion there is a lot of unsafe and unnecessary tags which allow almost anything but you can read more about them for example in here:
Cordova whitelist plugin content security policy
In the same page there are also explanations for other stuff like network request whitelist.
Hopefully this gets you through your problems.
Here's my security policy declaration meta on Cordova.. worked for me after 2 days of heavy wandering around the web:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval' *; style-src 'self' 'unsafe-inline'; media-src *; img-src * data: content:;">
I simply added a wildcard at the default-src, inner attribute end.. and definitely am going to develop an above security layer on all of my app inputs, cause it looks like an all access to me.
Saved my day.. hope someone's day too

PhoneGap doesn't want to use REST service no matter what I do

I have a PhoneGap app that I am using AngularJS with. I'm using a pretty simple $http call to my Node backend:
$http.get("http://localhost:6969/random")
.then(function(response) {
$scope.images = response.data;
});
No matter what, PhoneGap never hits the backend. I have tested it in a normal browser and it works as expected.
I have obviously read a bunch about it and most people fix it using whitelisting, but in my config.xml, my whitelisting is about as open as can be:
<plugin name="cordova-plugin-whitelist" source="npm" spec="1.1.0" />
<allow-navigation href="*" subdomains="true" />
<allow-intent href="*" subdomains="true"/>
<access origin="*" subdomains="true"/> <!-- Required for iOS9 -->
What do I have to change? Been wrestling this bug for a few days off and on and it's a bit annoying to not be able to actually create new cool features in my free time.
EDIT: I am serving the app using phonegap serve and testing it using the PhoneGap Developer App.
I would suggest your Content Security Policy might need to be modified to include a connect-src clause to specify where Ajax requests can go to.
Taking the CSP meta tag that you posted in the comments:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src: 'self' 'unsafe-inline' 'unsafe-eval'" />
I would suggest amending this to open up Ajax requests to anywhere, see if that helps then reign it in to just domain(s) you want to support after.
Suggested CSP would be:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; connect-src *">
If that works and you want to lock down to just one domain later you'd want something like:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; connect-src http://api.mydomain.com">
Additionally I think you will need to change your app's code to connect to your server by hostname or IP address, so so that on the device it doesn't confuse 'localhost' with the device itself and try to make a connection to port 6969 on the device.
So:
$http.get("http://localhost:6969/random")
May need to become:
$http.get("http://myhost.mydomain.com:6969/random")
Or
$http.get("http://xxx.xxx.xxx.xxx:6969/random")
There's some resources on this online:
Content Security Policy page
A blog post I wrote on this topic

Resources