GoogleChrome / GoogleChrome/lighthouse

People detect Lighthouse to cheat its performance score

Open
#15,829 14 comments 5 reactions 2 assignees Claimed by @paulirish View on GitHub
P1.5
Dominant language
JavaScript
Stars
30.8k
Forks
9.8k
Avg merge
1d 20h
Merged PRs (30d)
19

Description

**Summary**

Hey! I work as a performance technical architect at Shopify. Lighthouse (PSI) has always been one of the go-to tools for our merchants when it comes to checking the performance of their stores. Unfortunately this ended up as an opportunity for some bad 3rd party actors to offer "speed optimisation services" that heavily strip down the page content when the Lighthouse test is detected. This generates a false image of the actual experience real users are getting, preventing store owners from even learning it's worth to improve.

**Most popular techniques**
Here are the most popular techniques that I found during the investigation:

1. Checking for the `Lighthouse` string in the user agent.
2. Checking for the `Linux x86_64` value of `navigator.platform`.
3. Checking for the `moto g power` string in the user agent.

After Lighthouse is detected, there are usually scripts in place that do a mix of the following:

- Append an LCP hack.
- Prevent all/3rd party JavaScript from loading.
- Prevent all/lazyloaded images from loading.
- Prevent all/lazyloaded iframes from loading.
- Stop parsing of the HTML using `document.close()`.

**Proposed solution**
While we're working internally to address this issue, we probably won't be able to find and fix all of the affected pages. The malicious JavaScript is usually heavily obfuscated so it's not always as simple as looking for one of the strings mentioned above. That's why I thought it would be good to fix the problem at its root instead.

When it comes to the UA, I can see it was already removed by @paulirish in this [PR](https://github.com/GoogleChrome/lighthouse/pull/14384). That said, it seems like PSI still appends the `Chrome-Lighthouse` string. The information still leaks through the `Sec-Ch-Ua` header as well through: https://github.com/GoogleChrome/lighthouse/blob/d2517556d5e4ebf371179705a5a1a0b3644d0c2c/core/lib/emulation.js#L32
My first proposal would be to remain consistent and remove those completely.

I think that the `navigator.platform` issue can be addressed by adding the following logic somewhere inside the emulate function:
```javascript
await session.sendCommand('Page.addScriptToEvaluateOnNewDocument', {
source: `Object.defineProperty(
navigator,
'platform',
{ value: '${formFactor === 'mobile' ? 'Android' : 'MacIntel'}' }
);`,
});
```
This should keep its value consistent with the rest of the user agent.

For the `moto g power` I don't think there are any elegant ways to address it. If someone wants to risk breaking the page for the actual users of this device then so be it.

Let me know what you think. I'm happy to prepare a PR with the changes mentioned above so we can make sure it's not so easy to cheat people with those shady practices in the future.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.