Can a Website Know If I am Running a Userscript

Can a website know if I am running a userscript?

Yes, in theory, a site can deduce the presence of scripts in various situations.

This is not foolproof and usually is way too much trouble for the negligible "threat" to the site. (Then again, some webmasters can be obsessive-paranoids about such things. ;) )

Some methods, depending on what the script does (in no particular order):

  1. Gaming or auction sites can monitor the timing (speed and regularity) of "bid" clicks.

  2. A site can AJAX-back the count of say, <script> nodes, looking for extras.

  3. Similarly, a site can AJAX-back any or all of the content of a page and compare that to expected values.

  4. Extra AJAX calls, or AJAX calls that don't meet hidden requirements can be noted (and allowed to appear to succeed).

  5. If the script uses unsafeWindow in just the right (wrong) way, a page can detect that and even hijack (slightly) elevated privileges.

  6. "Clicks" that were not preceded by mouseover events can be detected. I've actually seen this used in the wild.

  7. A page's javascript can often detect script-generated clicks (etc.) as being different than user generated ones. (Thanks, c69, for the reminder.)

Ultimately, the advantage is to the userscript writer, however. Any counter-measures that a webpage takes can be detected and thwarted on the user end. Even custom, required plugins or required hardware dongles can be subverted by skilled and motivated users.

Can a webpage detect a tampermonkey userscript?

Browsers and Greasemonkey/Tampermonkey/Violentmonkey have (mostly) improved how they do injection, scoping, and sand-boxing. Userscripts are not injected using ordinary <script> tags (although your script may need to create such tags in some occasions).

In fact, there's almost no need to use an IIFE nowadays.

But, in addition to the detection methods in the previously linked question:

  1. In @grant none mode, if you @require a library that copies itself to window scope, the page can see it. Most libraries do not do that, but one that does is jQuery.
  2. Tampermonkey actually provides the installed script version to sites that are whitelisted in the advanced settings. This is mainly for script hosts like greasyfork.org.
  3. I don't know if a page can detect WebSockets in use by a userscript. I doubt it.

Bottom line, is for a "read only" userscript, that does not require global libraries in @grant none mode, the page cannot detect it.
(Unless the page is greasyfork.org, etc., and you have the Allow communication with cooperate pages setting at the default value.)

If you discover some leak whereby a page can detect a "passive" script, let us know and chances are it can get plugged.

Can websites detect use of simple Tampermonkey scripts?

tl;dr - no

The browser, nor the Tampermonkey plugin do not advertise the presence of userscripts. That is there isn't a straightforward way to just write if(tampermonkeyActive) and detect it.

However, webpage may implement anti-tampering techniques. These may not be directed at Tampermonkey, but any type of suspicious behaviour. This may include:

  • Suspicious amount of activity per unit of time per user
  • Activity when the webpage is not in focus
  • Unexpected global variables or function calls
  • Checking isTrusted on events.

Of all these, I have only experienced the first example, that is logging activity server-side and manually reviewing it. Thus if you're trying to automate something and the site owner is not keen on it, you should consider making it look human-like.

Security

Tampermonkey script already runs in wrapped scope, so the self-invoking function is redundant.

Detecting a userscript can be something a malicious actor might want to do. If you use @grant to get any of the special features of tampermonkey, and also use @grant unsafeWindow, leaking any of the functions could allow actor that detects that to hack your browser. It would take a lot of effort though - they need to detect the userscript, then manually hack it, since every userscript is different.

How can I prevent a webpage from detecting I am running a script?

For Firefox and Chrome there is no magic bullet to prevent detection, it is a process and an art...

The 3 principle ways that a site would detect a script are:

  1. Out of sequence or too-frequent AJAX requests.

  2. Changes to the page's code (HTML, global JS, or even CSS).

  3. Unnatural mouse or keyboard action.

See "Can a website know if I am running a userscript?" for more information.

Some countermeasures:

  1. For AJAX requests that your script makes:

    1. Use Wireshark, or similar, to analyze the traffic of normal AJAX calls. Make sure that you send the same type of calls, in the same order.
    2. Make sure that your requests show the same headers and data as the page's.
    3. Do not send AJAX requests faster than the page does normally or faster than a user could reasonably trigger.
    4. Consider adding random delays to your script's requests, so that they are not uniformly timed.
    5. Beware of constantly changing fields in the page's requests. Be sure that you know how to generate the correct value; don't just cut and paste.

  2. For changes that you make to the page's code:

    The page can handle these either entirely locally, with it's own javascript, or it can also send back status or code fragments to the server.

    1. Block and replace the page's javascript. Tools like NoScript, RequestPolicy, firewalls and proxies can be used to block the JS.

      Then use Greasemonkey to add your edited version of the page's JS. Greasemonkey will run even if all of a page's JS is disabled.

    2. If the page phones status home, and that status changes in response to your script's changes, Intercept and replace those messages. (This is not needed if you used the previous method.) You will need a custom firewall, proxy, or router to do this.

  3. For events that you trigger (mouse clicks, filling out fields, etc.):

    1. If the page checks for this, give it what it looks for. For example, instead of a click event, you may need a mouseover, mousedown, mouseup, mouseout sequence.
    2. If that is not enough, then the countermeasures are the same as for changes made to the page's code (replace JS, intercept status messages).

Important!
In the rare event that you are battling a site that tries to thwart userscripts, it is like a war. The webmaster can adapt to what you are doing, and the environment can constantly change. So scripting for such a site is an ongoing process.

JavaScript - Can a website see userscript generated errors/console logs?

A website can check their DOM to see if the page has been modified in ways that are not done by their own code. So, if a userscript was modifying the page in some way, a website could potentially detect that modification (they'd have to be looking for it).

A website can replace console.log() with their own function that captures any output sent to it (this would be actual console.log() statements in your code, not other messages the system puts in the console (such as uncaught exceptions).

Can I get a userscript's version and use it on another webpage?

Yes, you can show userscript data on a webpage provided that either the webpage, or your hosting server, can see and GET the script (possibly cross-domain).

But <script src="Scripts/scriptName.user.js"> won't work, because:

  1. It reads in and runs the script as vanilla javascript. There's no way for you to read the source code or the comments where the script's metadata lurks.
  2. Many script hosts, like GitHub, won't serve the file to a <script> tag at all (CORS blocked). Or, some do, but send the wrong mime type.
  3. Tampermonkey can't fire for <script> nodes, and it would be a major security disaster if it could.
  4. So obviously, GM_info will not be available.
  5. In fact, if the script uses any Tampermonkey native functions it will crash even if it loads. Note that this doesn't mean the metadata. That's harmless by itself.
  6. Ditto if @require or @resource assets are needed. (And not independently loaded by the page.)


You must read in the userscript as text, and then parse the string for the version info.

For example, for this userscript:

// ==UserScript==
// @name StackExchange, Add kbd, sup, and sub shortcuts
...
// @version 4.2
...

The following code will get the version:

$.get ("https://cdn.jsdelivr.net/gh/BrockA/SE-misc/Add_kbd_sup_sub_shortcuts.user.js", scrptTxt => {    var versionMtch = scrptTxt.match (/\/\/\s+@version\s+([0-9.]+)/i);    if (versionMtch  &&  versionMtch.length > 1) {        console.log ("The script is version: ", versionMtch[1]);    }    else {        console.log ("Version metadata not found.");    }} );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


Related Topics



Leave a reply



Submit