-
Notifications
You must be signed in to change notification settings - Fork 2
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
NoScript domrect jitters #166
Comments
you had me at jittery ... I don't have NoScript anywhere, except Tor Browser, which I haven't really been doing any testing in for like six months. Do you notice this from your own observations (i.e you see domrect getting trashed on creepy) or is from results in the backend? Tell me more |
Oh, and was this seen in Tor Browser |
So far, only noticed it in Tor Browser starting in Feb or March (on both creepy and TZP). I haven't done a thorough analysis yet, but the same pattern is in JShelter on FF (they imported NoScript code). I observed it on the frontend and accepted it on backend (the results valid). |
OK, I'll make a note of that in the ticket |
Then how did you observe it. Do you mean both TZP and creepy's lie PoCs fail? |
also is it slider related - do you need to be on safer/standard |
I just tried in uptodate alpha and release (both ESR91 based) and it seems stable: I just loaded TZP and checked my line-height and dom rect vales, then did a reload .. etc etc etc - stable AF so far: identical in both. Will keep testing every now and then |
It occurs in both. I noticed today that it also affects css pixels. Text metrics and svg rect unaffected.
It's on both TZP and creepy, and passes math checks, but randomly fails known zoom level checks. This seems to suggest element styles are altered in some fashion. I'm seeing it on 3 windows machines. |
So I was thinking about this before when I was out walking, and the reason we don't pick up on lies is twofold
It would be nice to know WTF is actually changing - I would assume it is the x/y. I wonder if some of the other tests that are affected could be resolved with judicious use of Need to know more about what causes this, to be able to think about preventing it and/or detecting it current <body>
<!-- domrect -->
<div id="divrect" class="divrect1">
<div class="testRect" id="rect6"></div>
<div class="insideDOMRect">
<h1 class="testRect" id="rect0">content</h1>
<span class="testRect" id="rect1">content
</div>
<select class="testRect" id="rect3"><option>content</option></select>
<progress class="testRect" id="rect4"></progress>
<button class="testRect" id="rect5"></button>
</div> .divrect1 { /* SNAP to top left */
top: 0;
left: 0;
}
.divrect2 { /* SHIFT test */
top: 0.25px;
left: 0.25px;
}
#rect6 { /* KNOWN measure, start top left, FIXED */
top: 0;
left: 0;
width:100px;
height:100px;
transform: rotate(45deg);
padding: 0px;
position: fixed;
} |
I wonder if NS is doing something like this
@abrahamjuliot BTW, can you tell me how you know the dom rect result (or other items) are not correct on TZP |
As far as I know, NS is always correct math wise, but the hash changes at random. NS is only incorrect on creepy in failing my rigid known zoom tests. I'm currently retesting on TZP, and the jitters no longer occur (it's still an issue on creepy). |
this is getting confusing. sticking to one test, are we talking about domrect. Are we talking about the known measurements PoC (which is zoom resistant on gecko)? If so, why the zoom tests - did you mean on chromium? but more importantly .. how do you know it's failing? Which part is failing - the known PoC or the domrect test itself? yours sincerely
|
Yes, domrect. NS fails the known PoC (testing in gecko only) due to unknown results, but only on the creep main page. It's passing the domrect test page and TZP with no jitters. I think you are correct that layout positioning is altered by the extension in some fashion. |
OK, still confused. So the known PoC fails so you record the domrect test as trash. Question: are the domrect results also altered? So the way I see it, is it works exactly as intended. Except ... NS is not actually trying to mess directly with clientrect, so you/we need to harden it from being moved around in other words, you noticed it fail because TZP wrapped domrect in red lies colors (or for you trashed with a less sexy red than TZP's), but didn't expect it to fail. gotcha from your comment 16 days ago
But I haven't changed anything. So IDK ... TB updated with a new NS version (I think). If TZP failed in the past it can fail again. TZP uses set elements. For the known poc failing, I think we might just need to reapply the css rule(s) right before each test. div element style = blah ?? <body>
<!-- domrect -->
<div id="divrect" class="divrect1">
<div class="testRect" id="rect6"></div> // <- known poc (diamond) #rect6 {
top: 0;
left: 0;
width:100px;
height:100px;
transform: rotate(45deg);
padding: 0px;
position: fixed !important;
} |
Do you create the domrect elements on the fly? That might explain it a bit if NS has a listener? |
BTW, that bookmarket I posted is something people use (or similar in extensions I guess) to remove advs and shit that follow you down the page etc - this https://news.ycombinator.com/item?id=31625804 made me think of this NS jitter issue so we should harden regardless - a bit like how we reset the span style in fonts |
PPS: you could test your creepy jitter by debugging the known PoC style at the end |
It alters all domrect coordinates. CSS pixels are altered too (top-right and bottom left here), but not SVG elements.
I think that must be the issue. Debugging is difficult since it occurs only once every other minute after repeat refreshing. 😭 One thing I'm seeing is some results reoccur and can still pass the known value test. For example, here, both results pass and were previously seen a number of days ago (the 2nd is the expected result).
Nice. I need to try that. I use uBO sometimes to manipulate pages. Created this to ban annoying styles in emails. 😁 |
I just force plain text in all emails (and block external requests) |
I often buy books there .. clearly I need more time off |
In order to use clientrect with confidence in any section, I promise it as a prereq; Note: I will be doing away with the current domrect test which is a bit useless, and in future I will have a much bigger range of elements (especially widgets) - single pass, single method Line 336 in be88895
Line 382 in be88895
So isClientRect determines what I use and if it is untrustworthy - currently gecko only I updated https://arkenfox.github.io/TZP/tests/domrectspoof.html and was using this to see if there was some sort of blink standard, but have found weird results (and I don't mean how Element,getBoundingClientRect can differ from the others, and I don't mean changes in zoom. Admittedly, these weird results only seems to happen at very large zooms and only after scrolling I'll post more in a minute. Note I want to move away from the shift method if possible. With FF, I can already determine if the amount altered is the same per measurement (chameleon), or random (canvasblocker), but it may be that we need the shift method for blink |
here are some blink notes: using https://arkenfox.github.io/TZP/tests/domrectspoof.html index order = obj. // chrome: math PoCs?
// x === left
// y === top
// width == height
// right == bottom
/* examples
what's the correlation/proof here: aspect ratio, area
width+height/2 vs right+bottom/2
Element.getBoundingClientRect can be different to the others
scroll around a bit and hit F5 and you get inconsistencies: so far only on zoom 500
zoom 500
0+1: -20.710678100585938
2+3: -20.710678100585938 <-- 0-3 the same
4+5: 141.42137145996094
6+7: 120.710693359375
0+1: -20.710668563842773
2+3: -20.710668563842773 <- 0-3 the same
4+5: 141.42135620117188
6+7: 120.7106876373291
0+1: -20.710668563842773
2+3: -20.710668563842773 <- 0-3 the same
4: 141.42137145996094
5: 141.42135620117188 <- 4 + 5 different
6: 120.71068954467773
7: 120.7106876373291 <- 6+7 different
zoom 400
0+1: -20.710678100585938
2+3: -20.710678100585938 <- 0-3 the same
4+5: 141.42135620117188
6+7: 120.71067810058594
zoom 300
0+1: -20.710674285888672
2+3: -20.710683822631836 <- 0-3 not the same
4+5: 141.42135620117188
6: 120.7106819152832
7: 120.71067237854004 <-- 6+7 different |
so I thought some quick lie tests would be x === left, y === top, and even the first four must match, but that's not always true: x and y can differ, there's even cases where width + height + right + bottom all differ - and besides, if the extension is adding the same amount of noise, the test would pass what exactly are you using in creepy? @abrahamjuliot if I remember rightly it;s width - left = top - height or whatever ? |
The shift method works on Bromite and Ungoogled Chromium, but I think only because they apply a fresh scale factor on every DOM reflow. There are some customized blink engine software that manage to bypass it. I use lied = (
right - left !== width ||
bottom - top !== height ||
right - x !== width ||
bottom - y !== height
) I noticed if I apply a custom matrix transform and run it in the console on some random heavily styled site, the dimension equality is not the same and needs to be refactored. Page styles or injected styles can sometimes leak into the elements and affect positioning. This can be prevented if we use an iframe for measuring elements or reset the styles. But, random styles injected from extensions can still impact the iframe. |
OK, so that's the same pair of tests and covering x == left and y == top, which always seems to be the case (I tidied up my examples - 0+1 are always the same, 2+3 are always the same) same result lied = (
x !== left ||
y !== top ||
right - x !== width ||
bottom - y !== height
) |
So, you can load the test in chrome, zoom up to 500, resize the window, as you get smaller enough, move the scrollbars and continue resizing, etc, then zoom down one, repeat, then zoom down one, repeat Then in the console you can type
That's 35 known results on windows with preset zoom levels and dpi = 1, devicepixelratio = 1, systemscaling = 1 I suspect that there are many more combos |
the one false positive testBlink()
So the shift method was the first method I came up with, but if an extension like chameleon shifts everything by the same amount, then this test fails, which is why I came up with the known measurement PoC So I have to ask, does this method (4 x lies check) detect those that shift everything by the same amount. and the answer is I am too tired to think about it right now - i.e the shift method is not required IMO, ever (off the top of my head) |
I got 2d2f0e42 too.
No, but if we use a matrix to Warp and Skew the rectangle, and then adjust the expected calculations accordingly, shifting by the same amount can still fail. I'm not fully understanding why it fails. /* style */
#rect1.matrix {
transform: matrix(1.11, 2.0001, -1.0001, 1.009, 150, 94.4);
} lied = !(
(matrixRight - matrixLeft) == matrixWidth && (matrixRight - matrixX) == matrixWidth &&
(matrixBottom - matrixTop) == matrixHeight && (matrixBottom - matrixY) == matrixHeight
) I like the known measurements PoC the best. |
not sure what you mean - are you saying that our false positive passes the matrix test, or that it still fails? So two options
refresher lied = (
x !== left ||
y !== top ||
right - x !== width ||
bottom - y !== height
) now that depends entirely on the extension. The first two lies will never trigger if legit, and I would suspect an extension would never trigger these either (if they did then that's even better). I honestly can't see any decent extension not triggering at least two lies (but it is possible) IDK how prevalent this "jitter" (ignoring NoScript) is, but perhaps you could start collecting a lieCount, or even better a lieMatrix so we know which ones are being affected |
We could also collect something like pageOffsetX,Y ? - e.g. if the page is offset and liecount is only 1 and it's item 3 then false positive - BUT it;s still untrustworthy ? IDK |
I like this idea. I am less inclined to rely on it, but it can be used to detect lies by comparing to CSS pixels. For example, if domrect is unstable by zoom, css pixels should be too, and everywhere a known css pixel fingerprint appears, it should have a known domrect paired with it.
Zoom settings and CSS transform scale should pass the matrix test since the engine calculates the dimensions, but if an offset is added to each dimension, this can fail the matrix test. |
It depends what is unstable. If it's x/y then we don't really use those in measurements - it's mostly width/height. I'm actually collecting the full diffs for FF and can categorize two anti-FP fingerprints - scope (what measurements: x, y, etc) and noise ( same chameleon style or different CB style - because we know the correct measurement - can't always do that in blink AFAICT)
grr. imma explain again :) so we have a false positive (with a single lie out of the four), does it pass the matrix test? I seriously need a break from this. Matrix test is not the same as shift test (which I want to ignore since it would be bypassed by eg chameleon style spoofing), right? don't answer, I will just do some tests. There's a key here to eliminate those false positives, but I guess the question is do we want to, they're not stable (or are they? - so many factors not tested: dpi, device pixel ratio etc) |
https://arkenfox.github.io/TZP/tests/domrectspoofratio.html - not needed for FF of course - zoom in and out etc to auto rerun (a history is kept) So this focuses only on width/height: but relies on known results let knownBlink = [
// standard
0.5, 0.4999999427781113, 0.5000000572218888,
// when page is scrolled so no longer top left = 0
0.4999999427781178,
0.4999998855562356,
] Given all it takes is either width or height to change by .000000000000001 or whatever, and there are too many factors (dpi, devicePixelRatio, zooming, the page not being top left (i.e scrolled), and numerous OSes not tested), then I think this wee test I whipped up is a bit naff, except that it lessened the variables. But also, that it only checks width/height - still, if they're fucked with the rest is suspect as well TBH, and width/height are usually the only values we use in metrics (although maybe left is useful in some metrics) Still, was an enjoyable 15 mins :) |
It works perfectly on my android !! maybe I'm onto something? |
@abrahamjuliot is this still an issue for you? PS: when I eventually upload my refactoring, TZP will only run on gecko, plus I've never seen this issue on TZP (unless I'm reproducing it by moving the content page when zoomed in those PoCs, and even then only on blink) also, NoScript no longer shows any proto/proxy lies - I thought it used to : it also no longer shows |
I'm seeing a minimal number of jitters affecting all element signals (rects, fonts, and svg), but it seems limited to the initial load on browser start up and does not affect TZP. I did just notice, with NoScript on or off, the glyphs fingerprints on TZP appear random per execution.
Nice. It looks clean now. |
every run I'm adding an extra tofu Line 1307 in 42b20f1
good catch 👍 |
actually, what I'm doing is essentially this let fntCodeUsed = fntCode // fntCode: master global var for lookup array of 42 codes, no '0xFFFF'
filter_tofu() // skipped if TB or android otherwise, removes tofu codes
fntCodeUsed.push('0xFFFF') // ensure one tofu but here's what happens (TB or android)
anyway, I'll patch it to only set fntCodeUsed once, and I'll replace that with fntCode.forEach(function(code) {fntCodeUsed.push(code)}) |
superior TZP coding bro ... what can I say 🤣 is this affecting all engines on creepy or just blink? |
#4 (comment) - here's what it was - those |
actually, it's quite different now. The items after "Performance" in iframe window properties when the slider is on safer includes 10 more properties after the index position of "Performance" : caused by NoScript (which integrates with the slider) + any code patches by TB themselves let aTampered = aProps.slice(aProps.indexOf("Performance")+1)
let lastItem = aProps[aProps.length - 1]
let aFilter = ['Event','Location'] // normal FF or TB-standard
if (isTB && lastItem == "Proxy") { // TB-safer
aFilter = ["Element","Event","HTMLCanvasElement","HTMLElement","HTMLFrameElement",
"HTMLIFrameElement","HTMLObjectElement","MediaSource","Proxy","URL","webkitURL",
]
} |
This reminds me, have you noticed NoScript affects dom rect results for a few months now. It's somewhat jittery and then stable after a few reloads. I'm not sure, but it seems to be a result of appending elements, but only the dom rect is affected.
Originally posted by @abrahamjuliot in https://github.com/arkenfox/TZP/issues/34#issuecomment-1132495699
The text was updated successfully, but these errors were encountered: