fix(figma): make preview share token read-only; keep a private edit token#75
Open
piaskowyk wants to merge 1 commit into
Open
fix(figma): make preview share token read-only; keep a private edit token#75piaskowyk wants to merge 1 commit into
piaskowyk wants to merge 1 commit into
Conversation
…oken The Figma plugin used a single token as both the read key (embedded in the preview share URL) and the write key (PUT config / PATCH visibility). Anyone handed the preview link could therefore modify or delete the project. Split it into two secrets per project: - edit token (private): the owner's secret, stored only in the plugin's clientStorage. Grants writes (PUT/PATCH) and the owner read. Never put in a URL. - public token (read-only): the only token in share links, QR codes and deep links. Reads through GET /figma-project/public/:publicToken, which honours visibility (403 when revoked) and can never modify. Server: add an indexed public_token column, backfilled = token for pre-split rows so already-distributed links keep working; new owner vs. public read routes; POST returns both tokens. Plugin: persist both tokens per file, build every share URL from the public token, recover the public token from the server for legacy shares. Preview app: read through the public route. Tests: cover the split end-to-end — a public-token holder gets 404 on PUT and PATCH (cannot edit or revoke), the owner read still serves config while private, and the migration backfill is exercised directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
54c1e0d to
b50c877
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Figma plugin used a single token as both the read key (embedded in the preview share URL) and the write key (
PUTconfig /PATCHvisibility). Handing the preview link to anyone gave them full edit/delete rights over the project.Fix
Split the token into two secrets per project:
PUT/PATCH) and the owner read. Stored only in the plugin'sclientStorage; never put in a URL.GET /figma-project/public/:publicToken, which honours visibility (403 when revoked) and can never modify the project.Only the designer who created the project (and holds the edit token) can modify it; anyone with the public token can read only.
Changes by layer
Server (
docs/server)public_tokencolumn;createFigmaProjectgenerates two distinct tokens.GET /figma-project/public/:publicToken— read-only share path, enforcesis_public.GET /figma-project/:token— owner read by edit token; serves config even when private and returns thepublicToken.PUT/PATCH …/visibilityunchanged — still keyed on the secret edit token.public_tokenbackfilled= tokenfor pre-split rows so already-distributed links keep working.Plugin (
figma/src) — stores both tokens per file, builds every share URL / deep link / "copy token" from the public token, recovers the public token from the server for legacy shares.Preview (
figma/preview) — reads through the public route. The mobile app needed no change (it forwards whatever token the QR/deep link carries, now the public one).Tests
84/84 server tests pass. New coverage proves the security boundary end-to-end:
PUTandPATCH(cannot edit or revoke the link); project verified untouched.WHERE public_token IS NULLguard) is exercised directly.Caveat
Links already shared before this change remain writable — their token is both edit and public, and it can't be rotated without breaking the owner who still holds it. Every project created from now on is secure. Documented in
figma/AGENT_CONTEXT.md.