3

Is it possible to easily detect DOM manipulation by the user?

When a user uses the console in any modern browser, he/she can manipulate the DOM in ways the developer did not intend.

I have a web app that is very much tied to the DOM being in certain states and should the user do anything to the DOM via a console, I'd like to be notified.

The answer:

  1. Doesn't need to be browser agnostic
  2. Doesn't need to be perfect. I fully understand that most, if not all, methods could be circumvented, but I'd like a good general solution.
  3. Can't be too convoluted. I'm not interested in registering an event handler with all DOM events that checks some flag set when my code performs an DOM manipulation

Edit:

There appears to be some confusion in the answers I've received thus far. As pointed out in #2 above, I understand that most, if not all, methods can be circumvented.

In addition, this is an internal tool and thus is protect by a VPN. Further more, there is server-side checking. However, there are reasons, which I cannot elaborate upon, for me wanting to know when a user (who are few in number) manipulated the DOM.

To be clear, this isn't for security reasons. I'm not trying to stop malicious users here. Think of this more as out of curiosity.

Avi
  • 1,231
  • 10
  • 23
  • 1
    What's wrong with the user manipulating the DOM? Your app shouldn't do anything sensitive (such as handling authentication) client-side. If the app is "tied to the DOM being in certain states", and the user changes the DOM, they can't complain when the app stops working. – Xenon Nov 24 '12 at 00:00
  • "DOM Mutation Events" might be the keyword: https://developer.mozilla.org/en-US/docs/DOM/Mutation_events – Samuli Hakoniemi Nov 24 '12 at 00:00
  • http://stackoverflow.com/questions/2844565/is-there-a-jquery-dom-change-listener – Sidharth Mudgal Nov 24 '12 at 00:01
  • 2
    You can not trust the client, server needs to validate everything submitted to it. The user does not even need to use your webpage to alter it, they can submit requests with command lines. :) – epascarello Nov 24 '12 at 00:01

6 Answers6

6

Don't do that. Code your web site to not trust user input and then don't care what the user does. If invalid input is submitted then reject it. Everyone is happy.

It's easy to think that you own the user's browser. You don't. It's serving you but only at the whim of the user.

If you really must know when the DOM is modified--and this seems a really fragile design--then just do what amounts to calculating checksums. After each legitimate step of the site's approved function, traverse the DOM elements you care about and record their positions, values, or whatever you are concerned with. At intervals, validation time, or a next UI interaction, compare. This is the only comprehensive, cross-browser (including old browsers) way to detect DOM changes. Modern browsers offer DOM mutation events (see Tim Down's answer for more detail) but have limited support and will apparently be replaced with yet another new thing, anyway.

Ultimately, nothing you do can stop someone determined to defeat your scheme. If anything, the user can copy the browser's POST request using Firebug, tweak it, and write a tiny program to submit his own malicious POST request. It is more important to protect your server from malicious input than it is to make your web page supposedly bullet-proof (because it won't be).

ErikE
  • 48,881
  • 23
  • 151
  • 196
4

DOM mutation events work in current versions of all major browsers and do what you want. The following will cover common DOM modifications within the whole document:

function handleDomChange(evt) {
    console.log("DOM changed via event of type " + evt.type);
}

document.addEventListener("DOMNodeInserted", handleDomChange, false);
document.addEventListener("DOMNodeRemoved", handleDomChange, false);
document.addEventListener("DOMCharacterDataModified", handleDomChange, false);

DOM mutation events will eventually be replaced by mutation observers, which are implemented in recent Mozilla and WebKit browsers.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • This is interesting but what about property changes such as changing css? – ErikE Nov 24 '12 at 07:36
  • @ErikE: There are no CSS mutation events that I'm aware of and a quick search didn't turn up much. You could use the `DOMAttrModified` to monitor changes to `style` attributes (although I'm not sure what browser support for that particular event is like), but otherwise you may have to resort to polling existing style rules via `document.stylesheets`. – Tim Down Nov 24 '12 at 11:53
2

Relying on a script to prevent or counteract malicious edits to the DOM is not the right approach. What exactly are you doing that depends on the DOM not being touched? Seems like that's a huge red flag in and of itself.

jcolicchio
  • 796
  • 5
  • 11
  • 1
    Hello, welcome to Stack Overflow. Requests for clarification are typically posted as comments, not as answers. However, I agree with you that this isn't the right approach, so I suggest you [edit] your answer to remove the question and focus instead on why this is wrong, and what alternatives there are. This will ensure your answer meets the guidelines in the [faq] and stands as a full answer. Good luck! :) – jamesmortensen Nov 24 '12 at 00:12
  • "that's a huge red flag in and of itself" - definitely wise. If there was any reason you didn't want the user to have the authority or ability to alter the DOM, your application really shouldn't be running in the browser. – netpoetica Nov 24 '12 at 00:48
1

This is a pretty interesting question, and I think DOM mutation events may be a best solution. One thing I was initially thinking I might do is run a timed function that checks the DOM for specific modules, based on data- attributes or IDs. If I was building my page entirely client-side through JS, I would have a build configuration object for each module (DOM element like:

<div id='weather-widget' data-module-type='widget'>
    <h1 data-module-name='weather'>Weather</h1>
    <!-- etc etc -->
</div>

Anyhow, my config object would contain all of these things like module type, module name, etc, etc:

//Widget configuration object
var weatherWidgetConfig = {
    type: 'widget',
    name: 'weather'
}

and I would inspect the DOM element and all of its children to make sure the data- attributes still matched the configuration object, that they existed, and that they have not been changed. If they have, I would call a module.destroy() and module.build() again with the correct configuration.

netpoetica
  • 3,375
  • 4
  • 27
  • 37
1

I've received a lot of answers in which the respondent delivers advice about how to build a web app. While that may be useful to some readers, that isn't answering the question. Some, however, have attempted to answer. The closest I seen to a complete answer was given by @Keith. The only problem is that it fails the 'easy' test.

It appears that the correct answer, as some have said, is NO - it isn't possible to easily detect DOM manipulation by a user.

Avi
  • 1,231
  • 10
  • 23
0

I recently discovered "Selector Listener", a technique that relies on css to detect DOM changes. It doesn't work in IE 9-. Applying it to the whole DOM doesn't sound like a good idea, the intent is rather to work with specific selectors.

More details can be found in this blog post.

Christophe
  • 27,383
  • 28
  • 97
  • 140