How can I make sure that my JavaScript files delivered over a CDN are not altered?

JavascriptCode Signing

Javascript Problem Overview


I am working on a scenario in which some JavaScript files are to be hosted on a CDN. I want to have some mechanism so that when these file are downloaded on user side, I can ensure that the files were not tampered with and are indeed coming from the specified CDN.

I understand that the task is very easy if I am using SSL, but still, I want to ensure that the right files are served even on HTTP without SSL.

As far as I could search, there is no existing mechanism like digital signature for JavaScript files which is supported across platforms. Perhaps it's not needed?

Is there some method built in to browsers to verify the author of the JavaScript files? Is there anything I can do to do this in a secure way?

Javascript Solutions


Solution 1 - Javascript

As a matter of fact, a feature like this is currently being drafted under the name of Subresource Integrity. Look into the integrity attribute of the <script> tag. While not yet fully adopted across the board, it fulfills just this purpose.

> integrity > >Contains inline metadata that a user agent can use to verify that a fetched resource has been delivered free of unexpected manipulation. See Subresource Integrity.

Source

> Subresource Integrity (SRI) is a security feature that enables browsers to verify that files they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched file must match.

Source


Example:

<script src="https://example.com/example-framework.js"
    integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
    crossorigin="anonymous"></script>

Note however that this will not protect you against Man in the Middle attacks if you are transferring your resources via plain HTTP. In this case, the hash code can be spoofed by the attacker, rendering the defense against manipulated script files useless.

For this reason, you should always use secure HTTPS connections instead of plain HTTP in addition to the security measures described above.

Solution 2 - Javascript

You're looking for subresource integrity checks.

For example, here's the jQuery CDN snippet:

<script src="https://code.jquery.com/jquery-3.1.0.js"
        integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
        crossorigin="anonymous"></script>

Solution 3 - Javascript

Disclaimer: As always, you should only consider these mechanisms to be of any use when using https, as they can easily be disabled via MitM with http

In addition to the mechanism in the above answers, you can also use the content-security policy http response headers on the parent page.

http://www.html5rocks.com/en/tutorials/security/content-security-policy/

> Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng=' > >There are a few things to note here. The sha*- prefix specifies the algorithm used to generate the hash. In the example above, sha256- is used. CSP also supports sha384- and sha512-. When generating the hash do not include the

Solution 4 - Javascript

There's an important point about what this kind of signing can and cannot do. It can protect the user from hypothetical attacks in which someone modifies your code. It cannot assure your site that your code is the code being executed. In other words, you still can't trust anything that comes to your site from the client.

Solution 5 - Javascript

If your adversary model permits an attacker to modify JavaScript files as they are delivered from a CDN, then your adversary model permits an attacker to modify the referring source as it is delivered to remove any attempt at verification, to alter the source address to other than the CDN, and/or to remove the reference to the JavaScript entirely.

And lets not open the can of worms of how your application can determine whether the user's resolver is or is not correctly resolving to the CDN via HTTP requests (or any other mechanism that doesn't have a verified chain of trust).

/etc/hosts:

#  ...
1.2.3.4    vile-pirates.org    trustworthy.cdn
#  ...

Solution 6 - Javascript

You can ensure this with Subresource Integrity. Many public CDNs include SRI hashes in the embeddable code offered on CDN websites. For example, on PageCDN, when you click on jquery file on the jQuery CDN page, you get the option to either copy the URL or use the script tag that contains SRI hash as below:

<script src="https://pagecdn.io/lib/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>

On page load, browser will issue a request for this resource and on completion of request it will match the hash of the received file with the one given as the integrity value in script tag. If both hashes do not match, browser will discard the jquery file.

At the moment, this feature is supported by 91% of browsers worldwide. More details on caniuse.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionbaba26View Question on Stackoverflow
Solution 1 - JavascriptTimoStaudingerView Answer on Stackoverflow
Solution 2 - JavascriptBrianView Answer on Stackoverflow
Solution 3 - JavascriptFabio BeltraminiView Answer on Stackoverflow
Solution 4 - JavascriptddyerView Answer on Stackoverflow
Solution 5 - JavascriptEric TowersView Answer on Stackoverflow
Solution 6 - JavascriptstefanView Answer on Stackoverflow