sentry-javascript: uBlock Origin blocks requests to sentry.io

Package + Version

  • @sentry/browser
  • @sentry/node
  • raven-js
  • raven-node (raven for node)
  • other:

Version:

5.23.0

Description

The uBlock Origin (probably most popular adblocking extension, installed by default on Raspberry PI Chromium) recently added sentry.io to it’s uBlock filters - privacy list on 28/08/2020.

As a result, Sentry events are not being sent to server.

Log from from Chrome DevTools console:

https://xxx.ingest.sentry.io/api/xxx/store/?sentry_key=xxx&sentry_version=7
net::ERR_BLOCKED_BY_CLIENT

The sentry.io entry might have been added to the list as a result of grofers.com (mis)using it to track user behaviour, unfortunately affecting web apps on all domains.

Reference to commit: https://github.com/uBlockOrigin/uAssets/commit/6489ab5eaf2a838bcdf2ae74ec8542ebb897d16d

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 3
  • Comments: 38 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Really annoying. Error trackers should never be blocked.

Does anyone know if there’s a way, using the Sentry JS SDK, to attempt to ping sentry.io, and catch an exception if it fails? So we could do something like:

try {
  Sentry.pingTheServer();
} catch (e) {
  // alert user to please disable any privacy blockers
}

if you are using netlify, it is really easy to make the tunnel using their _redirects proxy feature https://docs.netlify.com/routing/redirects/rewrites-proxies/

you will need to extract XXX YYY and ZZZ from your dsn https://XXX@YYY.ingest.sentry.io/ZZZ

_redirects (or you could use the netlify.toml format see link above for difference)

/unblocksentry      https://XXX@YYY.ingest.sentry.io/api/ZZZ/envelope/ 200

and in sentry add the tunnel you used (i used unblocksentry)

client-app.js

Sentry.init({
  dsn: 'https://XXX@YYY.ingest.sentry.io/ZZZ',
  tunnel: '/unblocksentry'
});

caveat : it may be possible that a malicious person could send /unblocksentry some garbage data and netlify will pass it over to your sentry ingest point. however, i’m not sure this is a concern - and moreover, what stops someone from doing that directly given the DSN is published/deployed anyway.

ps, kudos to @benswinburne for posting his solution too. there is a similar deployed proxy solution here as well https://github.com/getsentry/examples/blob/master/tunneling/nextjs/pages/api/tunnel.js

Oh no, not again

Proxying is just extra work for something that shouldn’t even happen in the first place.

Yep, you can sort of record user information with the reports - what doesn’t mean you’re really able to track the user down, or cookie them. And then, why not blocking the whole internet, since you can store any information about your users on, surprise surprise, your database as well? Why not block any AWS call, since AWS has databases which potentially could be used to store user information?

As stated in the uBlock issue, Sentry is open about what they do with the user information and move the responsibility about user data to the end developer - and thus, again, no reasons to block Sentry directly.

This is not a decent reason for blocking an error reporting tool which is invaluable for developers. They should at least explain clearly why they think those tools should go, and what to use instead. I asked exactly that on my new issue - https://github.com/easylist/easylist/issues/15806

2023 and Sentry is still blocked by uBlock Origin. I’m going to open yet-another-issue at easylist, but their current issue template states that

If a site implements any tracking or monitoring, UA/IP/Geo checks, browser detection, analytics, telemetry, linking to third-partys, pixels, referrers, fingerprinting, event/perf logging etc. Regardless how helpful or needed the script(s) are, it will be blocked in Easyprivacy. Privacy comes first and the block on these scripts will remain in place.

Effectively, for them, bug reporting == lack of privacy. Awesomely stupid developers 🤦‍♂️ All forms of extremism are wrong.

I guess the only way indeed is to tunnel the project out, when it’s possible.

OK. I tested it and it works.

In case anyone needs it… My Sentry Laravel Tunnel:
(environment and/or url check still needs to be implemented)

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class SentryTunnelController extends Controller
{
    /**
     * Handle the incoming request.
     */
    public function __invoke(Request $request)
    {
        $envelope = $request->getContent();
        $headers = array_map(
            fn ($line) => json_decode($line, true),
            preg_split('/\r\n|\r|\n/', $envelope)
        )[0];

        if (empty($headers['dsn']) || $headers['dsn'] != config('sentry.dsn')) {
            return response()->json(null, 401);
        }

        $parsed = parse_url(config('sentry.dsn'));
        $url = sprintf(
            'https://%s.ingest.sentry.io/api/%d/envelope/',
            explode('.', $parsed['host'])[0],
            last(explode('/', $parsed['path']))
        );

        $response = Http::withBody($envelope, 'application/x-sentry-envelope')->post($url);

        return response()->json($response->json(), $response->status());
    }
}

As of today, Sentry is still blocked by uBlock 🤦‍♂️

Hot take: The people who maintain EasyList are the same people who always vote to close questions on StackOverflow. 😏

For anyone trying to work around this, I am now successfully using AWS CloudFront and Lambda@Edge to tunnel the requests though the same domain. This is pretty straight forward in hindsight, but getting everything working took a bit more work than expected.

Hopefully sharing my setup can save people some time: https://gist.github.com/razor-x/44c1c572a8c9e4cb723b1945a4d75bdb

I don’t have the time right now to open a PR, but if anyone wants to take this work and incorporate it into the examples, go for it!

@Muetze42 Just make sure you use the tunnel option to the Sentry client library and forward the correct headers, then all should work!

The best thing will probably be to simply send the JavaScript errors to a separate API and then pass the error on to Sentry server-side. Is there a walkthrough for this?

I noted one way to do this above (See: https://rawdatum.com/posts/8th-piece/). This has been working great for me.

Everyone replying “still blocked” here as if the adblock lists are part of this repo. You are barking at the wrong tree, ya’ll.

Wanna make noise? Do it at the maintainers of the adblock lists: https://github.com/easylist/easylist/issues https://github.com/uBlockOrigin/uAssets/issues (They’ll probably still say no though. 🤷‍♂️)

And a reminder you can bypass it with the “tunnel” feature, if you host your own endpoint (at least until you are a big company and then the filter people block your domain. 😛) – Anyway, scroll up in the replies for a few implementation suggestions.

@igorsantos07 - given that you can record whatever you like with sentry, i don’t think they are wrong to block it. that said, just add your own proxy and it works just fine.

https://github.com/getsentry/sentry-javascript/issues/2916#issuecomment-1036564861

@ffxsam I got the tunnel working with a simple configuration to my CloudFront using CF functions!

Just use a CloudFront function like this and attach it to your Viewer Request. Works like a charm – not blocked!

function handler(event) {
  var request = event.request;
  var projectId = '123455';

  request.uri = `/api/${projectId}/envelope/`;

  return request;
}

I have gotten around this using Cloudfront as a reverse proxy for Sentry which allows me to use a custom DSN with my own domain name as opposed to using the tunnel option which uses the same domain as the application.

Below is a basic Cloudformation template to get it working. You’ll need to create an ACM certificate and the Route53 record manually (or add them to this template)

---
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Parameters:
  SentryIngestURL:
    Type: String
    Default: xxxxxxxx.ingest.sentry.io
    Description: Enter the ingest hostname for Sentry.
  ReverseProxyDomain:
    Type: String
    Default: sentry.yourdomain.com
    Description: Enter the hostname which will be proxied to Sentry ingest.
  AcmCertificateArn:
    Type: String
    Default: arn:aws:acm:us-east-1:xxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    Description: Certificate ARN for the Cloudfront Distribution

Resources:
  CloudFrontDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        Aliases:
          - !Ref ReverseProxyDomain
        Origins:
          - ConnectionAttempts: 3
            ConnectionTimeout: 10
            CustomOriginConfig:
              HTTPPort: 80
              HTTPSPort: 443
              OriginKeepaliveTimeout: 5
              OriginProtocolPolicy: "https-only"
              OriginReadTimeout: 30
              OriginSSLProtocols:
                - "TLSv1.2"
            DomainName: !Ref SentryIngestURL
            Id: !Ref SentryIngestURL
            OriginPath: ""
        OriginGroups:
          Quantity: 0
        DefaultCacheBehavior:
          AllowedMethods:
            - "HEAD"
            - "DELETE"
            - "POST"
            - "GET"
            - "OPTIONS"
            - "PUT"
            - "PATCH"
          CachedMethods:
            - "HEAD"
            - "GET"
          Compress: false
          CachePolicyId:
            Ref: CloudFrontCachePolicy
          OriginRequestPolicyId:
            Ref: CloudFrontOriginRequestPolicy
          SmoothStreaming: false
          TargetOriginId:
            Ref: SentryIngestURL
          ViewerProtocolPolicy: "https-only"
        Comment: |
          Reverse proxy for calls to Sentry through a first party TLD.

        PriceClass: "PriceClass_100"
        Enabled: true
        ViewerCertificate:
          AcmCertificateArn: !Ref AcmCertificateArn
          MinimumProtocolVersion: "TLSv1.2_2021"
          SslSupportMethod: "sni-only"
        Restrictions:
          GeoRestriction:
            RestrictionType: "none"
        HttpVersion: "http2"
        DefaultRootObject: ""
        IPV6Enabled: true

  CloudFrontCachePolicy:
    Type: "AWS::CloudFront::CachePolicy"
    Properties:
      CachePolicyConfig:
        Name: !Sub ${AWS::StackName}-CachePolicy
        Comment: ""
        DefaultTTL: 0
        MaxTTL: 1
        MinTTL: 0
        ParametersInCacheKeyAndForwardedToOrigin:
          EnableAcceptEncodingGzip: false
          EnableAcceptEncodingBrotli: false
          HeadersConfig:
            HeaderBehavior: "whitelist"
            Headers:
              - "Origin"
              - "Authorization"
              - "X-Sentry-Auth"
              - "X-Sentry-Token"
          CookiesConfig:
            CookieBehavior: "none"
          QueryStringsConfig:
            QueryStringBehavior: "all"

  CloudFrontOriginRequestPolicy:
    Type: "AWS::CloudFront::OriginRequestPolicy"
    Properties:
      OriginRequestPolicyConfig:
        Name: !Sub ${AWS::StackName}-OriginRequestPolicy
        Comment: ""
        HeadersConfig:
          HeaderBehavior: "whitelist"
          Headers:
            - "Origin"
            - "Access-Control-Request-Method"
            - "Access-Control-Request-Headers"
            - "Referer"
            - "X-Sentry-Token"
            - "X-Sentry-Auth"
        CookiesConfig:
          CookieBehavior: "none"
        QueryStringsConfig:
          QueryStringBehavior: "all"

IIRC Cloudformation must use certificates in us-east-1 (might be wrong) but as a result, deploy the template in us-east-1.

          aws cloudformation deploy \
            --region us-east-1 \
            --template-file stack.yml \
            --stack-name SentryReverseProxy

Then you can set up the client like so

Sentry.init({
  dsn: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@sentry.yourdomain.com/xxxxxxx',
});

@hyperknot Can confirm, that sentry is not working for me with ublock installed as today.

Now Easyprivacy is doing it, I’ve opened an issue here: https://github.com/easylist/easylist/issues/6963

This seems to be resolved by https://github.com/uBlockOrigin/uAssets/commit/9ab563e5fb6c2c8be78aa1ac47e429e057a0ead0, at least for now.

Thank you for everyone involved.