网络上充满了第三方脚本。 网站使用它们来投放广告、进行分析、重新定位等等。 但这并不总是全部内容。 脚本可以跟踪您的行为、您的偏好和其他信息。
在这里,我们将探讨这些第三方脚本的潜在风险。
第三方脚本可能涉及隐私问题
第三方脚本可以报告您不知道的数据。
来自 Google、Facebook 和 Wikipedia 的文档直接告诉我们,这些脚本可以跟踪行为、访问的网站、购买历史记录、人口统计、IP 地址、位置等等。 这部分一般都知道。

虽然标准的第三方跟踪通常有文档记录,但可能存在我们不知道的跟踪行为。
例如,根据普林斯顿大学和斯坦福大学的研究人员的 一项研究,排名前 50 位的网站(Alexa 前 50 位美国网站)中,有 42% 的网站以纯文本形式呈现唯一标识符。 这意味着窃听者可以跟踪您的电子邮件、用户名、全名、家庭住址、购买记录、位置、历史记录、IP 地址和偏好。 只需在网络上四处点击,您可能在不知不觉中允许某人建立一个关于您的庞大信息档案。 事实上,同一 项研究讨论了美国国家安全局如何利用谷歌的一些脚本来跟踪人们。
以下是一个广告商的官方实施指南的截图,该指南明确地向人们提供代码,以便以未加密的纯文本形式将电子邮件地址发送给他们。 他们在收到每个地址后对其进行加密,但它仍然以纯文本形式发送,因此损害已经造成。

第三方脚本可能涉及安全问题
只要您在页面上包含了其他人的外部脚本,就存在固有的安全风险,因为该脚本可以完全访问您网站的前端。
以下是一些这些脚本所做操作的示例。
通过未经清理的数据泄露信用卡信息
安全研究员 Randy Westergren 发现许多主要的跟踪脚本 没有正确地清理数据(感谢我的同事 Sam Ratcliffe 将这篇文章提请我的注意)。 这允许攻击者注入任何他们想要的代码,包括可以窃取信用卡号码的代码。
以下是一个恶意代码注入未经清理的 URL 的截图

使上面截图特别棘手的是,漏洞实际上并非来自该脚本本身。 相反,它来自另一个第三方脚本对另一个第三方脚本的不安全实现。
我在受影响的网站上进行了测试,亲眼目睹了这个漏洞(别担心,我没有使用真实的卡号),事实证明提取敏感信息非常容易

许多广告商已经修复了该漏洞,但这引发了一个问题:还有哪些其他漏洞仍然存在。
使用非 HTTPS 脚本公开私有数据
许多野生的跟踪脚本使用普通的非安全 HTTP。 这可以让攻击者获取人们的信息,并且会导致安全警告,从而吓跑安全页面上的用户。
以下是在安全购物车页面上使用 HTTP 的实施指南的示例。

代码可以在您不知情的情况下更改
对于第三方脚本,代码始终存在更改或消失的风险,而您对此一无所知。
我的同事 Brent Kimmel 告诉我一种名为 子资源完整性的技术,它基本上可以让您确保获得您期望的内容。 在撰写本文时,该技术尚未获得所有浏览器的完全支持,但请关注其进展。
还要记住,当原始第三方脚本本身没有缺陷时,此技术的效果最佳。
第三方脚本通常会加载他们自己的其他第三方脚本
当您信任的第三方脚本引入您没有预料到的脚本时,这会使迄今为止提到的所有安全和隐私风险的可能性成倍增加。
以下是一个第三方脚本加载其他脚本的示例

第三方脚本可能涉及性能问题
页面加载速度变慢
第三方脚本经常会导致页面加载速度变慢。 例如,Business Insider 的实际网站加载大约需要 1 秒,而第三方脚本占 7 到 15 秒加载时间的绝大部分。 以下截图显示了数百个第三方脚本长长队列的末尾

值得称赞的是,Business Insider 似乎异步加载了大部分第三方脚本,因此感知的加载时间并没有像 7 到 15 秒那样长。
当第三方脚本不允许您异步加载它们时会发生什么?
有些脚本不允许自身异步加载
当脚本使用 document.write
时,会阻止它异步加载。 许多常见的第三方脚本使用 document.write
,因此它们会阻塞文档并无故延长页面加载时间。
以下是一个示例

有些脚本会影响滚动性能
第三方脚本通常会对滚动事件执行操作。 以下是一个脚本在每次滚动时运行循环的截图。

虽然仅此一个示例不会影响网站的运行,但当多个脚本不断地轰炸滚动事件时,它会导致明显的变慢。
第三方脚本可能会产生意想不到的后果
第三方脚本可以在您的页面上做各种意想不到的事情。以下是一些例子。
覆盖您的变量
网络上一些最常用的第三方脚本使用不必要的全局变量,这些变量可能会覆盖您网站上的变量。
以下屏幕截图显示了一个使用两个全局变量来生成一个随机数的脚本(甚至在过程中使用不必要的类型转换)。

通过使用 eval 创建不必要的风险
由于 eval
会运行任何内容,因此它很容易成为攻击者的目标。以下是一个使用 eval
运行任意 JavaScript 的跟踪脚本的示例。有趣的是,这个函数实际上被称为 arbitraryJSCode
。

虽然 eval
不一定会破坏所有情况下的所有东西,但它确实存在风险,因此当您看到它时,至少需要再考虑一下。
更改您的布局
一些跟踪脚本在页面的底部或顶部插入微小的图像和 iframe,这会导致标题上方或页脚下方出现间隙。
以下屏幕截图显示了一个在 Comcast/Xfinity 网站底部创建间隙的跟踪标签。

或者,第三方脚本可能会像以下屏幕截图中 Elite Daily 网站上的广告代码一样出现故障。

通过将功能过于紧密地绑定到 DOM 来设置错误
以下示例显示了一个跟踪脚本,其功能取决于特定的 DOM 元素。对网站布局的微小更改可能会破坏此代码。

回顾
第三方脚本可以提供强大的功能,但它们也给隐私、安全、性能和页面行为带来风险。现在您已经了解了第三方脚本的一些风险,希望您对遇到它们时会有什么期待有所了解。
如果您有任何问题、想法或故事,请随时留下评论。我很想知道人们在集成它们时的思考过程。您是否完全避免使用它们?您是否只允许您高度信任的来源?您是否使用像 Google Tag Manager 或 Segment 这样的中介?您是否通过阅读代码或密切关注 DevTools 来自己审查代码?
我一直不明白为什么人们实际上会从 Google 或任何其他内容提供商加载像 jQuery 或 Prototype.js 这样的知名库。它们在您自己的服务器上非常容易处理。分片和 CDN 听起来像是很好的论据,但它们只带来了额外的故障点风险。
在您自己的服务器上托管尽可能多的这些库。
将脚本连接成一个单独的文件(考虑使用 grunt)。
如果您的网站使用许多资产:考虑分片。如果 Web 服务器有未使用的资源,您只需在 DNS 中添加服务器名称,强制浏览器打开更多到您服务器的并发连接。当然,这在 http/2 或 SPDY 中是多余的。
考虑自写的延迟脚本插入
为什么使用
type="text/javascript"
?我同意,我个人更喜欢在自己的服务器上托管像 jQuery 这样的库的想法。我知道这方面还有其他观点,但我同意,单独托管它确实引入了额外的故障点。
至于跟踪脚本,其中一些需要与第三方服务器直接交互,因此这会使事情变得复杂并引入大量风险。
@gcampbell: 为什么使用 .type=’text/javascript’?
我记得当没有指定脚本类型时,某些浏览器遇到了问题。我现在不记得是哪些浏览器了;我曾经用这种 JS 解决方案尝试过平板电脑、手机等。也许其他人可以回答这个问题?
@Phil
做了一些研究,事实证明,只有没有 type 属性的 HTML4 标签才是错误的,但浏览器似乎默认使用 type=”text/javascript”。见
http://stackoverflow.com/questions/2267476/html-script-tag-type-or-language-or-omit-both
http://stackoverflow.com/questions/4195427/is-the-type-attribute-necessary-for-script-tags
http://javascript.crockford.com/script.html
使用 CDN 托管像 jQuery 这样的通用库的原因是,您的访问者通常已经将此脚本下载到他们的浏览器缓存中 - 从而让您的网站加载更快 = 在 Google 的移动可访问性方面获得更好的排名(下载和呈现第一页的时间)。