Content Security Policy blocking AJAX but the domain is valid - javascript

I'm using Firefox console to run some JS from a github page (https://github.com/user/repo/pull/1/files specifically).
I'd like to be able to load the content of a file of the repo, and for that I'm using
var client = new XMLHttpRequest();
client.open("GET", "https://github.com/user/repo/raw/master/path-to-file", true);
client.onreadystatechange = function() {
alert(client.responseText + client.responseURL);
}
client.send();
The problem is that the content actually is at https://raw.githubusercontent.com/user/repo/master/path-to-file and the url I'm loading (which is the one the Raw button points to in the github webpage) is redirecting to that one.
Firefox errors in the console with:
Content Security Policy: The page’s settings blocked the loading of a resource at
https://raw.githubusercontent.com/user/repo/master/path-to-file
(“connect-src https://github.com https://uploads.github.com
https://status.github.com https://collector.githubapp.com
https://api.github.com https://www.google-analytics.com
https://github-cloud.s3.amazonaws.com wss://live.github.com”).
Is there a way to load that file in some way?
I think I need to run the request from the github page so that a file is accessible even if it's in a private repo (since the session of the user is used when sending the request).
I'm sending a request to a page that it's in the CSP, and that page does the redirect, so I don't see why the CSP should block me as I didn't try to access an "unauthorized" resource.
The alternative would be to load the github web page at https://github.com/user/repo/blob/master/path-to-file, but that means I'd have to parse it to remove all the displaying tags, and it's brittle as every change to github might break the script.

Related

Why does CORS block my Http request when sent from the browser but not from the terminal

I am a little confused on the security provided by CORS. Below are two HTTP requests that are practically the same, one works the other does not, one is via curl the other is javascript in the browser.
Terminal
$ curl https://www.google.com/
--> Returns a page
Browser:
// Open the console in the browser (or spin put localhost)
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.google.com");
xhr.send();
--> CORS Error
Try again:
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.google.com");
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.setRequestHeader("Access-Control-Allow-Methods", 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
xhr.setRequestHeader("Access-Control-Allow-Headers", 'Origin,Authorization,Content-Type,X-Auth-Token');
xhr.setRequestHeader("Access-Control-Allow-Credentials", 'true')
xhr.send();
--> CORS Error still
So I am guessing the google.com server has it set to only accept requests from the google domain. But when I curl from my terminal that isn't part of the google domain I get a 200 response with HTML, ect.
So why would the server respond to my terminal with no domain, but doesn't respond when I use javascript in the browser?
Thanks ^.^
CORS is a security feature that in the end is implemented by your browser. Which is why you would never see CORS errors when curling from a terminal. See also: this post from mozilla
which says:
Cross-Origin Resource Sharing (CORS (en-US)) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.
CORS is a feature provided by the browser.
CORS is a mechanism which aims to allow requests made on behalf of you and at the same time block some requests made by rogue JS and is triggered whenever you are making an HTTP request to:
a different domain (eg. site at example.com calls api.com)
a different sub domain (eg. site at example.com calls api.example.com)
a different port (eg. site at example.com calls example.com:3001)
a different protocol (eg. site at https://example.com calls http://example.com)
Please find the attached article - https://medium.com/#baphemot/understanding-cors-18ad6b478e2b

REST API in Wordpress for affiliation system

I have a web page with links towards other web pages. Once an user clicks in one of those links, a cookie is created, so in case he makes a purchase in the web page, the info related to this link is sent to us through an "API call".
So far, the code I have used in the following:
var storeCookie = getCookie("COOKIE_NAME"); //gets the cookie if it was previously created
if(tiendaCookie!=""){
var request = new XMLHttpRequest();
var url="URL TO A .PHP FILE IN MY SERVER";
peticion.open("POST",url,true);
peticion.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
peticion.send("PARAMETERS OF THE CALL")
The web pages with links on our web page added this code to their web page so the affiliation system can work but we found that when that code is called, the following is returned:
Cross-Origin Read Blocking (CORB) blocked cross-origin response "URL TO A .PHP FILE IN MY SERVER" with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
I know this is not the right way to set up an API endpoint but I have no knowledge about how to proceed. I was going to try this plugin (https://wordpress.org/plugins/rest-api/) but it looks it is not supported in the latest versions of Wordpress.
What would be the right way to do what I am trying?
Thank you.
EDIT
I have done some more research and I have discovered that the problem might be in my .PHP file, because of:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
But I have this code on the .PHP file:
header("Access-Control-Allow-Origin: *");
What can I be missing?

firebase storage cors strange Behaviour

I'm building an app in witch the user see a set of downsized images and than press " ok" for the app to download all of the original files, put them into a zip file and send the zip file.
the app is using polymer, polymerfire, firebase (including the storage).
during the upload of the images i save in the database both the download url and the storage reference for both the original file and the downsized one.
when i put the download url in the iron-image element to show the images in the browser everything works perfectly, the downsized images are shown on the screen.
When i try to download the fullsize images via XMLHttpRequest() i get the Cors error.
I can't understand why, both request are coming from the same app, why two different cors response?
here is the code for the XMLHttpRequest() (mostly copied from the firebase documentation):
for (var z = 0; z < visita.immagini.length; z++) {
var immagine =visita.immagini[z]
var storage = firebase.storage();
var pathReference = storage.ref('immagini/'+ immagine.original.ref);
pathReference.getDownloadURL().then(function(url) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function(event) {
var blob = xhr.response;
console.log(blob);
};
xhr.open('GET', url);
xhr.send();
}).catch(function(error) {
console.log(error);
});
}
and here is the error response:
XMLHttpRequest cannot load ***** [image link]******. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access.
note that if i copy the ***** [image link]****** and put in another tab of the browser i can see without problems.
I finally found some information on CORS + storage as asked. Check out the firebase docs on storage here: https://firebase.google.com/docs/storage/web/download-files#cors_configuration.
Firstly, you will need gsutil (https://cloud.google.com/storage/docs/gsutil_install).
Then make a file named cors.json somewhere in your project with the following content:
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
Finally run:
gsutil cors set cors.json gs://<your-cloud-storage-bucket>
These steps worked for me!
This is also answered here: Firebase Storage and Access-Control-Allow-Origin, which I found after answering.
The section on headers in the Firebase “Deployment Configuration” docs says that to enable cross-origin requests for images, you must add to your firebase.json something like this:
"headers": [ {
"source" : "**/*.#(jpg|jpeg|gif|png)",
"headers" : [ {
"key" : "Access-Control-Allow-Origin",
"value" : "*"
} ]
} ]
when i put the download url in the iron-image element to show the
images in the browser everything works perfectly, … When i try to
download the fullsize images via XMLHttpRequest() i get the Cors
error. I can't understand why, both request are coming from the same
app, why two different cors response?
Because browsers block cross-origin XHR requests unless the server receiving the requests uses CORS to allow them, by responding with an Access-Control-Allow-Origin: * header.
note that if i copy the ***** [image link]****** and put in another
tab of the browser i can see without problems.
That’s expected. When you put a URL into your browser’s address bar, it’s not a cross-origin request—instead it’s just you navigating directly to a URL.
But when you put that URL into the JavaScript for a Web application running at some origin on the Web, then when that request is sent, it’s not you navigating directly to the URL but instead it’s some Web application making a cross-origin request to another Web site.
So browsers by default block such cross-origin requests from frontend JavaScript code. But to opt-in to receiving such requests, a site can include the Access-Control-Allow-Origin header in its response to the browser. If the browser sees that header, it won’t block the request.
For more details, see the HTTP access control (CORS) article at MDN.

How to authorize user in my chrome extension?

What am I building is simple chrome extension which adds my script to all pages user visit like this
in contentscript.js:
var s = document.createElement('script');
s.src = 'https://localhost:3000/js/hack.js';
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
on rails-backend there is simple login-password and omniauth(oauth) authorization via devise gem.
If I authorize on rails pages and later in hack.js I try to make some ajax calls to my local server via XMLHttpRequest - it tries its best to assure me that user is not authorized.
I bet it can be solved via opening invisible iframe somewhere, but that's hellova pain, may be there are some more handy methods?
To do an authorized request, you probably have to get your script in an XHR, where you can add various auth headers. Then the script can be injected as inline code instead of supplying an src.
Do note that content scripts can do cross-domain XHR for all sites that have host permissions in the manifest, even if the page is not allowed to do it.
Since the page's Content Security Policy can potentially forbid injection of a script with your URL in the src, but injecting it as inline script sort of bypasses CSP, it's a superior method anyway.

My AJAX request object doesn't properly resolve the protocol portion of the URL

I'm trying to send an AJAX request from a secure page, but the XMLHttpRequest object doesn't properly resolve the protocol portion of the URL. This behavior is identical in Safari, Chrome, and Canary.
Here's my JavaScript:
function sendGETRequest(url, params, callback) {
"use strict";
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status !== 200) {
callback({ajaxError: true, status: req.status});
} else {
callback(req);
}
}
};
req.open("GET", url + "?" + params, true);
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
req.send();
}
Here are some different URLs passed to sendGETRequest(), along with their results:
url = "ajax/";
GET https://mydomain/mypage/ajax/?params 404 (NOT FOUND)
The above is the expected behavior: the relative url is correctly resolved with protocol intact.
url = "/ajax/";
The page at https://mydomain/mypage/ displayed insecure content from http://mydomain/ajax/?params.
Here, the realtive url is correctly appended to the domain root, but with the wrong protocol.
url = "https://mydomain/ajax/";
The page at https://mydomain/mypage/ displayed insecure content from http://mydomain/ajax/?params.
Here, the protocol is just ignored.
To be clear, I'm not trying to work around the same origin policy; I want to send an AJAX request from a secure page to a resource with the same (secure) origin. How can I accomplish this simple task?
There is a conversation here about this topic: http://bytes.com/topic/javascript/answers/459071-ajax-https
One of the last posts states "Just to be absolutely unambiguous; XML HTTP requests work over https
exactly as they do over http. If they did not our QA department would
have said something by now as they test over https almost exclusively"
Perhaps the server is not using Https (ssl) at the point where the request is being made: mydomain/ajax/.
This has nothing to do with HTTP and HTTPS. As you mentioned in a comment, the request is never being sent due to same-origin policy. How can the request be using the wrong policy if the request is never sent? What is confusing you is that whatever program/add-on/tool/etc that is generating the error message is showing "HTTP" instead of "HTTPS". The request IS and ALWAYS respects HTTPS when HTTPS is set.
Your real issue is quite simply that you are violating cross-origin policy. See this:
https://developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs
You cannot go UP the directory tree, only down. In the first example, you are requesting a subfolder. That's fine. In the second and third examples, you are requesting a page from a parent directory (ie, instead of https://mydomain/mypage/ajax/ you are asking for https://mydomain/ajax/. You cannot make a request up a directory tree like that.
Either move your index page up to the root of the domain, or change the same-origin policy header being sent on the files, or make a sub directory on the server handle the request (you can use something like PHP's include to just include the parent file).
This is a bug in WebKit. It's been fixed in Safari 5 for Lion but not Snow Leopard, and it's been fixed in Chrome but not Canary,... helluva a bug.

Categories

Resources