jquerywordpresssubresource-integrity

Hash Mismatch for Wordpress jquery 1.12.4


I am using latest (4.9.8) WordPress and currently working on adding integrity attribute to <script> tags. The version of /wp-includes/js/jquery/jquery.js is 1.12.4. The SRI (hash) for this is

sha256-/EjR2A7OcaeaezmHf0EE1J09psNmXPbcIDAA+330RH4=.

Version 1.12.4 on jquery site and Cloudflare CDN has SRI

sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=

The code looks minified, but the SRI does not match minified version either. SRI attributes on Cloudflare and jquery sites match for minified versions too.


Solution

  • The https://raw.githubusercontent.com/WordPress/WordPress/master/wp-includes/js/jquery/jquery.js used by Wordpress is a copy of https://code.jquery.com/jquery-1.12.4.min.js that’s been modified to add jQuery.noConflict(), to put it in “no conflict” mode https://api.jquery.com/jquery.noconflict/.

    I guess Wordpress does that to prevent any conflict in the case where, in your Wordpress site, you might load some other library that uses $ as a function or variable name.

    So, if you want to use that /wp-includes/js/jquery/jquery.js file with subresource integrity, you need to use a different hash than the upstream version — because the contents are different.


    More details

    https://raw.githubusercontent.com/WordPress/WordPress/master/wp-includes/js/jquery/jquery.js1 diffed against https://code.jquery.com/jquery-1.12.4.min.js shows this:

    --- jquery-1.12.4.min.js    2018-10-30 08:44:12.545350081 +0900
    +++ jquery.js   2018-10-30 08:38:48.978809390 +0900
    @@ -3,3 +3,4 @@
     }return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject...
     marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px"...
     padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function...
    +jQuery.noConflict();
    \ No newline at end of file
    

    1https://raw.githubusercontent.com/WordPress/WordPress/922f83a69f47c68d9f7adac6520d1de04075d8be/wp-includes/js/jquery/jquery.js, to be exact.

    So, https://raw.githubusercontent.com/WordPress/WordPress/master/wp-includes/js/jquery/jquery.js adds a jQuery.noConflict(); line and drops the newline from the end of the file.

    If you remove that jQuery.noConflict(); line and add a newline to the end of that file, then you’ll end up with contents identical to the upstream https://code.jquery.com/jquery-1.12.4.min.js. And if you generate a hash for that modified file, you get this:

    $ shasum -b -a 256 jquery-wordpress-modified.js \
        | awk '{ print $1 }' | xxd -r -p | base64
    
    ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=
    

    …or…

    $ cat jquery-wordpress-modified.js \
        | openssl dgst -sha256 -binary | openssl base64 -A
    
    ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=
    

    …which matches the hash shown for https://code.jquery.com/jquery-1.12.4.min.js at the jQuery site:

    <script
      src="https://code.jquery.com/jquery-1.12.4.min.js"
      integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
      crossorigin="anonymous"></script>
    

    The version of /wp-includes/js/jquery/jquery.js is 1.12.4. The SRI (hash) for this is

    sha256-/EjR2A7OcaeaezmHf0EE1J09psNmXPbcIDAA+330RH4=
    

    https://raw.githubusercontent.com/WordPress/WordPress/master/wp-includes/js/jquery/jquery.js (which currently shows v1.12.4), when I check it, doesn’t have that hash above; instead it has this:

    $ curl -s -O https://raw.githubusercontent.com/WordPress/WordPress/922f83a69f47c68d9f7adac6520d1de04075d8be/wp-includes/js/jquery/jquery.js \
        && cat jquery.js | openssl dgst -sha256 -binary | openssl base64 -A
    
    +gVfL3xbc127txlU9DSu15klvAD/L/vD7PxKeQaJpyM=
    

    See also the Tools for generating SRI hashes section of the MDN article on Subresource Integrity.