Summary
An outside contributor can open a pull request against this repo and have their code built and deployed to an Amplify preview automatically, before any maintainer reviews or approves the run.
The preview deploy is triggered by AWS Amplify's own GitHub App, not by a GitHub Actions workflow. GitHub's "require approval to run workflows for fork PRs" setting only gates Actions runs, so it does not cover the Amplify preview path. That is why these deploys happen with no approval step.
The build runs untrusted code. amplify.yml runs pnpm install --frozen-lockfile and pnpm build on whatever the PR contains. Package lifecycle scripts and the docs build both execute contributor-authored code inside Amplify's build environment. Any secrets or IAM permissions attached to that environment are reachable by that code. The output is also served from a Deque-controlled preview domain.
We want previews to deploy automatically for pull requests opened by people inside Deque, and not to deploy contributor code from outside Deque without an explicit, human approval.
Acceptance criteria
- A pull request opened by a Deque org member deploys a docs preview automatically, with no manual step.
- A pull request opened by an outside contributor does not deploy a preview automatically.
- No deploy credentials are exposed to code from an outside contributor's pull request.
- There is a documented way for a maintainer to approve a preview for a specific outside pull request after reviewing the diff (for example a label a maintainer applies).
CONTRIBUTING.md is updated to describe the new preview behavior. The current text at CONTRIBUTING.md:213 says previews deploy with each commit to a PR, which will no longer be true for outside contributors.
- The state of Amplify's native pull request previews is settled deliberately. They were turned off as an interim mitigation (see below). If the fix replaces them with a gated Actions workflow, they stay off, and that decision is recorded. If the fix does not provide previews another way, re-enable them in the Amplify Console only after the outside-contributor gate is in place, so the repo is not left with previews on and no gate. The preview that was disabled is for the develop branch, and you can see it here in the AWS console.
Interim mitigation (already applied)
Amplify pull request previews were disabled to stop the exposure while this ticket is open. In the Amplify Console, under Hosting then Previews, "Pull request previews" was turned off on the develop branch. That is the one rule governing all PRs into develop. The develop branch build is unaffected, so the live docs site still deploys. This is why the AC above asks whoever implements the fix to decide the final state of Amplify previews rather than assume they should go back on.
Out of scope
- Auditing what secrets or IAM permissions the current Amplify build environment actually holds. That is worth doing separately and would inform how urgent this is.
Dev notes (implementation findings so far)
Current state
amplify.yml is the only Amplify config in the repo. It is a standard Amplify Console build spec. It builds the docs site (artifacts.baseDirectory: docs/dist) via pnpm install --frozen-lockfile then pnpm build. It is referenced by no GitHub Actions workflow.
- None of the 13 workflows in
.github/workflows/ deploy to Amplify, post a preview URL, use pull_request_target, or check github.event.pull_request.head.repo.fork.
- The preview flow lives entirely in AWS Amplify's GitHub App integration, configured in the Amplify Console, not in this repo.
CONTRIBUTING.md:213 documents the current behavior: previews deploy "with each commit to a PR," and the aws-amplify bot posts the link.
Why the existing GitHub gate does not help
GitHub's fork-PR approval setting only gates GitHub Actions workflow runs. The Amplify GitHub App is a separate integration that reacts to PR webhooks on its own. So that setting never sees the preview deploy.
Proposed approach
Move the preview deploy off Amplify's native GitHub App trigger and into a gated GitHub Actions workflow.
- Turn off automatic PR previews in the Amplify Console so the native trigger stops firing. This is an AWS console change, not a repo change.
- Add an Actions workflow on the plain
pull_request trigger. Do not use pull_request_target, which would hand secrets to fork code and is the usual source of exploits in this pattern.
- Keep the AWS deploy credentials in a GitHub Environment rather than plain repo secrets.
- Gate the deploy on the PR author's relationship to the repo. The webhook payload exposes
github.event.pull_request.author_association. Deploy only when it is one of OWNER, MEMBER, COLLABORATOR. Skip otherwise.
- With the
pull_request trigger, GitHub already withholds secrets from fork PRs by default, so the author-association check is a second layer rather than the only one.
- For the maintainer-approved outside preview, gate on a label a maintainer applies only after reading the diff. This mirrors GitHub's own "approve to run" idea and keeps a human in front of any untrusted deploy.
Known edges to decide during implementation
author_association describes who opened the PR, not who authored each commit. A member could open a PR whose branch contains outside-authored commits, and it would still deploy. The accountable party is the member who opened it, which is usually the right trust boundary. Stricter handling is possible but should not be the starting point.
- An internal contributor who works from their own fork would be blocked by a fork-only check, which is why the author-association signal is preferred over a fork check.
Requires access outside this repo
- AWS Amplify Console access to disable the native auto-preview.
- GitHub org and repo admin access to set the Environment, its required reviewers, and the outside-collaborator approval setting.
Summary
An outside contributor can open a pull request against this repo and have their code built and deployed to an Amplify preview automatically, before any maintainer reviews or approves the run.
The preview deploy is triggered by AWS Amplify's own GitHub App, not by a GitHub Actions workflow. GitHub's "require approval to run workflows for fork PRs" setting only gates Actions runs, so it does not cover the Amplify preview path. That is why these deploys happen with no approval step.
The build runs untrusted code.
amplify.ymlrunspnpm install --frozen-lockfileandpnpm buildon whatever the PR contains. Package lifecycle scripts and the docs build both execute contributor-authored code inside Amplify's build environment. Any secrets or IAM permissions attached to that environment are reachable by that code. The output is also served from a Deque-controlled preview domain.We want previews to deploy automatically for pull requests opened by people inside Deque, and not to deploy contributor code from outside Deque without an explicit, human approval.
Acceptance criteria
CONTRIBUTING.mdis updated to describe the new preview behavior. The current text atCONTRIBUTING.md:213says previews deploy with each commit to a PR, which will no longer be true for outside contributors.Interim mitigation (already applied)
Amplify pull request previews were disabled to stop the exposure while this ticket is open. In the Amplify Console, under Hosting then Previews, "Pull request previews" was turned off on the
developbranch. That is the one rule governing all PRs intodevelop. Thedevelopbranch build is unaffected, so the live docs site still deploys. This is why the AC above asks whoever implements the fix to decide the final state of Amplify previews rather than assume they should go back on.Out of scope
Dev notes (implementation findings so far)
Current state
amplify.ymlis the only Amplify config in the repo. It is a standard Amplify Console build spec. It builds the docs site (artifacts.baseDirectory: docs/dist) viapnpm install --frozen-lockfilethenpnpm build. It is referenced by no GitHub Actions workflow..github/workflows/deploy to Amplify, post a preview URL, usepull_request_target, or checkgithub.event.pull_request.head.repo.fork.CONTRIBUTING.md:213documents the current behavior: previews deploy "with each commit to a PR," and theaws-amplifybot posts the link.Why the existing GitHub gate does not help
GitHub's fork-PR approval setting only gates GitHub Actions workflow runs. The Amplify GitHub App is a separate integration that reacts to PR webhooks on its own. So that setting never sees the preview deploy.
Proposed approach
Move the preview deploy off Amplify's native GitHub App trigger and into a gated GitHub Actions workflow.
pull_requesttrigger. Do not usepull_request_target, which would hand secrets to fork code and is the usual source of exploits in this pattern.github.event.pull_request.author_association. Deploy only when it is one ofOWNER,MEMBER,COLLABORATOR. Skip otherwise.pull_requesttrigger, GitHub already withholds secrets from fork PRs by default, so the author-association check is a second layer rather than the only one.Known edges to decide during implementation
author_associationdescribes who opened the PR, not who authored each commit. A member could open a PR whose branch contains outside-authored commits, and it would still deploy. The accountable party is the member who opened it, which is usually the right trust boundary. Stricter handling is possible but should not be the starting point.Requires access outside this repo