其他 · 2026年3月14日

39个Algolia Admin Key裸奔在开源文档里:你的前端搜索配置可能是个后门

用Algolia DocSearch做文档搜索的前端项目多了去了。Vue.js、Home Assistant、KEDA……这些你每天查文档的站点,搜索框背后的API Key可能正以admin权限暴露在前端代码里。

上周一个安全研究员Ben Zimmermann公布了他的发现:扫描了15000个文档站点后,找到39个拥有完整admin权限的Algolia API Key。这些Key能干什么?添加、修改、删除索引记录,甚至直接把整个搜索索引清空。

DocSearch的机制和问题根源

Algolia的DocSearch是个免费服务——它帮开源项目爬站点、建索引、提供搜索。接入方式很简单,前端嵌一段JS,传入appId和apiKey就能用。

正常流程是这样的:Algolia给你两个Key,一个search-only用于前端,一个admin用于爬虫和索引管理。前端代码里只该出现search-only Key。

问题出在”自建爬虫”这条路上。DocSearch官方有个run your own crawler的文档,很多团队选择自己跑爬虫。一跑就需要admin Key,然后这个Key就在配置文件里待着了。有人图省事直接把admin Key塞进前端配置,有人把Key提交到了Git历史里。

典型的前端接入代码长这样:

docsearch({
  appId: 'BH4D9OD16A',
  apiKey: '5990ad008512000bba2cf951ccf0332f',  // 这个该是search-only
  indexName: 'my-docs',
  container: '#search'
})

search-only Key和admin Key长得一模一样——都是32位十六进制字符串。肉眼看不出区别,只有在Algolia后台的权限页面才能确认。这就是问题所在:很多开发者根本没验证过自己前端用的到底是哪个Key。

怎么找到这些Key的

Ben的方法分三步,每一步都值得前端开发者了解。

第一步:从DocSearch配置库批量抓目标。Algolia官方有个已归档的docsearch-configs仓库,里面收录了3500+个使用DocSearch的站点配置。这就是现成的扫描目标列表。

第二步:前端代码扫描。用正则从网页源码中提取Algolia凭据:

import re

# appId是10位大写字母+数字
APP_RE = re.compile(r'["']([A-Z0-9]{10})["']')
# apiKey是32位十六进制
KEY_RE = re.compile(r'["']([\da-f]{32})["']')
# 先确认页面包含Algolia相关代码
ALGOLIA_RE = re.compile(r'algolia|docsearch', re.I)

def extract(text, app_ids, api_keys):
    if not ALGOLIA_RE.search(text):
        return
    for a in APP_RE.findall(text):
        app_ids.add(a)
    api_keys.update(KEY_RE.findall(text))

39个admin Key中有35个来自前端代码扫描。这些Key没有出现在任何Git仓库里——它们是构建时注入的,只有在部署后的网页源码中才能看到。

第三步:Git历史挖掘。对500多个文档站点的代码仓库跑TruffleHog,从Git历史中挖出被提交后又删除的Key。另外4个admin Key就是这么找到的。

受影响的项目有多大

部分受影响项目(数据来自原文):

项目 GitHub Stars 说明
Home Assistant 85,000+ 数百万活跃安装
Vue.js 48,000+ 已修复并轮换Key
KEDA CNCF项目 生产级Kubernetes集群在用
vcluster Kubernetes基础设施 搜索索引超10万条记录
SUSE/Rancher 企业级 2天内响应并轮换

Vue.js是最先被发现的。Ben去年10月就报告了,Vue团队轮换了Key,并把他加进了安全名人堂。问题是这激发了他的好奇心——既然Vue有这问题,别的项目呢?

这些Key能造成什么破坏

几乎所有39个Key都有同一组权限:search、addObject、deleteObject、deleteIndex、editSettings、listIndexes、browse。部分Key甚至额外包含analytics和logs权限。

拿到这种Key可以:

const algoliasearch = require('algoliasearch')
const client = algoliasearch('APP_ID', 'LEAKED_ADMIN_KEY')
const index = client.initIndex('docs')

// 1. 往搜索索引里插入恶意记录
await index.saveObject({
  objectID: 'malicious-1',
  title: 'Quick Start Guide',
  url: 'https://phishing-site.com/install.sh',  // 钓鱼链接
  content: 'Run this command to get started...'
})

// 2. 修改已有记录的链接
await index.partialUpdateObject({
  objectID: 'existing-doc-123',
  url: 'https://evil-cdn.com/compromised-package.tar.gz'
})

// 3. 核弹选项——直接删掉整个索引
await index.delete()

想象一下:某个知名开源项目的文档搜索结果被替换成钓鱼链接。用户搜”安装指南”,点进去看到的是一段恶意脚本。这不是理论攻击——前面的RAG投毒本质上就是类似的思路,只不过Algolia这条路更简单粗暴。

前端开发者该怎么检查自己的项目

如果你的项目用了Algolia或DocSearch,现在就该检查。

方法一:查看Algolia控制台

登录Algolia后台 → Settings → API Keys。找到你前端代码里用的那个Key,看它的ACL(Access Control List)。如果只有search权限,没问题。如果你看到addObject、deleteObject、deleteIndex这些权限——立即轮换。

方法二:用API直接检测

# 用你前端的appId和apiKey测试写入权限
curl -s -X POST "https://APP_ID-dsn.algolia.net/1/indexes/test_probe/query"   -H "X-Algolia-Application-Id: APP_ID"   -H "X-Algolia-API-Key: YOUR_FRONTEND_KEY"   -d '{"query":"test"}'

# 如果下面这个请求成功了,说明Key有写权限——危险!
curl -s -X POST "https://APP_ID.algolia.net/1/indexes/test_probe"   -H "X-Algolia-Application-Id: APP_ID"   -H "X-Algolia-API-Key: YOUR_FRONTEND_KEY"   -H "Content-Type: application/json"   -d '{"objectID":"probe","test":true}'
# 成功=你的Key权限太大了
# 403/401=Key是search-only,安全

方法三:扫描你的构建产物

#!/bin/bash
# 在构建产出目录里扫描可能的Algolia凭据
echo "扫描构建产出中的Algolia Key..."

# 找所有JS文件中的32位十六进制字符串
grep -rPoh '["'][0-9a-f]{32}["']' dist/ build/ .next/ 2>/dev/null |   sort -u | while read key; do
    clean=$(echo "$key" | tr -d ""'")
    echo "发现候选Key: $clean"
    echo "  → 请到Algolia后台确认该Key的权限级别"
done

正确的接入方式

如果你要自建DocSearch爬虫,Key的管理要做到分离:

# .env(爬虫用,绝对不提交到Git)
ALGOLIA_ADMIN_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# 前端配置(可以提交,可以暴露)
NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=yyyyyyyyyyyyyyyyyyyyyyyy
NEXT_PUBLIC_ALGOLIA_APP_ID=XXXXXXXXXX
// 前端代码——只用search Key
import algoliasearch from 'algoliasearch/lite'  // 注意用lite版

const searchClient = algoliasearch(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY  // search-only!
)

几个硬性规则:

  • 前端永远用algoliasearch/lite——这个包本身就只支持搜索操作,就算Key权限大也限制了客户端能调用的API
  • .env里的admin Key加到.gitignore,CI/CD里用Secret注入
  • Algolia后台定期Review API Key列表,删掉不用的Key
  • 如果用GitHub Actions跑爬虫,admin Key放在Repository Secrets里,别写进workflow YAML

Algolia的态度让人失望

Ben给Algolia发了完整的Key列表和受影响项目清单。几周过去了,没有回复。截至文章发布时,除了Vue.js和SUSE/Rancher主动修复的之外,其余Key全部仍然有效。

这其实暴露了一个更深层的问题:Algolia的DocSearch项目设计上没有做足防错。它完全依赖用户自己区分search Key和admin Key,但这两种Key在格式上毫无差别。一个简单的改进是:在Dashboard上对admin Key加醒目警告”此Key不应用于前端”,或者在检测到admin Key被用于搜索请求时发邮件告警。

对前端开发者来说,教训很明确:任何出现在前端代码、构建产物、或公开仓库中的API Key,必须是最小权限的。不只是Algolia——Firebase、Supabase、Stripe publishable key、Mapbox token,所有前端可见的凭据都该检查一遍权限范围。

原始研究来源:I Found 39 Algolia Admin Keys Exposed Across Open Source Documentation Sites