ci(docs): Add changed docs preview links#18413
Conversation
Post direct preview URLs for docs pages changed by a PR after a successful Vercel preview deployment. Use the generated doctree source paths so shared common pages can show affected rendered URLs without requiring reviewers to click around.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| } | ||
|
|
||
| interface DocTreeNode { | ||
| children?: DocTreeNode[]; |
There was a problem hiding this comment.
Fork-controlled code executes with write-scoped GITHUB_TOKEN via deployment_status checkout
The deployment_status-triggered workflow checks out the deployed commit (a fork PR head when Vercel deploys fork PRs) with no ref pinning, then runs pnpm install --frozen-lockfile and a TypeScript script from that untrusted tree while holding a GITHUB_TOKEN with issues: write, letting a fork contributor run arbitrary code on the runner and post deceptive bot comments. Pin checkout to a trusted ref (e.g. the base SHA) and avoid running untrusted install hooks/scripts under a write-scoped token.
Evidence
- Trigger is
deployment_status(a privileged trigger that runs in the base-repo context); theifonly filters on deployment state/environment, not on trust of the source. actions/checkoutat line 20 of.github/workflows/docs-preview-links.ymlhas noref:override, so fordeployment_statusit checks outgithub.sha, the deployed commit — the fork PR head when Vercel deploys fork PRs.pnpm install --frozen-lockfile(line 30) runs against the fork-controlled tree;--frozen-lockfiledoes not disablepreinstall/postinstalllifecycle scripts, so a maliciouspackage.jsonexecutes arbitrary commands.pnpm exec tsx scripts/docs-preview-links.ts(line 32) then executes fork-controlled script source.- The job token has
issues: write, so attacker code can post/edit PR/issue comments as the bot; no broader secrets are present, bounding impact.
Identified by Warden security-review · 6D6-WYQ
|
|
||
| - run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Post changed docs preview links |
There was a problem hiding this comment.
PR-author doc frontmatter injected unsanitized into bot PR comment markdown (link spoofing)
renderPreviewComment interpolates PR-author-controlled frontmatter.title and node.path directly into the markdown link text/target of the github-actions bot comment without escaping, so a crafted title like foo](https://attacker.com) [x renders a spoofed link inside an otherwise-trusted bot comment to phish reviewers. Escape ], (, ) and backticks in title/path before interpolation.
Evidence
- Workflow
docs-preview-links.ymlrunsscripts/docs-preview-links.tsondeployment_statussuccess and posts a comment viaissues: write. fetchDocTrees(previewUrl)loadsdoctree.json, whosefrontmatter.titleandpathcome from the PR author's.md/.mdxsource.buildSourcePathIndexstoresnode.frontmatter?.titleverbatim andnormalizePagePathonly trims slashes.renderPreviewCommentemits- [${formatPageLabel(page)}](${page.url})withformatPageLabel=${page.title} - /${page.path}/, so]/(/)in title breaks out of the link and injects an attacker-controlled markdown link.- Impact is bounded: GitHub sanitizes markdown HTML (no script execution) and the PR author can already comment directly, so this is link/content spoofing in a bot comment rather than XSS or privileged action.
Identified by Warden security-review · 3EJ-ELU
DESCRIBE YOUR PR
Adds a GitHub Actions workflow that listens for successful Vercel preview deployments, resolves the related PR, and posts one stable bot comment with direct preview links for changed docs pages.
The script uses the generated doctree source paths to map changed
docs/anddevelop-docs/files to rendered preview URLs. Shared/common docs are grouped and capped so reviewers get useful links without an enormous comment. Include-only files are listed separately when they do not map directly to a public page.IS YOUR CHANGE URGENT?
Help us prioritize incoming PRs by letting us know when the change needs to go live.
SLA
Thanks in advance for your help!
PRE-MERGE CHECKLIST
Make sure you've checked the following before merging your changes:
Test Plan
pnpm test scripts/docs-preview-links.spec.tspnpm exec eslint scripts/docs-preview-links.ts scripts/docs-preview-links.spec.tspnpm exec prettier --check scripts/docs-preview-links.ts scripts/docs-preview-links.spec.ts .github/workflows/docs-preview-links.ymlpnpm exec tsc --noEmit --skipLibCheck --target ESNEXT --module commonjs --lib dom,esnext --types node --moduleResolution node --esModuleInterop scripts/docs-preview-links.tsLEGAL BOILERPLATE
Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
EXTRA RESOURCES