1"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[2468],{22372:function(e,t,n){n.r(t),n.d(t,{Head:function(){return f},default:function(){return m}});var r=n(28453),a=n(96540);function l(e){const t=Object.assign({h1:"h1",a:"a",span:"span",p:"p",h2:"h2",ul:"ul",li:"li",ol:"ol"},(0,r.R)(),e.components);return a.createElement(a.Fragment,null,a.createElement(t.h1,{id:"pro-review-app-security",style:{position:"relative"}},a.createElement(t.a,{href:"#pro-review-app-security","aria-label":"pro review app security permalink",className:"anchor before"},a.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Pro Review App Security"),"\n",a.createElement(t.p,null,"React on Rails Pro review apps follow the same baseline rule as open-source review apps: deployed pull request code is\ncode execution. For public repositories, fork pull request review apps must be opt-in by a trusted maintainer and must\nrun with disposable resources."),"\n",a.createElement(t.h2,{id:"license-tokens",style:{position:"relative"}},a.createElement(t.a,{href:"#license-tokens","aria-label":"license tokens permalink",className:"anchor before"},a.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"License Tokens"),"\n",a.createElement(t.p,null,"Do not expose a production license token to fork pull request review-app builds or runtime by default, whether it comes\nfrom ",a.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">REACT_ON_RAILS_PRO_LICENSE</code>'}}),", Rails credentials, or the Node renderer's ",a.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">licenseToken</code>'}})," configuration. React on\nRails Pro needs no license key in any non-production environment. Review apps should run without a key unless there is\na deliberate reason to test license status handling."),"\n",a.createElement(t.p,null,"If a review app must validate license behavior:"),"\n",a.createElement(t.ul,null,"\n",a.createElement(t.li,null,"use a revocable non-production license token;"),"\n",a.createElement(t.li,null,"restrict the deployment to trusted maintainers;"),"\n",a.createElement(t.li,null,"keep the token out of ordinary fork PR workflows;"),"\n",a.createElement(t.li,null,"rotate the token if deployed pull request code is suspected of reading or exfiltrating it."),"\n"),"\n",a.createElement(t.h2,{id:"node-renderer-and-rsc-credentials",style:{position:"relative"}},a.createElement(t.a,{href:"#node-renderer-and-rsc-credentials","aria-label":"node renderer and rsc credentials permalink",className:"anchor before"},a.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Node Renderer And RSC Credentials"),"\n",a.createElement(t.p,null,"Renderer passwords, RSC URLs, Redis URLs, and internal service URLs are application runtime credentials. They can protect\ninternal service boundaries from unrelated traffic, but they do not protect secrets from the pull request code running\ninside the same review app."),"\n",a.createElement(t.p,null,"For Pro review apps:"),"\n",a.createElement(t.ul,null,"\n",a.createElement(t.li,null,"run Rails, client bundles, server bundles, RSC bundles, and the Node renderer in production-like mode;"),"\n",a.createElement(t.li,null,"keep renderer and Redis services inside the same isolated review environment;"),"\n",a.createElement(t.li,null,"avoid sharing renderer passwords, Redis databases, or cache stores with staging or production;"),"\n",a.createElement(t.li,null,"avoid mounting error-reporting, package-registry, SSH, or cloud-provider credentials into the app containers."),"\n"),"\n",a.createElement(t.h2,{id:"public-fork-pull-requests",style:{position:"relative"}}
1,a.createElement(t.a,{href:"#public-fork-pull-requests","aria-label":"public fork pull requests permalink",className:"anchor before"},a.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Public Fork Pull Requests"),"\n",a.createElement(t.p,null,"A maintainer comment or manual workflow dispatch can be a reasonable escape hatch for a forked pull request, but that\napproval means the maintainer is choosing to run untrusted code with the review-app deployment credential. Keep that\ncredential scoped to review apps only. It must not be able to read production secrets, manage production workloads, or\npromote staging to production."),"\n",a.createElement(t.p,null,"The recommended model is:"),"\n",a.createElement(t.ol,null,"\n",a.createElement(t.li,null,"Same-repository pull requests may auto-deploy when the repository team trusts that workflow."),"\n",a.createElement(t.li,null,"Fork pull requests run CI without secrets."),"\n",a.createElement(t.li,null,"A maintainer may trigger a review app after inspecting the change."),"\n",a.createElement(t.li,null,"The review app uses disposable databases and non-sensitive secrets only."),"\n",a.createElement(t.li,null,"Cleanup runs on pull request close and on a scheduled stale-app sweep."),"\n"),"\n",a.createElement(t.p,null,"See the open-source ",a.createElement(t.a,{href:"/linked-assets/7351d0b7fb98f9692df4cdced5b4f441/review-app-security.md"},"Review App Security")," page for the shared baseline."))}var i=function(e){void 0===e&&(e={});const{wrapper:t}=Object.assign({},(0,r.R)(),e.components);return t?a.createElement(t,e,a.createElement(l,e)):l(e)},s=n(63679),o=n(95197),c=n(47388),d=n(23690),u=n(14487);const p=s.default.p.withConfig({displayName:"doc-article__RedirectFallback",componentId:"sc-tic2w5-0"})(["padding:2rem;"]),h=e=>{let{data:t,location:n,children:r}=e;const{headings:l}=t.article.childMdx,i=(0,o.X9)(n.pathname),[s,d]=a.useState(null),h=n.pathname.split("/"),m=h.indexOf("docs"),f=-1===m?n.pathname.length:h.slice(0,m+1).join("/").length,v=n.pathname.slice(0,f),g=n.pathname.slice(f+1).replace(/\/$/,"").split("/").filter((e=>""!==e)),w=g.length>1?g.slice(0,-1).join("/"):"";a.useEffect((()=>{if(!i)return;const{hash:e}=window.location;d(e);const t=""+i+e;window.location.href!==t&&window.location.replace(t)}),[i]);const E=null===i||null===s?null:""+i+s;return a.createElement(a.Fragment,null,null!==E?a.createElement(p,{role:"status","aria-live":"polite"},"Redirecting..."," ",a.createElement("a",{href:E,target:"_blank",rel:"noopener noreferrer"},"Click here if not redirected.")):a.createElement(c.A,{main:a.createElement(u.A,{body:r,headings:l,transformUrl:e=>{if(e.startsWith("http")||e.startsWith("#"))return e;const t=e.replace(/\.md$/,"/");if(t.startsWith("./"))return v+(""===w?"":"/"+w)+t.slice(1);if(t.startsWith("../")){if(""===w)return""+v+t.slice(2);const e=w.split("/").slice(0,-1).join("/");return v+(""===e?"":"/"+e)+t.slice(2)}return v+"/"+(""===w?"":w+"/")+t}})}))};function m(e){return a.createElement(h,e,a.createElement(i,e))}const f=e=>{let{data:t,location:n,pageContext:r}=e;const{headings:l}=t.article.childMdx,{siteUrl:i}=t.site.siteMetadata,{repoDisplayName:s}=r,c=l.find((e=>1===e.depth)),u=(0,o.X9)(n.pathname)||""+i.replace(/\/+$/,"")+n.pathname;return a.createElement(d.A,{title:c?c.value:s,description:c?c.value:s+" documentation",isArticle:!0,canonical:u,pathname:n.pathname})}}}]); 2//# sourceMappingURL=component---src-template-doc-article-tsx-content-file-path-cache-gatsby-source-git-react-on-rails-docs-pro-deployment-review-app-security-md-6c52e527e4a320812739.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.