Visitar URL original
fix(search): require a search-only Algolia key at build time by julionav · Pull Request #266 · stackblitz/docs · GitHub
Skip to content

fix(search): require a search-only Algolia key at build time - #266

Draft
julionav wants to merge 2 commits into
mainfrom
cursor/algolia-search-only-key-8035
Draft

julionav wants to merge 2 commits into
mainfrom
cursor/algolia-search-only-key-8035

Conversation

@julionav

@julionav julionav commented Oct 5, 2026

Copy link
Copy Markdown

Summary of changes

Linear: BAC-1857. HackerOne: 3998832.

Problem

The docs site sends the Algolia API key to all visitors. This is necessary for DocSearch. But the key on developer.stackblitz.com is not a search-only key. Its ACL has write permissions: addObject, deleteObject, deleteIndex, editSettings. Any visitor can use the key to change or delete the stackblitz index.

The repository does not contain the key. The build gets the key from the Netlify variable VITE_ALGOLIA_KEY.

Also, Vite puts every VITE_* variable into the client bundle (the framework chunk), even when the code does not use that variable. Thus, if the old variable stays in Netlify, the old key continues to go to visitors.

Solution

  1. The build reads the key from a new variable, VITE_ALGOLIA_SEARCH_KEY.
  2. Before the build uses the key, it sends one read-only request, GET /1/keys/<key>. Algolia lets each key read its own ACL. If the ACL is not exactly ["search"], the build fails. If the request fails (for example, HTTP 403 for a key that is not valid), the build fails.
  3. If the old variable VITE_ALGOLIA_KEY is set, the build fails. This prevents the old key in the bundle.
  4. A new optional variable, VITE_ALGOLIA_INDEX, sets the index name. The default is stackblitz.
  5. If no Algolia variables are set, the build passes without a search box. This is the same as before.

The guard is strict on purpose. Read-only extras such as listIndexes and settings also make the build fail.

Implementation details

  • .vitepress/config.ts: getSearchConfig is now async and the config uses await. The new function assertSearchOnlyKey does the ACL check.
  • README.md: the variable list shows the new names. It also tells you not to put secrets in VITE_* variables.

How to reproduce the problem (BEFORE)

Use only read-only requests. Do not write to the index.

  1. Get the page and its scripts: curl -s https://developer.stackblitz.com/guides/user-guide/what-is-stackblitz, then get each /assets/*.js file in the page.
  2. Search the output for VITE_ALGOLIA_KEY and apiKey. The result shows app YCVDUYWLVC and a key that starts with 8fe79cd8.
  3. Read the ACL of the key: curl -s -H "X-Algolia-Application-Id: YCVDUYWLVC" -H "X-Algolia-API-Key: $KEY" https://YCVDUYWLVC-dsn.algolia.net/1/keys/$KEY.
  4. The ACL has write permissions.

BEFORE: key in live page source (masked)

BEFORE: ACL of the live key

Build checks (AFTER)

We did not create a key on app YCVDUYWLVC, because that is a write operation. The checks use public keys from other projects:

  • Search-only key: the public Vitest DocSearch key (app ZTF29HGJ69, index vitest). Its ACL is ["search"].
  • Key with extra ACLs: the public Vue docs key (app ML0LEBN7FQ). Its ACL is ["search","listIndexes","settings"].

Commands (keys are masked to 8 characters):

# A: key with extra ACLs -> FAIL
$ VITE_ALGOLIA_ID=ML0LEBN7FQ VITE_ALGOLIA_SEARCH_KEY=10e7a8b1… npm run build
Error: VITE_ALGOLIA_SEARCH_KEY must have only the "search" ACL, got ["search","listIndexes","settings"].
exit code: 1

# B: invalid key -> FAIL
$ VITE_ALGOLIA_ID=ZTF29HGJ69 VITE_ALGOLIA_SEARCH_KEY=00000000… npm run build
Error: Could not verify VITE_ALGOLIA_SEARCH_KEY permissions (HTTP 403).
exit code: 1

# C: old variable still set -> FAIL
$ VITE_ALGOLIA_KEY=deadbeef… npm run build
Error: VITE_ALGOLIA_KEY must not be set: it is shipped in the bundle. Use VITE_ALGOLIA_SEARCH_KEY.
exit code: 1

# D: no Algolia variables -> PASS (no search box)
$ npm run build
build complete in 4.22s.
exit code: 0

# E: search-only key -> PASS
$ VITE_ALGOLIA_ID=ZTF29HGJ69 VITE_ALGOLIA_SEARCH_KEY=9c3ced6f… VITE_ALGOLIA_INDEX=vitest npm run build
build complete in 4.70s.
exit code: 0

# Bundle scan of build/ after E
$ grep -rl 8fe79cd8 build | wc -l     # old production key prefix
0
$ grep -rl VITE_ALGOLIA_KEY build | wc -l
0
$ grep -rl 9c3ced6f build | wc -l     # search-only key, public by design
72

npx prettier --check .vitepress/config.ts README.md passes.

AFTER: build guard checks and bundle scan

Search works with a search-only key. For this screenshot only, we changed lang to en, because the Vitest index uses lang: en and the site sends lang:en-US. We did not commit this change.

AFTER: local search works with a search-only key

Ops steps (necessary — this PR alone does not stop the leak)

The old key is public now and must be deleted. Do these steps in this sequence:

  1. In the Algolia dashboard (app YCVDUYWLVC), create a new API key. Give it only the search ACL. Limit it to the stackblitz index.
  2. In Netlify (site for developer.stackblitz.com), add VITE_ALGOLIA_SEARCH_KEY with the new key.
  3. In Netlify, delete the variable VITE_ALGOLIA_KEY. If you do not, the build fails (check C).
  4. Merge this PR. Make sure that the production deploy passes.
  5. In the Algolia dashboard, delete the old key (starts with 8fe79cd8).
  6. Make sure that the old key does not work: GET /1/keys/<old key> must return HTTP 403.
  7. Do the BEFORE steps again on production. The page source must not contain 8fe79cd8. The ACL of the new key must be ["search"].

Also examine the Algolia index and settings for changes that you did not expect. The old key had write access for a long time (created 2021-12-07).

Note

We used only read-only Algolia requests: GET /1/keys and search. We did not write to, delete, or change any index or setting.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 2 commits October 5, 2026 19:49
Co-authored-by: Julio Navarro <julionav@users.noreply.github.com>
Co-authored-by: Julio Navarro <julionav@users.noreply.github.com>
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@stackblitz-staging

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

@codex review

@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

@greptile review

@netlify

netlify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

❌ Deploy Preview for stackblitz-docs failed. Why did it fail? →

Name Link
🔨 Latest commit fbab885
🔍 Latest deploy log https://app.netlify.com/projects/stackblitz-docs/deploys/6ac3fff9a5a0b800085f649a

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants