An oRPC CORS plugin copied an incoming request's Vary header into its response, allowing the client to influence instructions intended for downstream caches. CVE-2026-77360, also tracked as GHSA-j9v4-rhgr-4m5f, carries a CVSS v4.0 score of 6.3 in GitHub's advisory database as of September 18, 2026. Its practical impact depends on the caching layer in front of the application.
The record entered GitHub's advisory database on September 17, but the project advisory dates to July 12. This is a newly cataloged CVE for an already public fix. The affected stable package range is @orpc/server through 1.14.7; the listed patched version is 1.14.8.
For a team running oRPC behind a shared cache, the question is whether the cache can reuse a response under conditions the application never intended. A correct-looking response from the origin server cannot settle that question by itself.
The request supplied the fallback's replacement
The change is in packages/server/src/plugins/cors.ts. In the vulnerable code, the plugin assigned Vary from the request, falling back to origin only when the request supplied no value. The public patch, commit daabded122a89d323357c4c401e879701864cb2f, replaces that assignment with logic that reads the response's existing header.
-result.response.headers.vary = interceptorOptions.request.headers.vary ?? 'origin'+const existingVary = flattenHeader(result.response.headers.vary)+if (!existingVary?.split(',').some(v => v.trim().toLowerCase() === 'origin')) {+ result.response.headers.vary = existingVary ? `${existingVary}, Origin` : 'Origin'+}The fallback explains why an ordinary check could miss the defect. With no incoming Vary, the old expression returned the expected origin value. Supplying the header selected a different path through that same assignment. The client had acquired control over a response field without changing the application's CORS configuration.
The original issue, opened July 11, illustrates the mismatch: the response's allowed origin depended on the request origin, while its cache variation could describe a different request field. The issue also mentions a prerelease build. Teams on prereleases should verify their exact build against the fix rather than infer a patched beta range from the stable-version advisory.
Vary tells a cache which requests are interchangeable
RFC 9111, section 4.1, published June 2022, specifies how a cache uses Vary when deciding whether a stored response can satisfy a later request. Reuse without revalidation requires the named request fields to match according to the specification's comparison rules. For a response that varies by origin, Vary: Origin communicates that dependency.
Consider an illustrative API whose response headers differ between two approved browser origins. The application may produce the appropriate headers each time it handles a request. A shared cache, however, can answer a later request without invoking the application again. Its reuse decision must preserve the distinctions on which that response depends.
The vulnerable assignment could remove Origin from that instruction. That establishes a defect in the response metadata. Whether it produces a security-relevant result requires examining which responses the intermediary stores and how it constructs its cache keys.
This distinction limits the claim. The advisory describes potential cache-key pollution and inconsistent CORS enforcement, and reports no direct confidentiality, integrity, or availability impact in the default non-cached configuration. It does not establish that every affected installation leaks customer data. Nothing in the sources reviewed for this article establishes active exploitation.
The tests check who owns the response header
The patch's regression tests cover more than rejecting an incoming value. They also check that the plugin preserves an existing response variation and avoids adding another Origin entry when one already exists, including a differently capitalized spelling.
Those cases protect two separate requirements: the request must not dictate the response's variation, and the CORS plugin must not erase a legitimate variation supplied elsewhere in the response pipeline. Replacing every value with Origin would address only the first requirement.
We reviewed the code and tests; we did not reproduce a cache-poisoning attack against a particular CDN. The regression cases establish the intended header behavior, while an application's deployment still determines what downstream systems do with it.
Verify the public response path after updating
Check the resolved package version in the deployed application, then update to a maintained release that includes the fix. The project's 1.14.8 release is the stable remediation identified by the advisory. Review any other bundled oRPC packages that carry the CORS plugin as part of that update.
In staging, compare the response served directly by the application with the one delivered through your normal proxy or CDN. Use synthetic data and the origins your application is configured to allow. Confirm that server-controlled variation survives the full path and that a request cannot replace it. Exercise both an uncached response and a subsequent cache hit where caching is intended.
If the update must wait, review whether affected API responses can temporarily bypass shared caching. That is a deployment-specific containment measure, with a potential performance cost, rather than a replacement for the patch. Check the intermediary's actual configuration before relying on it.
Close the remediation when the deployed version contains the fix and the public response path preserves the intended variation. A successful dependency update establishes only the first of those facts.
