跳转至主要内容

我们对 RCE 安全公告的回应

·阅读时间:12 分钟
chris48s
Shields.io 核心团队

我们刚刚发布了一个关于动态 JSON/TOML/YAML 徽章中远程代码执行漏洞的关键安全公告:https://github.com/badges/shields/security/advisories/GHSA-rxvx-x284-4445 感谢 @nickcopi 的帮助。

如果您自行托管 Shields 实例,请尽快升级到 server-2024-09-25 或更高版本,以保护您的实例。

这主要影响自托管用户。然而,这也对 shields.io 本身的一些用户带来了一些连锁反应。

1. 授权 Shields.io GitHub OAuth 应用的用户

虽然我们在发现此漏洞后迅速采取了措施来修复它,但此攻击向量已在我们的应用程序中存在一段时间。我们不知道它是否在 shields.io 上被积极利用。我们也无法证明它没有被利用。

我们不会记录或跟踪我们的用户,因此,对于 shields.io 的最终用户来说,漏洞的攻击面非常有限。这是设计使然。shields.io 持有的(少数)信息资产之一是我们的 GitHub 令牌池。这允许用户通过授权我们的 OAuth 应用与我们共享令牌。这样做可以让我们访问具有公共数据只读权限的令牌,我们可以使用它来提高调用 GitHub API 时的速率限制。

我们持有的令牌对攻击者来说价值不高,因为它们只有公共数据的只读权限,但我们不能肯定它们没有被泄露。如果您过去捐赠过令牌并想撤销它,您可以在 https://github.com/settings/applications 撤销 Shields.io OAuth 应用,这将停用您与我们共享的令牌。

2. 使用动态 JSON/TOML/YAML 徽章的用户

到目前为止,我们一直使用 https://github.com/dchester/jsonpath 作为我们使用 JSONPath 表达式查询文档的库。@nickcopi 负责任地向我们报告了如何利用该库中的原型污染漏洞来构造 JSONPath 表达式,从而允许攻击者执行远程代码。此漏洞已在该软件包的问题跟踪器上报告,但未被安全扫描工具标记。尽管该软件包被广泛使用,但似乎不太可能在上游软件包中修复此问题。即使是为了应对关键安全问题,该软件包将来似乎也不太可能再获得任何维护。为了解决这个问题,我们需要切换到不同的 JSONPath 库。我们决定切换到 https://github.com/JSONPath-Plus/JSONPath 并使用 eval: false 选项来禁用脚本表达式。

这是一项重要的安全改进,我们必须做出更改以保护 shields.io 和用户托管的应用程序实例的安全。然而,从向后兼容性的角度来看,这确实需要一些权衡。

使用 eval: false

使用带有 eval: false 的 JSONPath-Plus 将禁用一些依赖于计算 javascript 表达式的查询语法。

例如,以前可以使用类似 $..keywords[(@.length-1)] 的 JSONPath 查询针对文档 https://github.com/badges/shields/raw/master/package.json 从关键字数组中选择最后一个元素 https://github.com/badges/shields/blob/e237e40ab88b8ad4808caad4f3dae653822aa79a/package.json#L6-L12

现在这不支持此查询。

在这个特定情况下,您可以将该查询重写为 $..keywords[-1:] 并获得相同的结果,但这并非在所有情况下都可行。我们确实意识到这会删除一些以前可以使用的功能,但修复此远程代码执行漏洞是首要任务,尤其是在许多情况下都有解决方法的情况下。

实现的怪癖

从历史上看,每个 JSONPath 实现都有其自身的特性。虽然大多数简单和常见的查询在不同实现中的行为方式相同,但切换到另一个库意味着某些查询可能无法工作或产生不同的结果。

JSONPath 领域最近发生的一件有趣的事情是 RFC 9535 https://www.rfc-editor.org/rfc/rfc9535,它试图标准化 JSONPath。作为此缓解措施的一部分,我们确实研究了迁移到符合 RFC9535 的库是否可行。然而,我们的评估是 JavaScript 社区还没有一个足够成熟/受支持的符合 RFC9535 的 JSONPath 实现。这意味着我们正在从一个有怪癖的实现切换到另一个有不同怪癖的实现。

同样,这代表了向后兼容性的不幸中断。然而,有必要优先修复此远程代码执行漏洞,而不是向后兼容性。

尽管我们无法提供精确的迁移指南,但下表列出了 https://github.com/dchester/jsonpathhttps://github.com/JSONPath-Plus/JSONPath 与共识实现已知存在差异的查询类型。这来源于优秀的 https://cburgmer.github.io/json-path-comparison/ 虽然这是一个长列表,但其中许多输入代表边缘情况或病态输入,而不是常见用法。

表格
查询类型示例查询
具有较大结束数字和负步骤的数组切片$[2:-113667776004:-1]
具有较大起始数字和负步骤的数组切片$[113667776004:2:-1]
具有负步骤的数组切片$[3:0:-2]
对部分重叠数组使用负步骤的数组切片$[7:3:-1]
仅具有负步骤的数组切片$[::-2]
具有开放结尾和负步骤的数组切片$[3::-1]
数组切片,开头开放,负向步长$[:2:-1]
范围为 0 的数组切片$[0:0]
步长为 0 的数组切片$[0:3:0]
带有步长和前导零的数组切片$[010:024:010]
带有空路径的括号表示法$[]
对对象使用带数字的括号表示法$[0]
对字符串使用带数字的括号表示法$[0]
带数字 -1 的括号表示法$[-1]
带引号的数组切片字面量的括号表示法$[':']
带引号的右括号字面量的括号表示法$[']']
带引号的当前对象字面量的括号表示法$['@']
带引号的转义反斜杠的括号表示法$['\']
带引号的转义单引号的括号表示法$[''']
带引号的根字面量的括号表示法$['$']
带引号的组合特殊字符的括号表示法$[':@."$,*'\']
带引号的字符串和未转义单引号的括号表示法$['single'quote']
带引号的联合字面量的括号表示法$[',']
带引号的通配符字面量 ? 的括号表示法$['*']
在没有键的对象上使用带引号的通配符字面量的括号表示法$['*']
带空格的括号表示法$[ 'a' ]
用点分隔两个字面量的括号表示法$['two'.'some']
用点分隔两个字面量且不带引号的括号表示法$[two.some]
不带引号的括号表示法$[key]
使用点表示法的当前对象@.a
点括号表示法$.['key']
带双引号的点括号表示法$.["key"]
不带引号的点括号表示法$.[key]
递归下降后带有额外点的点表示法?$...key
联合后带有键的点表示法$['one','three'].key
带破折号的点表示法$.key-dash
带双引号的点表示法$."key"
递归下降后带双引号的点表示法?$.."key"
带有空路径的点表示法$.
数组上名为 length 的键的点表示法$.length
带有键根字面量的点表示法$.$
带有非 ASCII 键的点表示法$.??
带数字的点表示法$.2
带数字 -1 的点表示法$.-1
带单引号的点表示法$.'key'
递归下降后带单引号的点表示法?$..'key'
带单引号和点的点表示法$.'some.key'
键带空格的点表示法$. a
对标量进行递归下降后带有通配符的点表示法?$..*
不带点的点表示法$a
没有根的点表示法.key
没有根和点的点表示法key
不适用
对象的过滤表达式$[?(@.key)]
递归下降后带有通配符的点表示法后的过滤表达式?$..*[?(@.id>2)]
递归下降后的过滤表达式?$..[?(@.id==2)]
带加法的过滤表达式$[?(@.key+50==100)]
带布尔与运算符和值 false 的过滤表达式$[?(@.key>0 && false)]
带布尔与运算符和值 true 的过滤表达式$[?(@.key>0 && true)]
带布尔或运算符和值 false 的过滤表达式$[?(@.key>0 || false)]
带布尔或运算符和值 true 的过滤表达式$[?(@.key>0 || true)]
带 -1 的括号表示法的过滤表达式$[?(@[-1]==2)]
对对象使用带数字的括号表示法的过滤表达式$[?(@[1]=='b')]
带当前对象的过滤表达式$[?(@)]
带不同未分组运算符的过滤表达式$[?(@.a && @.b || @.c)]
带除法的过滤表达式$[?(@.key/10==5)]
带破折号的点表示法的过滤表达式$[?(@.key-dash == 'value')]
带数字的点表示法的过滤表达式$[?(@.2 == 'second')]
数组上带数字的点表示法的过滤表达式$[?(@.2 == 'third')]
带空表达式的过滤表达式$[?()]
带等于的过滤表达式$[?(@.key==42)]
对数字数组进行等于比较的过滤表达式$[?(@==42)]
对对象进行等于比较的过滤表达式$[?(@.key==42)]
等于数组的过滤表达式$[?(@.d==["v1","v2"])]
范围为 1 的数组切片的等于数组的过滤表达式$[?(@[0:1]==[1])]
带星号的点表示法的等于数组的过滤表达式$[?(@.*==[1,2])]
等于数组或等于 true 的过滤表达式$[?(@.d==["v1","v2"] || (@.d == true))]
带单引号的等于数组的过滤表达式$[?(@.d==['v1','v2'])]
等于布尔表达式值的过滤表达式$[?((@.key<44)==false)]
等于 false 的过滤表达式$[?(@.key==false)]
等于 null 的过滤表达式$[?(@.key==null)]
范围为 1 的数组切片的等于数字的过滤表达式$[?(@[0:1]==1)]
带星号的括号表示法的等于数字的过滤表达式$[?(@[*]==2)]
带星号的点表示法的等于数字的过滤表达式$[?(@.*==2)]
带小数的等于数字的过滤表达式$[?(@.key==-0.123e2)]
带前导零的等于数字的过滤表达式$[?(@.key==010)]
等于对象的过滤表达式$[?(@.d=={"k":"v"})]
等于字符串的过滤表达式$[?(@.key=="value")]
带 unicode 字符转义的等于字符串的过滤表达式$[?(@.key=="Mot\u00f6rhead")]
等于 true 的过滤表达式$[?(@.key==true)]
带路径和路径的等于比较的过滤表达式$[?(@.path1 == @.path2)]
带根引用的等于比较的过滤表达式$.items[?(@.key==$.value)]
带大于的过滤表达式$[?(@.key>42)]
带大于等于的过滤表达式$[?(@.key>=42)]
值数组中的过滤表达式$[?(@.d in [2, 3])]
当前对象中的过滤表达式$[?(2 in @.d)]
使用 length 自由函数的过滤表达式$[?(length(@) == 4)]
使用 length 函数的过滤表达式$[?(@.length() == 4)]
使用 length 属性的过滤表达式$[?(@.length == 4)]
带小于的过滤表达式$[?(@.key<42)]
带小于等于的过滤表达式$[?(@.key<=42)]
数据中带有本地点键和 null 的过滤表达式$[?(@.key='value')]
带乘法的过滤表达式$[?(@.key*2==100)]
带否定和等于的过滤表达式$[?(!(@.key==42))]
带否定和等于数组或等于 true 的过滤表达式$[?(!(@.d==["v1","v2"]) || (@.d == true))]
带否定和小于的过滤表达式$[?(!(@.key<42))]
带否定且没有值的过滤表达式$[?([email protected])]
非单一存在性测试的过滤表达式$[?(@.a.*)]
带不等于的过滤表达式$[?(@.key!=42)]
带不等于数组或等于 true 的过滤表达式$[?((@.d!=["v1","v2"]) || (@.d == true))]
带父轴运算符的过滤表达式$[*].bookmarks[?(@.page == 45)]^^^
带正则表达式的过滤表达式$[?(@.name=~/hello.*/)]
从成员获取正则表达式的过滤表达式$[?(@.name=~/@.pattern/)]
与标量进行集合比较的过滤表达式$[?(@[*]>=4)]
与集合进行集合比较的过滤表达式$.x[?(@[*]>=$.y[*] )]
带单个等号的过滤表达式$[?(@.key=42)]
带子过滤器的过滤表达式$[?(@.a[?(@.price>10)])]
深度嵌套子路径的过滤表达式$[?(@.a.b.c==3)]
带减法的过滤表达式$[?(@.key-50==-100)]
带三个等号的过滤表达式$[?(@.key===42)]
带值的过滤表达式$[?(@.key)]
递归下降后带值的过滤表达式?$..[?(@.id)]
值为 false 的过滤表达式$[?(false)]
从递归下降获取值的过滤表达式$[?(@..child)]
值为 null 的过滤表达式$[?(null)]
值等于 true 的过滤表达式$[?(true)]
不带括号的过滤表达式$[[[email protected]]==42]
无值的过滤表达式$[?(@.key)]
求和函数$.data.sum()
括号表示法$(key,more)
递归下降?$..
点符号后的递归下降?$.key..
标量上的根$
标量 false 上的根$
标量 true 上的根$
脚本表达式$[(@.length-1)]
数组重复值的并集$[0,0]
对象重复值的并集$['a','a']
带过滤器的并集$[?(@.key<3),?(@.key>6)]
带键的并集$['key','another']
在不包含键的对象上使用键的并集$['missing','key']
数组切片后的键的并集$[:]['c','d']
括号表示法后的键的并集$[0]['c','d']
通配符点符号后的键的并集$.*['c','d']
递归下降后的键的并集?$..['c','d']
通配符点符号后重复匹配的并集$.*[0,:5]
数字和切片的并集$[1:3,4]
带空格的并集$[ 0 , 1 ]
通配符和数字的并集$[*,1]

Shields 自定义徽标的停用

·2 分钟阅读
PyvesB
Shields.io 核心团队

#9476中的讨论之后,我们已删除了 Shields.io 端维护的所有自定义徽标(bitcoin、dependabot、gitlab、npm、paypal、serverfault、stackexchange、superuser、telegram、travis),并且从现在起将完全依赖Simple-Icons 项目为我们的徽章提供命名徽标。如果您之前使用的是 Shields 自定义徽标,您将透明地切换到相应的 Simple-Icon,并且无需对您的徽标进行任何更改。

做出此决定的原因包括以下几点:

  • 通过删除数十行代码来降低代码复杂性和由此带来的开销。
  • 减少维护负担;我们经常收到添加不符合我们准则的徽标的拉取请求,或其他各种相关问题。
  • 提供更清晰的用户体验;现在,所有命名徽标在 logoColor 和其他参数方面的行为方式相同。
  • 减少贡献者的挫败感,他们准备了徽标拉取请求,却被告知他们没有阅读准则或对所述准则的理解存在偏差。
  • 强化 Shields.io 提供一致徽章的使命,现在所有命名徽标均为单色。
  • 提高对第三方品牌的合规性;Simple-Icons 会定期检查其图标是否符合最新的品牌准则,而我们不会。
  • 解锁#4947

我们承认,在#7684中,你们中的一些人表达了对特定 Shields 自定义徽标的偏好,而不是其对应的 Simple-Icons 徽标。如果您真的想回到 Shields 自定义徽标,您可以利用自定义徽标来实现。以下是我们所有现有徽标的相应 Base64 编码徽标参数:

名称徽标预览logo 参数
bitcoinbitcoindata:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIzLjYzNiAxNC45MDJjLTEuNjAyIDYuNDMtOC4xMTQgMTAuMzQyLTE0LjU0MyA4Ljc0QzIuNjY2IDIyLjAzNy0xLjI0NiAxNS41MjUuMzU3IDkuMDk4IDEuOTYgMi42NjkgOC40Ny0xLjI0NCAxNC44OTcuMzU5YzYuNDMgMS42MDIgMTAuMzQxIDguMTE1IDguNzM5IDE0LjU0NCIgZmlsbD0iI2Y3OTMxYSIvPjxwYXRoIGQ9Ik0xNC42ODYgMTAuMjY3Yy0uMzcxIDEuNDg3LTIuNjYzLjczMS0zLjQwNi41NDZsLjY1NS0yLjYyOWMuNzQzLjE4NiAzLjEzOC41MzEgMi43NSAyLjA4M20tLjQwNiA0LjI0MmMtLjQwNyAxLjYzNS0zLjE2Ljc1LTQuMDUzLjUzbC43MjQtMi45Yy44OTMuMjI0IDMuNzU0LjY2NCAzLjMzIDIuMzdtMy4wMDgtNC4yMTljLjIzOC0xLjU5Ni0uOTc3LTIuNDU1LTIuNjQtMy4wMjdsLjU0LTIuMTYzLTEuMzE4LS4zMy0uNTI1IDIuMTA3YTU0LjI5MiA1NC4yOTIgMCAwIDAtMS4wNTQtLjI0OWwuNTMtMi4xMi0xLjMxNy0uMzI4LS41NCAyLjE2MmMtLjI4Ni0uMDY1LS41NjctLjEzLS44NC0uMTk4bC4wMDEtLjAwNy0xLjgxNi0uNDUzLS4zNSAxLjQwNnMuOTc3LjIyNC45NTYuMjM4Yy41MzMuMTMzLjYzLjQ4Ni42MTMuNzY2bC0uNjE1IDIuNDYzYy4wMzguMDEuMDg1LjAyNC4xMzcuMDQ1bC0uMTM4LS4wMzUtLjg2MiAzLjQ1MmMtLjA2NS4xNjEtLjIzLjQwNS0uNjA0LjMxMi4wMTQuMDItLjk1Ny0uMjM5LS45NTctLjIzOUw1LjgzNiAxNS42bDEuNzE0LjQyN2MuMzE4LjA4LjYzLjE2NC45MzguMjQybC0uNTQ1IDIuMTkgMS4zMTUuMzI4LjU0LTIuMTY0Yy4zNi4wOTcuNzA4LjE4NyAxLjA1LjI3MWwtLjUzOCAyLjE1NiAxLjMxNi4zMjguNTQ2LTIuMTgzYzIuMjQ1LjQyNCAzLjkzMy4yNTMgNC42NDMtMS43NzcuNTc0LTEuNjM1LS4wMjctMi41NzgtMS4yMDgtMy4xOTQuODYtLjE5OCAxLjUwOC0uNzY1IDEuNjgxLTEuOTM0IiBmaWxsPSIjZmZmIi8+PC9zdmc+
dependabotdependabotdata:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NCA1NCIgZmlsbD0iI2ZmZiI+PHBhdGggZD0iTTI1IDNhMSAxIDAgMCAwLTEgMXY3YTEgMSAwIDAgMCAxIDFoNXYzSDZhMyAzIDAgMCAwLTMgM3YxMkgxYTEgMSAwIDAgMC0xIDF2MTBhMSAxIDAgMCAwIDEgMWgydjZhMyAzIDAgMCAwIDMgM2g0MmEzIDMgMCAwIDAgMy0zdi02aDJhMSAxIDAgMCAwIDEtMVYzMWExIDEgMCAwIDAtMS0xaC0yVjE4YTMgMyAwIDAgMC0zLTNIMzNWNGExIDEgMCAwIDAtMS0xaC03em0tMy45ODIgMjZhMS4yMSAxLjIxIDAgMCAxIC44MzcuMzU1bDEuMjkgMS4yOWExLjIxIDEuMjEgMCAwIDEgMCAxLjcwOSAxLjIxIDEuMjEgMCAwIDEgMCAuMDAxbC02LjI5MSA2LjI5YTEuMjEgMS4yMSAwIDAgMS0xLjcxIDBsLTMuNzktMy43OTFhMS4yMSAxLjIxIDAgMCAxIDAtMS43MWwxLjI5LTEuMjlhMS4yMSAxLjIxIDAgMCAxIDEuNzEgMEwxNiAzMy41bDQuMTQ1LTQuMTQ1YTEuMjEgMS4yMSAwIDAgMSAuODczLS4zNTV6bTE5Ljk2MiAwYTEuMjEgMS4yMSAwIDAgMSAuODc0LjM1NGwxLjI5IDEuMjlhMS4yMSAxLjIxIDAgMCAxIDAgMS43MWwtNi4yOSA2LjI4OXYuMDAyYTEuMjEgMS4yMSAwIDAgMS0xLjcxMSAwbC0zLjc5LTMuNzlhMS4yMSAxLjIxIDAgMCAxIDAtMS43MWwxLjI5LTEuMjlhMS4yMSAxLjIxIDAgMCAxIDEuNzEgMGwxLjY0NSAxLjY0NSA0LjE0Ny00LjE0NkExLjIxIDEuMjEgMCAwIDEgNDAuOTggMjl6Ii8+PC9zdmc+
gitlabgitlabdata:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjkzIDkzIDE5NCAxOTQiPjxkZWZzPjxzdHlsZT4uYntmaWxsOiNmYzZkMjZ9PC9zdHlsZT48L2RlZnM+PHBhdGggc3R5bGU9ImZpbGw6I2UyNDMyOSIgZD0ibTI4Mi44MyAxNzAuNzMtLjI3LS42OS0yNi4xNC02OC4yMmE2LjgxIDYuODEgMCAwIDAtMi42OS0zLjI0IDcgNyAwIDAgMC04IC40MyA3IDcgMCAwIDAtMi4zMiAzLjUybC0xNy42NSA1NGgtNzEuNDdsLTE3LjY1LTU0YTYuODYgNi44NiAwIDAgMC0yLjMyLTMuNTMgNyA3IDAgMCAwLTgtLjQzIDYuODcgNi44NyAwIDAgMC0yLjY5IDMuMjRMOTcuNDQgMTcwbC0uMjYuNjlhNDguNTQgNDguNTQgMCAwIDAgMTYuMSA1Ni4xbC4wOS4wNy4yNC4xNyAzOS44MiAyOS44MiAxOS43IDE0LjkxIDEyIDkuMDZhOC4wNyA4LjA3IDAgMCAwIDkuNzYgMGwxMi05LjA2IDE5LjctMTQuOTEgNDAuMDYtMzAgLjEtLjA4YTQ4LjU2IDQ4LjU2IDAgMCAwIDE2LjA4LTU2LjA0WiIvPjxwYXRoIGNsYXNzPSJiIiBkPSJtMjgyLjgzIDE3MC43My0uMjctLjY5YTg4LjMgODguMyAwIDAgMC0zNS4xNSAxNS44TDE5MCAyMjkuMjVjMTkuNTUgMTQuNzkgMzYuNTcgMjcuNjQgMzYuNTcgMjcuNjRsNDAuMDYtMzAgLjEtLjA4YTQ4LjU2IDQ4LjU2IDAgMCAwIDE2LjEtNTYuMDhaIi8+PHBhdGggc3R5bGU9ImZpbGw6I2ZjYTMyNiIgZD0ibTE1My40MyAyNTYuODkgMTkuNyAxNC45MSAxMiA5LjA2YTguMDcgOC4wNyAwIDAgMCA5Ljc2IDBsMTItOS4wNiAxOS43LTE0LjkxUzIwOS41NSAyNDQgMTkwIDIyOS4yNWMtMTkuNTUgMTQuNzUtMzYuNTcgMjcuNjQtMzYuNTcgMjcuNjRaIi8+PHBhdGggY2xhc3M9ImIiIGQ9Ik0xMzIuNTggMTg1Ljg0QTg4LjE5IDg4LjE5IDAgMCAwIDk3LjQ0IDE3MGwtLjI2LjY5YTQ4LjU0IDQ4LjU0IDAgMCAwIDE2LjEgNTYuMWwuMDkuMDcuMjQuMTcgMzkuODIgMjkuODJMMTkwIDIyOS4yMVoiLz48L3N2Zz4=
npmnpmdata:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZD0iTTAgMGg0MHY0MEgwVjB6IiBmaWxsPSIjY2IwMDAwIi8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTcgN2gyNnYyNmgtN1YxNGgtNnYxOUg3eiIvPjwvc3ZnPgo=
paypalpaypaldata:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE5LjcxNSA2LjEzM2MuMjQ5LTEuODY2IDAtMy4xMS0uOTk5LTQuMjY2QzE3LjYzNC42MjIgMTUuNzIxIDAgMTMuMzA3IDBINi4yMzVjLS40MTggMC0uOTE2LjQ0NC0xIC44ODlMMi4zMjMgMjAuNjIyYzAgLjM1Ni4yNS44LjY2NS44aDQuMzI4bC0uMjUgMS45NTZjLS4wODQuMzU1LjE2Ni42MjIuNDk4LjYyMmgzLjY2M2MuNDE3IDAgLjgzMi0uMjY3LjkxNS0uNzExdi0uMjY3bC43NDktNC42MjJ2LS4xNzhjLjA4My0uNDQ0LjUtLjguOTE1LS44aC41YzMuNTc4IDAgNi4zMjUtMS4xMSA3LjE1Ni01LjkxNS40MTgtMS44NjcuMjUyLTMuMzc4LS43NDctNC40NDUtLjI1LS4zNTUtLjY2Ni0uNjIyLTEtLjg4OSIgZmlsbD0iIzAwOWNkZSIvPjxwYXRoIGQ9Ik0xOS43MTUgNi4xMzNjLjI0OS0xLjg2NiAwLTMuMTEtLjk5OS00LjI2NkMxNy42MzQuNjIyIDE1LjcyMSAwIDEzLjMwNyAwSDYuMjM1Yy0uNDE4IDAtLjkxNi40NDQtMSAuODg5TDIuMzIzIDIwLjYyMmMwIC4zNTYuMjUuOC42NjUuOGg0LjMyOGwxLjE2NC03LjM3OC0uMDgzLjI2N2MuMDg0LS41MzMuNS0uODg5Ljk5OC0uODg5aDIuMDhjNC4wNzkgMCA3LjI0MS0xLjc3OCA4LjI0LTYuNzU1LS4wODMtLjI2NyAwLS4zNTYgMC0uNTM0IiBmaWxsPSIjMDEyMTY5Ii8+PHBhdGggZD0iTTkuNTYzIDYuMTMzYy4wODItLjI2Ni4yNS0uNTMzLjQ5OC0uNzEuMTY2IDAgLjI1LS4wOS40MTYtLjA5aDUuNDk0Yy0uMjY2IDAgMS4zMy4wOSAxLjgzLjE3OC4xNjYgMCAuMzMzIDAgLjQ5OC4wODkuMTY4LjA4OS4zMzQuMDg5LjQxOC4xNzhjLjI0OCAwIC40MTYuMDg5LjU4NC4yNjYuMTU5LjI2Ni4xNTkuNDk4LjE1OS43NDkuMjVjLjI0OC4wODkuNDk3LjI2Ni43NDguMzU1LjI0OC0xLjg2NiAwLTMuMTEtLjk5OS00LjM1NUMxNy43MTcuNTMzIDE1LjgwNCAwIDEzLjM5IDBINi4yMzVjLS40MTggMC0uOTE2LjM1Ni0xIC44ODlMMi4zMjMgMjAuNjIyYzAgLjM1Ni4yNS44LjY2NS44aDQuMzI4bDEuMTY0LTcuMzc4IDEuMDg0LTcuOTF6IiBmaWxsPSIjMDAzMDg3Ii8+PC9zdmc+
serverfaultserverfaultdata:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAgMTIwIj48c3R5bGU+LnN0MHtmaWxsOiNhN2E5YWN9LnN0MXtmaWxsOiM4MTgyODV9LnN0MntmaWxsOiM1ODU4NWF9LnN0M3tmaWxsOiNkMWQyZDR9LnN0NHtmaWxsOiMyMzFmMjB9PC9zdHlsZT48cGF0aCBjbGFzcz0ic3QwIiBkPSJNMTMuNyA0MS42aDQ0djguN2gtNDR6Ii8+PHBhdGggY2xhc3M9InN0MSIgZD0iTTEzLjcgNTUuOGg0NHY4LjdoLTQ0eiIvPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMy43IDY5aDQ0djguN2gtNDR6Ii8+PHBhdGggY2xhc3M9InN0MyIgZD0iTTEzLjcgMjcuNmg0NHY4LjdoLTQ0eiIvPjxwYXRoIGNsYXNzPSJzdDQiIGQ9Ik0xMy43IDgzLjJoNDR2OC43aC00NHoiLz48cGF0aCBmaWxsPSIjOTkyMjI0IiBkPSJNNjMgNDEuNmgxOC43djguN0g2M3oiLz48cGF0aCBmaWxsPSIjNjMwZjE2IiBkPSJNNjMgNTUuOGgxOC43djguN0g2M3oiLz48cGF0aCBmaWxsPSIjMmIxNDE1IiBkPSJNNjMgNjloMTguN3Y4LjdINjN6Ii8+PHBhdGggZmlsbD0iI2U3MjgyZCIgZD0iTTYzIDI3LjZoMTguN3Y4LjdINjN6Ii8+PHBhdGggY2xhc3M9InN0NCIgZD0iTTYzIDgzLjJoMTguN3Y4LjdINjN6Ii8+PGc+PHBhdGggY2xhc3M9InN0MCIgZD0iTTg2LjggNDJoMTguN3Y4LjdIODYuOHoiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNODYuOCA1Ni4yaDE4Ljd2OC43SDg2Ljh6Ii8+PHBhdGggY2xhc3M9InN0MiIgZD0iTTg2LjggNjkuNGgxOC43djguN0g4Ni44eiIvPjxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik04Ni44IDI4aDE4Ljd2OC43SDg2Ljh6Ii8+PHBhdGggY2xhc3M9InN0NCIgZD0iTTg2LjggODMuNmgxOC43djguN0g4Ni44eiIvPjwvZz48L3N2Zz4=
stackexchangestackexchangedata:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIuMjczIDEwLjQ2M2gxOS4zMjV2My45NzhIMi4yNzN6IiBmaWxsPSIjMzc2ZGI2Ii8+PHBhdGggZD0iTTIuMjczIDUuMzIyaDE5LjMyNVY5LjNIMi4yNzN6IiBmaWxsPSIjNGNhMmRhIi8+PHBhdGggZD0iTTE4LjU3NSAwSDUuMzc0Yy0xLjcwNSAwLTMuMSAxLjQyLTMuMSAzLjE3OFY0LjIxaDE5LjMyNFYzLjE3OEMyMS41OTggMS40MiAyMC4yNTQgMCAxOC41NzUgMHoiIGZpbGw9IiM5MWQ4ZjQiLz48cGF0aCBkPSJNMi4yNzMgMTUuNTc4djEuMDMzYzAgMS43NTcgMS4zOTYgMy4xNzggMy4xIDMuMTc4aDguMjY4VjI0bDQuMDgxLTQuMjExaC45MDVjMS43MDUgMCAzLjEtMS40MiAzLjEtMy4xNzh2LTEuMDMzeiIgZmlsbD0iIzFlNTM5NyIvPjwvc3ZnPg==
superusersuperuserdata:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIuNTk0IDBhLjUxNC41MTQgMCAwIDAtLjM0NC4xMS40MDQuNDA0IDAgMCAwLS4xMzMuMzA2djIzLjE5N2MwIC4xMjQuMDQ4LjI0Ni4xNDUuMzEyLjA5Ni4wNjUuMjA4LjA3NS4zMzIuMDc1aDUuNTkzYy4xMyAwIC4yNDMtLjAyLjMzNC0uMDkzLjA5Mi0uMDcyLjEzMS0uMi4xMTItLjMxN2wuMDAyLjAyM3YtMS40NjdhLjM2Ny4zNjcgMCAwIDAtLjE2LS4zMDEuNjEyLjYxMiAwIDAgMC0uMzQ0LS4wODdINS42MTNjLS4xMSAwLS4xNy0uMDItLjE5MS0uMDM3LS4wMjItLjAxNi0uMDMyLS4wMy0uMDMyLS4xVjIuNDA4YzAtLjA3MS4wMTItLjA5NC4wNDEtLjExNi4wMy0uMDIzLjEwMi0uMDUuMjM5LS4wNWgyLjQ4OGMuMTI0IDAgLjIzNS0uMDEuMzMyLS4wNzYuMDk3LS4wNjYuMTQ1LS4xODguMTQ1LS4zMTFWLjQxNmEuMzk2LjM5NiAwIDAgMC0uMTU3LS4zMjNBLjU4My41ODMgMCAwIDAgOC4xMzEgMHoiIGZpbGw9IiMwMDAiLz48cGF0aCBkPSJNMjAuOTU4IDE0LjQ3Yy0xLjQ4Mi40MTQtMi40ODkgMS4yNzMtMi40ODkgMi42ODR2NC4wNDJjMCAzLjAxNy0yLjkwOSAyLjY4NS0yLjUxNyAyLjY4NWgtLjU2Yy0uMjIzIDAtLjM2My0uMDgzLS4zNjMtLjI3N1YyMi4yMmMwLS4xOTQuMTEyLS4yNzcuMzM2LS4yNzdoLjQ0N2MyLjE1NCAwIDMuNjY0LjQ3IDMuNjY0LTEuMjQ1di0zLjg3NmMwLTEuMTkuODQtMi44NTEgMi41MTctMy40Ni4xMTItLjAyOC4xNC0uMDgzLjE0LS4xMzggMC0uMDU2LS4wMjgtLjEzOS0uMTQtLjE5NC0xLjUzOC0uNjkyLTIuNTE3LTEuODI3LTIuNTE3LTMuMTg0VjUuNDczYzAtMS42ODktMS41MS0zLjM3Ny0zLjY2NC0zLjM3N2gtLjQ0N2MtLjIyNCAwLS4zMzYtLjA4My0uMzM2LS4yNzdWLjQzNWMwLS4xOTQuMTQtLjI3Ny4zNjQtLjI3N2guNTZjMy42MDcgMCA2LjU0NCAyLjU0NyA2LjU0NCAxLjU2NHYzLjY4MmMwIDEuMzg0IDEuMDA3IDIuMTg2IDIuNTE3IDIuNzEyLjU2LjE2Ni44NjcuMTk0Ljg2Ny4yMzd2MS4xNjNjLjAyOC4yNDktLjI1MS4zNi0uOTIzLjU1MyIgZmlsbD0iIzJlYWNlMyIvPjxwYXRoIGQ9Ik0xMS4xNzYgOC4zM2MtLjQwNiAwLS43ODUuMzAzLS43ODUuNzJ2MS4zMjhjMCAuMzg5LjM1LjcyMS43ODUuNzIxaDEuNDgyYy40MDYgMCAuNzg0LS4zMDQuNzg0LS43MlY5LjA1YzAtLjM4OC0uMzQ4LS43Mi0uNzg0LS43MnoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=
Telegramtelegram...
Travis CItravis...

如有任何疑问,请随时联系我们,祝您使用愉快!

Simple Icons 13

·阅读时间:1 分钟
chris48s
Shields.io 核心团队

Shields.io 上的徽标由 SimpleIcons 提供。我们最近升级到了 SimpleIcons 13。此版本删除了 65 个图标并重命名了一个图标。所有更改的完整列表可以在发行说明中找到。

请记住,我们只是 SimpleIcons 的用户。有关更改和删除的决定由SimpleIcons项目制定。

Simple Icons 12

·阅读时间:1 分钟
chris48s
Shields.io 核心团队

Shields.io 上的徽标由 SimpleIcons 提供。我们最近升级到 SimpleIcons 12。此版本删除了以下 10 个图标:

  • FITE
  • Flattr
  • Google Bard
  • Integromat
  • Niantic
  • 任天堂网络
  • 罗马
  • Shotcut
  • 天网
  • 推特

并重命名以下 3 个图标

  • Airbrake.io 改为 Airbrake
  • Amazon AWS 改为 Amazon Web Services
  • RStudio 改为 RStudio IDE

更多详情请参见发行说明

请记住,我们只是 SimpleIcons 的用户。有关更改和删除的决定由SimpleIcons项目制定。

Simple Icons 11

·阅读时间:1 分钟
chris48s
Shields.io 核心团队

Shields.io 上的徽标由 SimpleIcons 提供。我们最近升级到了 SimpleIcons 11。此版本移除了以下 4 个图标

  • Babylon.js
  • Hulu
  • 百事可乐
  • Uno

更多详情请参见发行说明

请记住,我们只是 SimpleIcons 的用户。有关更改和删除的决定由SimpleIcons项目制定。

Simple Icons 10

·阅读时间:1 分钟
chris48s
Shields.io 核心团队

Shields.io 上的徽标由 SimpleIcons 提供。我们最近升级到了 SimpleIcons 10。此版本移除了 45 个图标。完整的移除列表可以在发行说明中找到。

请记住,我们只是 SimpleIcons 的用户。有关更改和删除的决定由SimpleIcons项目制定。

对 GitHub 标签和发布徽章应用过滤器

·阅读时间:1 分钟
chris48s
Shields.io 核心团队

我们最近发布了一项功能,允许您将任意过滤器传递给 GitHub 标签和发布徽章。filter 参数可用于在从列表中选择最新标签或版本名称之前对项目标签或版本名称应用过滤器。可以使用两种结构:* 是匹配零个或多个字符的通配符,如果模式以 ! 开头,则整个模式将被否定。

为了举例说明这可能如何有用,我们在 GitHub 存储库上创建了两种类型的标签:https://github.com/badges/shields/tags 有一些标签的格式为 major.minor.patch,对应于我们的 NPM 软件包版本,以及格式为 server-YYYY-MM-DD 的标签,对应于我们的 Docker 快照版本

在我们的例子中,这将允许我们制作一个应用过滤器 !server-* 的徽章,以过滤掉快照标签并只选择最新的软件包标签。

我们推出了一个新的前端

·阅读时间:1 分钟
chris48s
Shields.io 核心团队

除了整体视觉刷新和外观改进之外,我们的新前端还让我们能够解决许多长期存在的特性请求和增强功能

  • 更清晰、更容易找到我们静态、动态 json/xml/yaml端点 徽章的文档
  • 改进的徽章构建器界面,所有可选查询参数都包含在每个徽章的构建器中
  • 每个徽章现在都有自己的文档页面,我们可以链接到该页面。例如:https://shieldsio.npmjs.net.cn/badges/discord
  • 浅色/深色模式主题
  • 改进的搜索
  • 单个路径和查询参数的文档

新站点还为核心团队带来了巨大的维护优势。我们严重依赖 docusaurusdocusaurus-openapidocusaurus-search-local。这使我们转向了主要声明式的设置,大大减少了我们自己维护的自定义前端代码量。