Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate remaining jQuery #915

Merged
merged 19 commits into from Jan 14, 2019
Merged

Translate remaining jQuery #915

merged 19 commits into from Jan 14, 2019

Conversation

buck54321
Copy link
Member

@buck54321 buck54321 commented Jan 6, 2019

This is a full translation of all remaining jQuery to native JS.

The strip-js module is used to replace jQuery.parseHTML and to scrub inserted HTML for cross-site scripting defense. It's an improvement over parseHTML all around, but doesn't cover some vulnerabilities from older browsers.

The DOMPurify module is brought in to replace jquery.parseHTML, and to scrub inserted HTML as an XSS defense.

The following are the major points to check if testing.

Address page

  1. QR Code
  2. Matching tx hash highlighted on hover over source link.
  3. 4 sets of buttons
  4. radio buttons for "Sent and Received" chart view

Charts page

  1. Chart select
  2. Night mode toggle

Mempool page

  1. Top counters incrementing on update
  2. Rows being inserted on update

It looks like #718 changed the response type for the getmempooltxs websocket request from MempoolInfo to TrimmedTxInfo which broke the mempool page somewhat. I did not address that in this PR. I will open an issue or just pick it up separately.

Sync status page: Progress bar updates. Hard to test, but I checked it on a fresh sync.

Nexthome page:

  1. Mainnet statistics update with new block.
  2. Visual blocks update with mempool and new blocks.

Also fixed a bug in humanize.decimalParts where integers were not being displayed.

Raw transaction send/decode: Message decoding and broadcasting working as expected. Sacrificed a jQuery fade-in effect, though I could create an animation if needed or use one of many packages available through npm.

Keyboard navigation

  1. Hamburger menu
  2. Click out to close

Dark theme

  1. Sun icon changes
  2. Persistent on turbolinks visits

Don't forget to npm install.

@gozart1
Copy link
Member

gozart1 commented Jan 6, 2019

strip-js loads https://github.com/cheeriojs/cheerio, as a dependency, which is similar to jQuery.
between that and it's other dependency, sanitize-html, we're loading 110kb (minified size) for the xss guard.

All our xhr data comes from same origin at this point, so this seems too high a price in page weight to pay. But as security best practice we should still pass all the client side generated html through a xss guard.

https://github.com/cure53/DOMPurify comes in at 14.7 kb minified and is actively maintained, any reasons not to use that instead?

@buck54321
Copy link
Member Author

Ughh. I didn't see the dependency. DOMPurify was my first choice, but it's a little too aggressive in it's HTML validation. It stripped all the tr elements, presumably because they weren't nested in table and tbody elements in the snippets being validated. It seems to be undocumented and there was not configuration setting for it.

The Google Caja based scrubbers (sanitizer, gogle-caja) are also really large and really short on documentation for unexpected behavior I encountered.

I tried sanitize-html, but quickly discovered that every request would require a detailed whitelist of every element and attribute allowed, and then it's not clear whether those attributes that are whitelisted are being themselves scrubbed or not, though I'm sure those details could be figured out.

There is also xss which is tiny, but has very restrictive default settings, so would need customized whitelists for every request.

One last thought for now. We could use a really aggressive sanitizer and just filter inserted values instead of chunks of HTML. We could even strip out all HTML if it targeted at just the values. I played with this a little, but it gets pretty nasty in some places.

@buck54321
Copy link
Member Author

buck54321 commented Jan 6, 2019

I've got a little more on this. DOMPurify internally does something like this.

var dirty = '<tr><td>5</td></tr>'
var doc = document.implementation.createHTMLDocument("New Document")
var _doc = doc, body = doc.body // Not sure why
body.outerHTML = dirty
node = document.getElementsByTagName.call(doc, 'body')[0]
// some other stuff
console.log(node.innerHTML)

This will yield 5, I guess because freestanding tr elements are not valid. Instead of allowing dompurify to create nodes, we can create the elements ourselves and tell dompurify to sanitize it in-place.

var tbody = document.createElement('tbody')
tbody.innerHTML = '<tr><td>5</td></tr>'
dompurify.sanitize(tbody, {IN_PLACE: true})
return tbody.firstChild

Which also might yield some performance benefits (see cure53/DOMPurify#190 and cure53/DOMPurify#191).

@buck54321
Copy link
Member Author

Worked out the QR code animation. Used the new --purge-n-blocks flags to further test the sync status page progress bars through completion.

@chappjc
Copy link
Member

chappjc commented Jan 9, 2019

Great. I'm glad that's helping. I'm prepping a PR to complete the feature by rewinding sqlite too.

@gozart1
Copy link
Member

gozart1 commented Jan 11, 2019

Testing well, was not able to find any bugs that are not already on master.

Please also remove jquery from the externals declarations in our webpack config
https://github.com/decred/dcrdata/blob/master/webpack.common.js#L11

@gozart1 gozart1 merged commit 1996f02 into decred:master Jan 14, 2019
@chappjc chappjc added this to the 4.0 milestone Mar 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants