What domains/protocols in the img-src
directive of the Content-Security-Policy header are required to allow Google AdWords conversion tracking?
From testing, when we call google_trackConversion
, it looks like the browser creates an image with a src that follows a chain of 302 redirects between various domains...
www.googleadservices.com ->
googleads.g.doubleclick.net ->
www.google.com ->
www.google.co.uk
The final .co.uk
looks suspicious to me. As we're testing from the UK, we're concerned that tracking called from other countries will redirect to other domains.
What is the complete list of domains that we need to open up in order for the tracking to work?
As requested in comments, an example path component of the first request is:
pagead/conversion/979383382/?random=1452934690748&cv=8&fst=1452934690748&num=1&fmt=3&label=jvoMCNP4umIQ1uiA0wM&guid=ON&u_h=1080&u_w=1920&u_ah=1033&u_aw=1920&u_cd=24&u_his=18&u_tz=0&u_java=false&u_nplug=5&u_nmime=7&frm=0&url=https%3A//beta.captevate.com/payment%3Flevel%3Da00&async=1
and repeating the conversion a second time, the path component of the first request is
pagead/conversion/979383382/?random=1452934959209&cv=8&fst=1452934959209&num=1&fmt=3&label=jvoMCNP4umIQ1uiA0wM&guid=ON&u_h=1080&u_w=1920&u_ah=1033&u_aw=1920&u_cd=24&u_his=26&u_tz=0&u_java=false&u_nplug=5&u_nmime=7&frm=0&url=https%3A//beta.captevate.com/payment%3Flevel%3Da00&async=1
I used a free VPN service to connect from a couple of countries (Netherlands and Singapore), and the last redirect doesn't occur: the final request to www.google.com
is a 200. However, I obviously haven't tried connected from every country, so my original question stands.
You can use Wikipedia's List of Google domains. There are many domains unrelated to Google Adwords, but I don't think allowing domains like
youtube.com
could cause problems.Currently the list is:
However, if you want to be sure if that's really all domains, you should ask Google directly.
What are you trying to achieve by locking down your img-src?
CSP is a great security option but most issues are with javascript (which can cause all sorts of issues), css (which can be used to hide or overly elements with injected content) or framing options (which can be used for click-jacking by similarly overlying content). Images are a much smaller risk IMHO.
There are few security risks that I can think of with loading images, which boil down to:
Tracking and the privacy implications of that. Though you are already using Google Adwords which tracks so much. And those that care about this typically block it in their browser.
Loading of insecure content (I presume you are using HTTPS exclusively or this whole conversation is a bit pointless?). This can be remediated with a more loose CSP policy of just https for img-src.
Loading an image and subsequently overlying part of your website with that rogue image. But that requires javascript and/or CSS injection too - which should be locked down in CSP.
Ultimately unless you have a XSS vulnerability people shouldn't be able to easily load images into your pages. And even if they could I think the risks are small.
So, I would be tempted to just have a "img-src 'self' https:;" rather than try any of the other work arounds the others have suggested - all of which have downsides and are not very future proof.
Ultimately if you are that concerned about security of your site that locking down images is a high priority I would question whether you should be running Google Adwords.
However if there is a specific threat you are trying to protect against, while at the same time still allowing Adwords, then provide details of that and there may be other ways around it. At the moment you've asked for a solution to particular problem without necessarily explaining the actual underlying problem which may have solutions other than the one you are asking about.
Unfortunately, there aren't many ways around this. Resources require either whitelisting (in the case of remote resources, like this one) or inlining tricks (i.e.
nonce
orsha256-...
) when CSP is active. At the end of the day, though, CSP can probably still make your site safer and protect most resources.Depending on what you are trying to do, though, you may still be able to achieve your goal.
Here are some options:
Whitelist all images.
Of course, you could simply place a
"*"
in yourimg-src
directive, but I imagine you already know that and are choosing not to because it defeats CSP's protection for images.Load the image via alternate means.
If all you are after is specifically locking down images, and, say, don't care so much about
XMLHttpRequest
, you could load the pixel viaPOST
or even via a<script>
tag with a customtype
(using the AdWords image tag tracking method). This takes advantage of the fact that Google only needs the browser to complete the HTTP request/response (and redirect) cycle for analytics purposes, and you don't really care about parsing or executing the resulting content, which is a 1x1 transparent pixel anyways. This allows you to lock down yourimg-src
directive (if that is indeed your goal) while still allowing whatever domain Google would like to use for redirects.I know this only moves your problem, but it's useful if your main threat is malicious images.
Place all Google domains in your
img-src
.As suggested below. Header lengths will be a problem (even if the specs say you're fine, implementors are not always so generous), and more importantly, you may encounter spurious failures as Google changes their list of domains, which is certainly not a public or easily noticeable action (besides your ad conversions not coming through!). Since I imagine your job isn't to update that list constantly, you probably don't want to go with this option.
Report failures for a few months and then roll with it.
Because CSP supports reporting URIs and the
Content-Security-Policy-Report-Only
variant, you can roll it out in report-only mode and wait for reports to come in. If you already have good data about your userbase (and it doesn't change much), this can be a good option - once you see those reports stabilize on a list of domains, seal it in a regular CSP header. Optionally, you can place a reporting URI on the final header to catch any additional failures. The downside of this strategy, of course, is that you don't get protection while in report-only mode, and when you switch to enforcing it, failures cause lost conversion data and you're playing catch up.Static pixel with reverse proxy
Okay. Well, with the above options not being so great (I admit it), it's time to think outside the box. The problem here is that HTTP optimization techniques applied by Google (sharding/geo-pinning domains) are at odds with good security practice (i.e. CSP). The root cause of the domain ambiguity is the client's geographic location, so why not pin it yourself?
Assuming you have advanced control of your own HTTP server, you could use the static pixel approach for tracking and proxy the request yourself, like so:
Using a static pixel (like approach #2) and putting your proxy, say, in the US or UK should ensure that the source IP is geographically pinned there, and Google's anycast frontend should route you to a stable endpoint. Placing a proxy in between the user and Google also gives you a chance to force-rewrite the redirect if you want to.
To simplify proxy setup (and add some performance spice), you could opt for something like Fastly with Origin Shielding instead of building it yourself. If you add the DoubleClick backend and proxy from there, you can pin the originating requests from the CDN to come only from a certain geographic region. Either way, your user should see a stable set of redirects, and you can trim down that list of Google domains to just
img-src 'self' *.google.com *.doubleclick.net *.googleadservices.net
.Edit: It is also worth noting that Fastly (and a growing list of other CDN providers) peer directly with Google Cloud at a few of their Points-of-Presence, offering an optimized path into Google's networks for your proxied traffic.