Announcing Beacon: Self-improving memory for coding agents
← All skills
Skill

implement-rfc

skill:remix-run/react-router#implement-rfc

Implement a React Router RFC from a GitHub discussion URL. Fetches the proposal, evaluates community feedback, resolves outstanding questions interactively, then implements the feature with tests, future flags (if breaking), and a changeset.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 27, 2026, 22:00 UTC at 959182e

Dispute security verdict

If you believe this verdict is incorrect, submit a dispute and we'll review it.

1
findings
high
highest severity
1
threat classes
1,314
files scanned
3,605/3,605
checks satisfied
0
package advisories

Why this verdict

  • suspicious: finding skill:.agents/skills/implement-rfc:packages/react-router/lib/router/router.ts:87:EXEC

Security findings 1

Code execution

highContextual risklow confidence

The router.ts flagged span embeds an opaque base64url blob (beginning pZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo) as the head of a hidden/encoded channel, surrounded only by ordinary router implementation comments with no string-literal assignment, label, test fixture, or executable use shown, leaving an unclassified concealed payload in a core routing module consumed by every build.

pZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM
conceal:encodingvector:code
Counter-argument considered

The decoded channel verbatim opens with an opaque base64url blob embedded among ordinary router comments with no assignment, label, or consumer shown; concealment in a core module is outside every carve-out and undeclared by the skill's RFC-implementation description, so the finding stands as contextual risk, while no executable sink is evidenced so chain fails without refuting.

Open questions 20

What the analysis could not settle from the code alone.

Detector leads (PY-CLAIM-RESIDUE) flag env-var reads (npm_config_user_agent, IS_RR_BUILD_REQUEST, NODE_ENV), a recursive file copy in vite/plugin.ts, a placeholder test URL, and a cookies module import in repository source files whose cited lines are not included among this pass's owed units; whether these constitute undeclared capabilities should be settled by the declared-vs-actual or behavior-chains passes.
Detector lead DET:36e832fe70d4ea8c flags an undeclared env read 'process.env.REACT_ROUTER_ROOT' in packages/react-router-dev/vite/plugin.ts (line 1275); that file is not among the units shown, so whether this capability is part of the declared implement-RFC task could not be verified in this pass.
Credential access
Detector lead DET:4f43490065d3bc84 flags an undeclared env read 'process.env.IS_RR_BUILD_REQUEST' in packages/react-router-dev/vite/plugin.ts (line 1807); that file is not among the units shown, so the purpose and reach of this env read could not be verified in this pass.
Credential access
The head of decoded unit SRC:b3523bd2520eb9bf begins with a ~140-character base64url string ('pZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM') whose meaning cannot be settled from the evidence shown; it may be an extraction/shard fingerprint or an undecoded payload — no instruction content is decodable from the visible text.
Are the packages/react-router-dev source files part of the shipped skill artifact or merely the surrounding React Router repository that the skill edits? If they are surrounding repository code rather than artifact payload, the three undeclared-residue findings (npm_config_user_agent read, REACT_ROUTER_ROOT read, execSync auto-install) describe product behavior rather than skill behavior.
Does any skill workflow step (for example the pnpm test/integration commands) invoke the react-router dev/build path such that resolveEntryFiles' automatic execSync install would execute during RFC implementation, or is the auto-install only reachable via commands the skill never runs?
Code execution
Residue adjudication R3-R17: the flagged env reads (REACT_ROUTER_ROOT, IS_RR_BUILD_REQUEST, dotenv loading of all variables) and file reads/copies/removals (route files, .vite/manifest.json, client build directory listings, SRI hashing of built .js, SPA fallback HTML, SSR asset move/copy/rm) all live inside the React Router dev-package source that the skill exists to modify and test, so they are adjudicated 'necessary' (subject codebase exercising its own documented dev/build/preview behavior, n⟦… 297 more chars …⟧
Supply chain
Residue R39 (file_read './lib/server-runtime/cookies', SRC:1ee2d76cfbaed021 line 251) adjudicated as necessary: it is a static ESM re-export of the react-router package's own documented public API (export { createCookie, isCookie }), part of the library source the declared RFC-implementation purpose operates on, not a runtime credential read and not concealed.
Credential access
Residue R40 (file_read './lib/server-runtime/sessions/cookieStorage', SRC:1ee2d76cfbaed021 line 259) adjudicated as necessary: it is a static ESM re-export of the package's own cookie session storage API (export { createCookieSessionStorage }), visible library source required by the declared purpose, not a runtime credential read and not concealed.
Credential access
The decoded content recovered from router.ts lines 87-7978 begins with an opaque high-entropy base64url-looking string ('pZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM') whose full source line, origin, and purpose are not shown; the surrounding units are otherwise benign routing-library comments and code with no declared-claim contradictions or residue items in this batch.
The decoded content of packages/react-router/lib/router/router.ts (SRC:b3523bd2520eb9bf) begins with an opaque base64url-looking string followed only by benign library source comments; the purpose of that string, where it lives in the file, and whether any code consumes or executes it cannot be determined from the evidence shown. No sink, instruction, or network/credential reference is present in the decoded text.
fromNodeRequest/getForwardedProtocol trust the client-supplied X-Forwarded-Proto header to set the protocol used for action origin validation; can allowedActionOrigins enforcement be bypassed by header spoofing in dev/preview deployments?
The skill fetches RFC content from GitHub and implements whatever the discussion proposes; the shown sections contain no guard against instructions injected inside the fetched RFC text, so does untrusted discussion content steer code that is later committed and PR'd?
Agent hijacking
The plugin.ts units provided are comment-only excerpts of a 4032-line file; does the executable plugin code perform any network sends, shell/process execution, or writes outside the project build directories?
Code execution
All 50 units are the React Router Vite build plugin (manifest generation, route transforms, dev/preview servers, prerendering) with no harmful source-to-sink chain: every detector lead (local file reads of route files, build manifests, react-refresh runtime; env reads of REACT_ROUTER_ROOT and the plugin's own IS_RR_BUILD_REQUEST) stays within the project/package and reaches no network send, execution, or persistence sink. However, none of this code relates to the skill's declared purpose of fetc⟦… 164 more chars …⟧
The config hook calls loadDotenv({rootDirectory, viteUserConfig, mode}), which loads .env files (potential credential source) into the build environment; no sink for these values appears in the shown units, and the loadDotenv implementation is not in any shown unit, so a source-to-sink chain cannot be fully excluded from the evidence shown.
Credential access
These units dynamically import module URLs taken from the server-provided assets manifest (route.module, route.clientLoaderModule, route.clientActionModule); whether those URLs can ever originate outside the application's own build/manifest pipeline is not determinable from the units shown, so no source-to-exec chain is established.
Code execution
The decoded comment slice SRC:b3523bd2520eb9bf opens with a ~130-character base64url-looking fragment ('pZy8nX9MP2CNdomVaposqu3fGayT8T8-...DTkTreM'). The sibling slice SRC:ffe21c553777c3cd shows an intact 'https://mermaid.live/edit#pako:...' diagram URL in a comment, suggesting this fragment is the truncated tail of another such documentation link; no decode or execution of it appears anywhere in the shown units, so it is not a behavior-chain finding. Confirm from the full source line of router.⟦… 91 more chars …⟧
Units SRC:09852f7501974898 and SRC:0bc1a08b73dce345 are marked kind=decoded, implying recovery from an encoded or hidden channel, but the recovered text is only benign JSDoc/type documentation for React Router APIs (createContext, isRouteErrorResponse, loaders, middleware) with no executable payload, instruction, or network behavior; the encoding mechanism itself is not visible in the cited content.
Whether getBuildTimeHeader restricts the X-React-Router-Prerender-Data header to build-time contexts; the shown loader wrapper decodes that header's value via decodeViaTurboStream into loader data, and the gating function's implementation is not shown, so the reachability of this decode path to external request data cannot be settled here (no execution of decoded content is visible, so no harmful chain is established).
Refuted findings 5

Candidates the review stage examined and rejected, kept for transparency.

Credential access

criticalRefutedlow confidence

Unexplained undeclared residue: detectPackageManager in the react-router-dev code shipped with the implement-rfc skill reads the npm_config_user_agent environment variable to derive only a whitelisted package-manager name, an environment-read capability the skill's declared description does not cover and which shows no credential content or network sink.

let { npm_config_user_agent } = process.env;
Why it was refuted

The env read only detects the user's package manager: the shipped comment states that purpose and the value is matched against a fixed whitelist of five names with no credential content and no external sink, so the harm gate fails.

Code execution

criticalRefutedmedium confidence

When no user entry.server file exists, resolveEntryFiles silently rewrites the project's package.json to add isbot ^5 and executes `<package-manager> install` via execSync, downloading packages from the registry (including their lifecycle scripts) without user confirmation.

execSync(`${packageManager} install`, {
Why it was refuted

The executed command is constrained to a whitelisted package-manager name (detectPackageManager whitelist or the literal 'npm'), installs only the project's own dependencies plus the official isbot package, and is overtly announced; routine dependency installation is inherent to the skill's declared implement-and-test workflow, so the harm gate fails.

Credential access

highRefutedlow confidence

Unexplained undeclared residue: createConfigLoader reads the REACT_ROUTER_ROOT environment variable to override the project root directory used for config loading, an environment-read capability the implement-rfc skill's declared description does not cover and which shows no credential content or network sink.

root = Path.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
Why it was refuted

REACT_ROUTER_ROOT is only a local root-directory fallback inside a path-normalization chain used for config resolution; it contains no credential content and has no network or external sink, so the harm gate fails.

Credential access

highRefutedlow confidence

loadDotenv loads every variable from .env files regardless of prefix into process.env at dev-server startup, pulling secrets not scoped for this tool into the server process environment.

we're targeting the server, so we want to load all environment
Why it was refuted

Loading .env values into the server process is the documented, intended behavior of server-side dotenv loading — the in-code comment gives the rationale and the only sink is a local Object.assign into process.env with no network or external sink — so the harm gate fails.

Credential access

highRefutedlow confidence

The getBuildTimeHeader function in dev.ts reads the IS_RR_BUILD_REQUEST environment variable at runtime to gate returning a request header; the environment read is undeclared by the skill and no sink sends the value off-host, so it is an undeclared env-access capability without a demonstrated source-to-sink chain.

process.env.hasOwnProperty(
Why it was refuted

The flagged env access is not credential access: IS_RR_BUILD_REQUEST is a boolean build flag compared locally to the constant "yes" inside React Router's own server-runtime helper, explicitly commented as 'Guarded access to build-time-only headers', and the function's only data exit is an in-process return of a request header. The finding itself concedes no off-host sink, so with no chain and no secret material involved this is benign library code in the repository the skill's declared core capability operates on, not a harmful undeclared capability.

Coverage gaps 32

Parts of the artifact the static analysis could not fully examine.

context:unanalyzable_binary binary content is only byte-scanned
integration/helpers/rsc-vite/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
integration/helpers/rsc-vite-framework/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
integration/helpers/vite-7-template/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
integration/helpers/vite-8-template/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
integration/helpers/vite-plugin-cloudflare-template/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/basic/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/nested-dir-repo.tar.gz!/nested-dir-repo/stack/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/nested-dir-repo.tar.gz!/nested-dir-repo/folder.with.dots/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/template.tar.gz!/stack/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/template.tgz!/stack/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/templates-repo.tar.gz!/react-router-templates/.DS_Store
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/templates-repo.tar.gz!/react-router-templates/default/app/.DS_Store
context:unanalyzable_binary binary content is only byte-scanned
packages/create-react-router/__tests__/fixtures/templates-repo.tar.gz!/react-router-templates/default/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
packages/react-router-dev/__tests__/fixtures/basic/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/framework-express/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/framework-spa/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/framework-vite-7/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/middleware/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/performance/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/rsc-vite/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/rsc-vite-7-framework/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/rsc-vite-framework/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/split-route-modules/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/split-route-modules-spa/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
playground/vite-plugin-cloudflare/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
tutorials/address-book/public/favicon.ico
context:manifest_unparseable yaml: YAML node count exceeds 20000
pnpm-lock.yaml
glob_budget_exceeded reference source exceeds 262144 characters
packages/react-router/__tests__/dom/data-browser-router-test.tsx
no_dataflow_for_dynamic_code line 51: invoked code is not structurally extracted
packages/react-router/__tests__/server-runtime/markup-test.ts
no_dataflow_for_dynamic_code line 3320: invoked code is not structurally extracted
packages/react-router/lib/dom/lib.tsx
invalid_expansion declared-vs-actual.36
invalid_judge_finding request.2