uBlockOrigin / uAssets

Resources for uBlock Origin, uMatrix: static filter lists, ready-to-use rulesets, etc.
GNU General Public License v3.0
3.55k stars 682 forks source link

ALL facebook.com issues #3367

Open GetGankNow opened 5 years ago

GetGankNow commented 5 years ago

URL(s) where the issue occurs

Facebook.com

Describe the issue

The Facebook sponsored ads is appearing again, i have tried all the solutions but nothing works

Versions

Settings

KiLL4FuNK commented 5 years ago

I see nothing Can it be adware?
you have to see what programs you installed any
check if you do not have some rare extensions

GetGankNow commented 5 years ago

No i don't have any adware or some adware extensions, the ads are from Facebook ( sponsored )

mapx- commented 5 years ago

While on a page with ads, right click on page, save as ..., you'll get a folder + html page, zip them together, upload the zip on some free server. Post here the link.

GetGankNow commented 5 years ago

Here the page with the sponsored ad: https://ufile.io/y827j

mapx- commented 5 years ago

@GetGankNow test this filter facebook.com##.userContentWrapper :has([id^="feed_subtitle_"]:has-text(Sp))

GetGankNow commented 5 years ago

@mapx- is blocking all post but allowing the comment section and reaction section.

mapx- commented 5 years ago

facebook.com###substream_1:has([id^="feed_subtitle_"]:has-text(Sp))

GetGankNow commented 5 years ago

@mapx- works bro, thanks a lot.

GetGankNow commented 5 years ago

Edit: some sponsored ads are appearing again.

mapx- commented 5 years ago

another example page ?

GetGankNow commented 5 years ago

The page that i save include all ads, i don't know how to save the page without the ads of this: facebook.com###substream_1:has([id^="feedsubtitle"]:has-text(Sp))

GetGankNow commented 5 years ago

facebook.zip Here the page again.

mapx- commented 5 years ago

test

facebook.com##[id^=hyperfeed_story_id_]:has(a[href*="client_token"])
facebook.com##[id^=hyperfeed_story_id_]:has(a[href*="utm_campaign"])
GetGankNow commented 5 years ago

@mapx- this 3 rules works. Thanks for all!!

ghajini commented 5 years ago

ads 'sponsored'

screenshot 41c

mapx- commented 5 years ago

test facebook.com##[id^=hyperfeed_story_id_]:has([id^=u_fetchstream_2_1]:has-text(SpSonSsoSredS)) or facebook.com##[id^=hyperfeed_story_id_]:has([id^=u_fetchstream_2_1]:has-text(Sp))

ghajini commented 5 years ago

not working bro screenshot 42

mapx- commented 5 years ago

weird, working for me (exactly using your test-case)

Did you test the same case you uploaded ? or something new ? could be "they" are using different approaches

shuhaowu commented 5 years ago

Doesn't work for me either. I had to use something like this:

facebook.com##[id^=hyperfeed_story_id_]:has([id^=feed_subtitle_]:has-text(SpSonSsoSredS))

However, with this filter active, FB seems to be refreshing the posts in an infinite loop.

filbo commented 5 years ago

From about 3mo to about 2wk ago, it was possible to catch Sponsored posts with :has-text(SpSonSsoSredS). This appeared only in Sponsored posts, with the 'S' elements hidden by CSS. (I'm not sure about back then, but now, the hiding CSS uses 'font-size:0', not 'display:none'.)

About 2wk ago, they started putting that stuff into all(*) posts. In Sponsored posts they use CSS to hide the 'S' elements. In 'normal' posts they use CSS to hide all of this. :has-text() is not aware of CSS hiding. The CSS used for this hiding is cryptographically hashed; so far it has remained stable for me, but another user has completely different classes, so the simple selector I use in my own filter won't work for anyone else. So we have to get into runtime evaluation of CSS computed styles :(

[(*)Not really 'all', but all normal posts by users, and many Sponsored posts, although some emitted by other modules inside FB don't use this particular trickery.]

It seems like uBO :matches-css() [see: https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters] might be able to handle this. Something like:

facebook.com##[id^=hyperfeed_story_id_]:if([id^=feed_subtitle_] span:has-text(^Sp$):matches-css(:not(display:none)))

-- which is COMPLETELY UNTESTED, just a pile of syntax smashed together by hand. Not sure if the nested uBO selectors are supported...

And all they need to do to break this is chop the word 'Sponsored' up differently; and it won't work for other UI languages. This is getting ugly.

kowith337 commented 5 years ago

Maybe need to view the deep of they DOM tag, e.g. looking in data-ajaxify, data-sigil, data-uri, data-ft, data-xt, ...

for example, I've found some part of sponsored URLs have is_sponsored=1 parameter, sometime it's boxed the parameter like [is_sponsored]=1

wtchangdm commented 5 years ago

Hi, I saw the comment in filters so I'd like report here: I am not sure if is region-related, but the following rule is killing my timeline (using https://www.facebook.com/?sk=h_chr). All of the posts are hidden now.

facebook.com##[id^=hyperfeed_story_id_]:has([id^=feed_subtitle_]:has-text(SpSonSsoSredS))

Thanks.

shuhaowu commented 5 years ago

This issue probably should be reopened, as more ads are using this new method to show up.

That said, I've identified the filter to block this ad:

facebook.com##[id^=hyperfeed_story_id_]:has([id*=feed_subtitle_]):if(a:if(span:has-text(/^Sp$/)):matches-css(display: inline))

Same thing as about but it might be better without too much regex:

facebook.com##[id^=hyperfeed_story_id_]:has([id*=feed_subtitle_]):if(a:if(span:has-text(SpSonSsoSredS)):matches-css(display: inline))

The basic idea is that the a element is showing up as display block if it is an ad and display inline if it is not an ad. This is how we positively identify the ads.

Additionally, id changed from ^feed_subtitle_ to ^_feed_subtitle_, so I'm matching with a *=

sigtus commented 5 years ago

I'm also having some publicty, but I have spanish as language so it says "Publicidad". Example: https://i.imgur.com/InXCyaM.png

filbo commented 5 years ago

@shuhaowu try this:

facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:if(div[id^="_feed_subtitle_"] > span:matches-css(display:none):has(abbr .timestampContent))

-- which is back to the 'hidden timestamp' trick, but using computed CSS. I think inline vs. block at the 'Sp' level is an accident, while the display:none ancestor span is 100% intentional. And blocking on hidden .timestampContent is completely UI-language-agnostic, while 'Sp' only works for English and a few other languages (e.g. would probably need to be 'Pu' for @sigtus's Spanish example above).

:has():if(span:has()) applies span:has() to all span elements inside hyperfeed_story_id; I'm trying to restrict the use of expensive JS computations to only spans inside feed_subtitle. And in fact only direct children of feed_subtitle, so this should be many times more efficient. (But I don't know how to actually test uBO filter performance in a situation like this, where the materials to be filtered are controlled by a site like FB which emits different stuff on every reload...)

okiehsch commented 5 years ago

I do not have a Facebook account, but I think we should leave one Facebook issue open. I doubt very much that Facebook will stop trying to push their ads, so this issue will never be "fixed".

shuhaowu commented 5 years ago

I think inline vs. block at the 'Sp' level is an accident

It's not at the "Sp" level. The <span>s inside the <a> are definitely the same across all posts. It's the <a> which is toggled depending on if the post is something we want to block or not.

I'm also not familiar with what timestampcontent is, but it sounds like something easily fixable on the their end. Detecting texts would be much harder to deal with.

Ideally, we would be able to strip out text that doesn't display in a function similar to has-text, although I guess that would be relatively expensive. The browsers should have this information already internally, as hinted by the fact that you can do things like Ctrl+F for Sponsored on the page and have it return sensible results.

I'm trying to restrict the use of expensive JS computations to only spans inside feed_subtitle

Shouldn't my filter execute only on the children of <a>s inside feed_subtitle as I've restricted it down to that? My filter is along the line of :has():if(a:if(span:has())).

filbo commented 5 years ago

The <span>s inside the <a> are definitely the same across all posts

Only when your FB UI language is English. If a workable UI-language-neutral expression can be written, that's better.

I'm also not familiar with what timestampcontent is, but it sounds like something easily fixable on the their end.

Yes of course whatever the ad blockers look for, they will further mutate. And of course it is all futile because people who are going to the trouble to block ads don't want ads and will not buy products offered by those ads. Yet they persist. As must we, putting up new blocks as the old ones fail.

the fact that you can do things like Ctrl+F for Sponsored on the page and have it return sensible results

Which browser? In Opera, and I assume this would be true for the whole Chromium family, searching for 'Sponsored' does not find those posts; searching for 'SpSonSsoSredS' highlights the visible word 'Sponsored'. Perhaps you are using Firefox and it actually does do integrative visibility checking on text searches. It seems unlikely, though -- those 'S' aren't even hidden with display:none, rather font-size:0. I'm not even sure it's well-defined which of those searches should succeed. When you see 'Sponsored' on such a post, in the fully resolved browser window, the actual string being displayed is 'SpSonSsoSredS'! Except the extra 'S's have font size 0.

Shouldn't my filter execute only on the children of s inside feed_subtitle as I've restricted it down to that?

You have [id^=hyperfeed_story_id_]:has([id*=feed_subtitle_]):if(a:if(...)) -- as I understand it, this checks whether hyperfeed_story_id has feed_subtitle; then, if so, it checks the subsequent :if() against hyperfeed_story_id again. To narrow the scope of the 2nd check you would need to apply it to the search item of your :has(), changing from:

[id^=hyperfeed_story_id_]:has([id*=feed_subtitle_]):if(a:if(...)) to [id^=hyperfeed_story_id_]:has([id*=feed_subtitle_]:if(a:if(...))) -- except that is not allowed, :has() can only search for valid expressions according to what the ongoing CSS4 working group has defined, so it would need to be: [id^=hyperfeed_story_id_]:if([id*=feed_subtitle_]:if(a:if(...)))

shuhaowu commented 5 years ago

Perhaps you are using Firefox and it actually does do integrative visibility checking on text searches. It seems unlikely, though

Hmm I must have done something wrong earlier, but I did just try this on FF and the text search doesn't work.

mapx- commented 5 years ago

@ghajini

working for me

facebook.com###substream_1:has([id^="feed_subtitle_"]:has-text(Sp))
facebook.com##[id^=hyperfeed_story_id_]:has(a[href*="gsuitebygoogle"])

However, the second one targets directly this specific ad

ghajini commented 5 years ago

I see too many ads like Amazon sponsored , Samsung sponsored etc

mapx- commented 5 years ago

Choose a part of the link to samsung, amazon and create filters like the above 1 for google suite (gsuitebygoogle)

and remember to provide feedback on the filters above

ghajini commented 5 years ago

Yeah, those 2 filters hided Google suite ad only, not others as I said previously

mapx- commented 5 years ago

ok, follow my advice with the other ads and if works post here your filters

filbo commented 5 years ago

@mapx-

facebook.com###substream_1:has([id^="feedsubtitle"]:has-text(Sp))

#substream_1 doesn't exist in FB pages I see; and this is a good thing, because :has([id^="feed_subtitle_"]:has-text(Sp)) would remove almost all posts. And it would remove at the anchor point #substream_1, so if that did exist I guess it would remove 100% of all posts, tearing them out at the root of the entire post stream.

mapx- commented 5 years ago

@filbo I tested with the page @ghajini uploaded and ... it worked for me. However I guess blocking single advertisers is the last way for the moment

filbo commented 5 years ago

This is a tested and working expression, with minor performance impact:

facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:if(div[id^="_feed_subtitle_"] > span:matches-css(display:none):has(abbr .timestampContent))

mapx- commented 5 years ago

Let's see what @okiehsch is thinking ( this issue will never be "fixed" )

okiehsch commented 5 years ago

I only meant to say that we should keep the issue open, you can obviously still add filters, I can‘t test I have no account.

kowith337 commented 5 years ago

Don't know these also works...

facebook.com##div[id^="hyperfeed_story_id"]:has(a[href*="[is_sponsored]=1"])
facebook.com##div[id^="hyperfeed_story_id"]:has(a[href*="is_sponsored=1"])

or

facebook.com##div[id^="hyperfeed_story_id"]:has(a[data-uri*="[is_sponsored]=1"])
facebook.com##div[id^="hyperfeed_story_id"]:has(a[data-uri*="is_sponsored=1"])
filbo commented 5 years ago

@mapx-

filbo I tested with the page @ghajini uploaded and ... it worked for me.

@ghajini posted two expressions. The first:

facebook.com###substream_1:has([id^="feed_subtitle_"]:has-text(Sp))

won't work, and would be harmful if it did. Fortunately it won't do anything.

The second:

facebook.com##[id^=hyperfeed_story_id_]:has(a[href*="gsuitebygoogle"])

is legit, but site-specific. (And would catch users talking about that site, if they included a live link to it, but that's a small danger.)

However I guess blocking single advertisers is the last way for the moment

It isn't. The expression I posted works on 80-90% of current FB ads by detecting the CSS trickery they're using to hide the timestamp on 'Sponsored' posts. The remainder are caught by filtering for a._5pcq[ajaxify*='ad_id='] within a post, probably facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:has(a._5pcq[ajaxify*='ad_id=']) in an uBO context.

a[href*="is_sponsored=1"] might catch a couple percent, but they would already be caught by the timestamp filter. Until FB breaks that in some new way, of course.

filbo commented 5 years ago

I wrote:

facebook.com###substream_1:has([id^="feed_subtitle_"]:has-text(Sp))

won't work, and would be harmful if it did. Fortunately it won't do anything.

Hmm, even worse. #substream_1 does exist on the main News Feed page (https://www.facebook.com/) -- but contains only 1, or possibly up to 5 posts. There is also a similar #substream_0, and then a bunch of #substream_0_5baxxxxxxxxxxxxxxxxxxxx divs each containing 5 posts. So that expression could potentially block up to 5 ads, if they happen to be pushed down in one of the two early post-streaming blocks.

#substream_1 does not exist on Timeline, Page, Group, or search-results post pages; nothing matching [id^=substream_] exists.

FB post filters should be keyed with:

facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:if(WHATEVER) (use has(WHATEVER) if WHATEVER is a standards-compliant CSS expression).

Robertof commented 5 years ago

facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:if(div[id^="_feed_subtitle_"] > span:matches-css(display:none):has(abbr .timestampContent))

I had to remove the underscore before _feed_subtitle as the IDs I see begin with just feed_subtitle:

filbo commented 5 years ago

@Robertof -- that was fixed by @mapx-, you should refresh your uBlock filters.

@mapx- -- the rules of :has() insist that both the left and right CSS must be CSS4-proposed-standards compliant. :matches-css(whatever):has(whatever) is invalid because :has() is applied to uBO pseudo-CSS.

By 'invalid' here I do not mean that it won't work. It does work right now. But the point of the distinction between :has() and :if() is that if uBO is someday running on a browser which natively supports :has(), it can allow that part of the CSS to be handled directly by the browser. Code which uses :if() is not expected to ever be browser-compatible and must always be interpreted by uBO.

Therefore, if this expression is still in the filter set at a time when uBO encounters a browser with native :has() support -- the expression will fail. It should be further revised to:

facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:if(div[id*="feed_subtitle_"] > span:matches-css(display:none):if(abbr .timestampContent))

The following MIGHT work (but I have not tested), and would likely be more efficient if it does:

facebook.com,facebookcorewwwi.onion##div[id^="hyperfeed_story_id_"]:if(div[id*="feed_subtitle_"] > span:has(abbr .timestampContent)):matches-css(display:none)

(should be more efficient because we're applying the expensive :matches-css() to fewer spans)

gwarser commented 5 years ago

:if is deprecated, I (or someone) need to update wiki - https://github.com/gorhill/uBlock/issues/3683

filbo commented 5 years ago

Thanks, @gwarser. So uBO now parses all :has() and internally boils them down to whatever's necessary, including (possibly) passing through to browser's :has() if that exists and the expression is going to be compatible?

filbo commented 5 years ago

(that seems like a net improvement -- future uBO behavior doesn't depend on rule authors following obscure rules, violation of which have no current negative effect... Deciding which :has() are browser-compatible only needs to be done once at the time the expression is first loaded, not each time at runtime...)

gwarser commented 5 years ago

Actually @gorhill I want to know this too.

filbo commented 5 years ago

I think currently it's more like 'uBO assumes (correctly) that no browser supports :has(), so it just handles it all itself. If/when browsers support it, and it seems worthwhile, future code can munge filter-supplied :has() instances down to internal uBO representation or leave simple CSS-standards-compliant :has() for the browser to interpret'

gorhill commented 5 years ago

All cosmetic filters are first validated to find out whether they are valid CSS selectors. If that fails, uBO then tries to parse them as procedural cosmetic filters. Whenever a browser starts to support :has, uBO will see them as valid CSS selectors and they will be used as such (assuming the content of :has(...) also pass as a valid CSS selector). This is all done at filter list-compile time.