Skip to content

fix(api): Add CORS support to API#3222

Merged
another-rex merged 3 commits intogoogle:masterfrom
dataprosconsulting:patch-1
Mar 12, 2025
Merged

fix(api): Add CORS support to API#3222
another-rex merged 3 commits intogoogle:masterfrom
dataprosconsulting:patch-1

Conversation

@dataprosconsulting
Copy link
Copy Markdown
Contributor

@dataprosconsulting dataprosconsulting commented Mar 5, 2025

The OSV API does not respond properly to CORS requests, for example a call to https://api.osv.dev/v1/query with Origin in the headers should return Access-Control-Allow-Origin: "*".

According to https://cloud.google.com/endpoints/docs/openapi/specify-esp-v2-startup-options#cors , this change to the ESPV2 env variables should get the job done without requiring someone to go into the backend and mess with nginx / apache files.

Why it's important: Integrations that use a webkit-based backend (or a Web Application Framework) when configured to security best practices will have CORS checks enabled for any non-same origin calls (meaning any curl/fetch calls made outside of the domain of the tool). While this can be bypassed by altering the Cross-Origin Resource Policy, it is not recommended to do so as CORS prevents certain kinds of XSS/remote hijacking attacks.

That means any integration system that does CORS checks cannot access the OSV API.

There is precedent for enabling this within the integrations OSV already is using - all of the CDN-pulled libraries and many of the data sources such as NIST are correctly sending CORS headers when resources are fetched from them. All NIST API endpoints have Access-Control-Allow-Origin: "*" in the header. It is a well-documented standard practice to enable this setting for public APIs, which OSV is.

The OSV API does not respond properly to CORS requests, for example a call to https://api.osv.dev/v1/query with Origin in the headers should return Access-Control-Allow-Origin: "*".

According to https://cloud.google.com/endpoints/docs/openapi/specify-esp-v2-startup-options#cors , this change to the ESPV2 env variables should get the job done without requiring someone to go into the backend and mess with nginx / apache files.
@google-cla
Copy link
Copy Markdown

google-cla Bot commented Mar 5, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@dataprosconsulting
Copy link
Copy Markdown
Contributor Author

Ok, no clue if I did this right or not, problem is that I won't really be able to tell until a build is pushed to either api.osv.dev or api.test.osv.dev .

A couple of tests you can do:

  1. curl "https://api.test.osv.dev/v1/query" -X POST -H "Accept: */*" -H "Accept-Language: en-US,en;q=0.5" -H "Accept-Encoding: gzip, deflate, br, zstd" -H "Content-Type: text/plain;charset=UTF-8" -H "Origin: null" -H "Sec-GPC: 1" -H "Connection: keep-alive" -H "Sec-Fetch-Dest: empty" -H "Sec-Fetch-Mode: cors" -H "Sec-Fetch-Site: cross-site" -H "Priority: u=4" --data-raw "{""package"": {""name"": ""bootstrap"", ""ecosystem"": ""npm""}, ""version"": ""3.0.0""}" should have a header
    Access-Control-Allow-Origin: "*"
  2. go to a live preview website like w3schools.com and make a fetch call. Press F12 in chrome and watch the Network tab - Chrome (and Firefox) will block the request if osv.dev does not include the header - unless you did something risky like overriding CORS settings locally, which if you did, you should not be browsing the web on that computer...
    Here's some code you can shove into the w3schools site's "Try it" editor:
    <!DOCTYPE html><html><body><h1>JavaScript Fetch API</h1><h2>The fetch() Method</h2><p id="demo">Fetch a file to change this text.</p><script>getText("fetch_info.txt");async function getText(file){let x=await fetch("https://api.test.osv.dev/v1/query",{method:"POST",body:'{"package":{"name":"bootstrap","ecosystem":"npm"},"version":"3.0.0"}'});let y=await x.text();document.getElementById("demo").innerHTML=y;}</script></body></html>

@dataprosconsulting dataprosconsulting changed the title Add CORS support to API fix(api): Add CORS support to API Mar 5, 2025
@andrewpollock
Copy link
Copy Markdown
Contributor

Hi, could you update the PR description to include more details on what problem you're trying to solve here? What's the use case you can't perform today with the API configured as it is?

@dataprosconsulting
Copy link
Copy Markdown
Contributor Author

dataprosconsulting commented Mar 6, 2025

Done. Let me know if I did it wrong or more clarity is needed.

The short-and-sweet is that CORS checks are standard for web-based backends and web applications, so the API should be configured for CORS in order to enable those types of systems to leverage and integrate it. People using one of these backends can't call the OSV API without the change. Bypassing the checks is not recommended for security, it's easier to change one line in the ESV configuration to do the right thing than to tell every potential user of the API to do something that would raise their CISO's blood pressure.

Sources for the rationale behind the change:

https://stackoverflow.com/questions/41302753/does-a-restful-api-need-cors-implementation-anytime
https://developer.mozilla.org/en-US/docs/Web/Security/Practical_implementation_guides - identifies CORS as a high-impact low-effort security best practice
https://livebook.manning.com/book/cors-in-action/chapter-6/28 - good overall read on CORS
https://reflectoring.io/complete-guide-to-cors/ - has a lot of good diagrams explaining the flows supported by CORS
https://auth0.com/blog/cors-tutorial-a-guide-to-cross-origin-resource-sharing/ - Okta (Auth0) is a reliable source as a leading cybersec/IGA/IGM platform

@another-rex another-rex self-requested a review March 12, 2025 05:35
@another-rex
Copy link
Copy Markdown
Contributor

/gcbrun

Copy link
Copy Markdown
Contributor

@another-rex another-rex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out! Let's see if this works.

@another-rex
Copy link
Copy Markdown
Contributor

/gcbrun

@another-rex another-rex merged commit 2b73029 into google:master Mar 12, 2025
11 checks passed
@dataprosconsulting
Copy link
Copy Markdown
Contributor Author

Looks like the test site https://api.test.osv.dev is passing CORS responses correctly (meaning this change did what it was supposed to do!), but prod is not yet returning the CORS header:

image

Is there a separate CI/CD that has to run to promote that change to the prod endpoint, or a manual step necessary to restart that container?

Since this change is an environment flag change, if you're using a "hotpatch" style test->prod promotion pathway it wouldn't take effect until a container refresh. Not an expert in the GC App hosting framework, but if it's anything like Kubernetes and has multiple HA/latency containers running, you have to round robin through the nodes to restart each instance, similar to how you would apply a major Kubernetes version upgrade.

@another-rex
Copy link
Copy Markdown
Contributor

Seems to allow cross origin requests now on the test instance of the API, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants