StackHawk
๏ƒ‰

Node.js CORS Guide: What It Is and How to Enable It

Matt Tanner   |   Jul 31, 2025

Share on LinkedIn
Share on X
Share on Facebook
Share on Reddit
Send us an email

Ever tried to build a frontend application that fetches data from your Node.js API, only to be greeted by a cryptic error message in your browser’s console? You check the network tab and see your request failed, with mentions of CORS or same-origin policy violations.

If you’re working with a Node.js application that needs to serve requests from different domains, this comprehensive guide is for you. We’ll explore how Node.js handles cross-origin requests when CORS becomes necessary, how to resolve common CORS errors during development, how to configure secure CORS settings for production, and best practices for validating your setup with automated testing tools like StackHawk.

Let’s dive into understanding what CORS actually means and why it matters for your Node.js applications.

What Is CORS?

CORS stands for Cross-Origin Resource Sharing. It’s a web standard that determines how browsers handle requests between different domains, allowing servers to specify which external websites can access their resources.

Let’s say your server runs on https://domain1.com. You could serve images, fonts, or have simple web services that send back some data. Now, imagine there’s another website that runs on https://domain2.com, which wants to access your services and retrieve data from your server. To do so, this website makes an HTTP request to one of your API endpoints.

Unknown website requesting data from your server

Every HTTP request comes with request headers that contain information about the request. In our example, when https://domain2.com sends an HTTP request to your server, it also includes an origin property in the request’s header. This origin property specifies the domain of the source that has made the request.

Origin in HTTP request headers

The browser on which domain2 sends a request to domain1 implements the same-origin policy. Because of this policy, the browser blocks all requests sent from one origin to another. Therefore, web browsers by default don’t allow cross-origin resource sharing.

CORS request blocked by the browser

This built-in mechanism acts as a safety blanket for web servers. It protects unknown websites from accessing their resources.

Recognizing CORS Errors in Node.js Applications

If you’ve landed on this guide, chances are you’ve encountered CORS-related errors when your client application attempts to communicate with your Node.js API. These errors typically appear in your browser console like this:

Access to fetch at 'https://api.myservice.com/data' from origin 'https://myapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Or perhaps something like:

Access to XMLHttpRequest at 'http://localhost:8000/api/users' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

These errors occur because your browser is enforcing the same-origin policyโ€”a security feature that blocks requests between different origins (protocol, domain, and port combinations). Seeing these messages in your console indicates that you’re dealing with a CORS configuration issue.

Common CORS Scenarios in Node.js Development

These types of issues typically arise from predictable situations that are fortunately straightforward to resolve. Here are the most frequent scenarios where CORS problems surface in Node.js applications:

  • Client-server separation: React/Vue/Angular application at https://myapp.com consuming Node.js API at https://api.myapp.com
  • Local development: Frontend development server at http://localhost:3000 calling Node.js backend at http://localhost:8000
  • Authentication flows: Single-page applications attempting to include cookies or authorization tokens
  • Multi-environment testing: APIs being accessed from various development and staging environments

Troubleshooting CORS Issues

Before jumping into CORS configuration changes, it’s worth confirming that you’re actually dealing with a CORS problem:

  1. Examine the Network panel – You’ll observe the request being sent, but the response data won’t be accessible
  2. Watch for preflight OPTIONS requests – Certain requests trigger an OPTIONS call before the main request
  3. Verify with direct testing – Use curl, Postman, or similar tools to test the same endpoint

If your API works perfectly with direct tools but fails in the browser, you’ve confirmed it’s a CORS issue.

Do You Need CORS?

Since CORS is a fundamental security mechanism, your approach should be to enable it selectively, only when genuinely needed, and only for the specific endpoints that require it.

From a security standpoint, browsers assume that your server doesn’t want to share resources with websites it doesn’t know. However, there are many situations where you explicitly want to enable CORS on your server.

Open or Public APIs

Public or open APIs with CORS enabled

Often, you want other developers to access your APIs. Developer-specific tools, Software as a Service (SaaS) companies, and others have open APIs that anyone can use on their website.

For instance, you may want to create an API service that allows developers to check the SEO scores of their websites. In that case, you’d have to keep an open API that anyone can conveniently access.

Free, open, and public APIs are extremely popular today and are widely used in various businesses and side projects.

Allow Access to Multiple Environments of the Same Project

Multiple project environments

Let’s say you’re pushing out a revamped version of your website. Before pushing your code to production, you typically test it in a test environment first. In this case, you test your front end against different environments. You could first test it at a staging environment, then a pre-production environment, and so on. In this case, your different front ends may fail to communicate with your server if CORS is not enabled.

If neither scenario applies to your application, CORS configuration may be unnecessary.

How to Enable CORS in Node.js

There are multiple ways to enable CORS on your Node.js server. Let’s explore the most effective methods.

Set Access-Control-Allow-Origin in the Response Header

We can allow certain or all origins to request a resource from our APIs by sending back a property in the response. This property, called Access-Control-Allow-Origin, can be configured on the headers of our response inside the request handler.

For Public/Open APIs

You can specify the value of this property to be * (wildcard) for any origin or website to access the API. As a result, when the browser sees this value, it allows the website to access the resource from the API regardless of its domain or origin.

app.get('/colors', (req, res) => {
    res.set('Access-Control-Allow-Origin', '*');
    res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    
    // Handle preflight requests
    if (req.method === 'OPTIONS') {
        return res.status(200).end();
    }
    
    res.json(colors);
});

    

SECURITY WARNING: You should never use the `*` (wildcard) value in production environments unless you have a genuine public API. This setting allows any website to access your API, which can be a significant security risk.

If you test this with a frontend application, the request should proceed successfully, and the JSON data should be displayed on the frontend.

CORS enabled using wildcard property

For Specific Websites

Alternatively, if you want only users from a specific origin to access your APIs, you can set a specific value for this property. This approach is more suitable for use cases where you want to enable CORS for different environments.

app.get('/colors', (req, res) => {
    res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
    res.json(colors);
});

The effect should be the same – if you test with your frontend application, you should see the data rendered on the page.

Use the cors Express Middleware

The cors npm module provides middleware that you can use in your request handlers. It’s simple to use, so let’s get started by installing it in our project first:

npm i cors

Import this module at the top:

const cors = require('cors');

Next, invoke this middleware in your Express app:

app.use(cors());

Now, all requests received by the server will have CORS enabled in them. You can also customize this by passing an options object inside the cors() method. Inside that object, you can specify the origin property, similar to how you set Access-Control-Allow-Origin in the response header previously.

const options = {

    origin: 'http://localhost:3000',

};

app.use(cors(options));

You can also specify more than one origin by passing an array to the origin property inside your options object:

const options = {
    origin: ['http://localhost:3000', 'http://localhost:8080'],
};

The above isn’t possible when you manually set the Access-Control-Allow-Origin property on the response header. If you pass more than one origin, the API would have CORS disabled, and the error message would tell you to use only a single origin property.

If you want to specifically enable CORS for a particular request, you can call it inside the request handler:

app.get('/colors', cors(), (req, res) => {

    res.json(colors);

});

This will enable CORS for the /colors API endpoint only.

Production Configuration Example

For production applications, itโ€™s best to be explicit about which origins can access your API. Below is a complete example of a CORS implementation that sets various CORS options and includes an array of allowed origins that can access the API.

const allowedOrigins = [
    'https://myapp.com',
    'https://www.myapp.com',
    'https://admin-panel.myapp.com'
];

const corsOptions = {
    origin: function (origin, callback) {
        // Allow requests with no origin (mobile apps, curl, etc.)
        if (!origin) return callback(null, true);
        
        if (allowedOrigins.includes(origin)) {
            callback(null, true);
        } else {
            callback(new Error('Not allowed by CORS'));
        }
    },
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization']
};

app.use(cors(corsOptions));

Using a Proxy Server for CORS-Disabled APIs

Often, your frontend needs to access third-party APIs that have CORS disabled. Since you don’t have access to the backend code of those third-party APIs, it’s not possible to implement the solutions discussed above. In this case, a proxy server is particularly useful. It allows your frontend to access resources from a server that is not CORS-enabled.

Let’s say you have a third-party API running at http://localhost:8080/user that doesn’t have CORS enabled. If you try to access it directly from your frontend, you’ll get a CORS error:

CORS disabled server error on frontend

You can use your own Node.js server as a proxy. First, install axios to make HTTP requests:

npm i axios

Then create a proxy endpoint:

const axios = require('axios');

app.get('/user', async (req, res) => {
    const response = await axios.get('http://localhost:8080/user');
    res.json(response.data);
});

Now your frontend can make requests to http://localhost:8000/user instead of the CORS-disabled endpoint directly. Since you have CORS enabled on your own server, you use it as a proxy to fetch data from the server that your frontend can’t directly access.

Proxy server for accessing data from CORS-disabled server

This is how you can enable CORS on third-party APIs using a custom proxy server.

Essential CORS Headers Explained

As youโ€™ve seen in some of our examples, there are quite a few different CORS headers that can be set. Understanding these key CORS headers will help you configure your Node.js application properly. The various headers include:

  • Access-Control-Allow-Origin: Defines which origins can access your resources
  • Access-Control-Allow-Methods: Lists permitted HTTP methods for cross-origin requests
  • Access-Control-Allow-Headers: Specifies which headers clients can include in requests
  • Access-Control-Allow-Credentials: Controls whether cookies and authorization headers can be sent
  • Access-Control-Max-Age: Sets how long browsers can cache preflight response results

Node.js CORS Best Practices

Before we go into testing your CORS configuration, letโ€™s review a few important best practices to keep in mind, many of which have already been covered in the sections above. Here are a few things to keep in mind:

  1. Specify explicit origins: Avoid wildcard usage in production environments; enumerate exact domains requiring access
  2. Implement preflight handling: Ensure your application responds appropriately to OPTIONS requests
  3. Validate origins programmatically: Don’t rely solely on browser enforcement; implement server-side origin validation
  4. Leverage established packages: Use well-maintained libraries like the cors package for production deployments
  5. Test comprehensively: Combine manual verification with automated security testing tools
  6. Apply selective enabling: Only configure CORS for endpoints that genuinely require cross-origin access

Why Automated CORS Testing Matters

CORS misconfigurations are among the most common security issues in modern web applications. Manual testing often misses edge cases, and it’s easy to inadvertently create security gaps while attempting to resolve functionality issues.

A common mistake when fixing CORS errors is implementing overly permissive configurations that work but create security vulnerabilities. For example, setting Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true or using overly broad origin patterns.

One of the most trusted security platforms for this type of testing is StackHawk. By using StackHawk to test for vulnerabilities in your Node.js applications and APIs, you get:

  • Early detection of CORS issues during development
  • Automated testing of complex CORS scenarios you might not think to test manually
  • Clear remediation guidance with specific examples of vulnerable requests
  • Verification that fixes don’t introduce new security issues

By integrating CORS security testing into your development workflow, you can ensure that your cross-origin requests work reliably while maintaining your application’s security.

Getting Started with StackHawk

To make your AI-generated APIs more secure by default with StackHawk, youโ€™ll need an account. You canย sign up for a trial account. If youโ€™re using an AI-coding assistant like Cursor or Claude Code, sign up for our $5/month single-user plan,ย Vibe, to find and fix vulnerabilities 100% in natural language.

Validating Your CORS Configuration with StackHawk

Once you’ve implemented CORS headers, it’s crucial to ensure your configuration is both functional and secure. A common mistake is fixing the immediate CORS error but inadvertently creating security vulnerabilities, such as allowing credentials from any origin or being overly permissive with allowed domains.

This is where automated security testing becomes invaluable. Instead of manually testing every possible CORS scenario and hoping you haven’t introduced security gaps, you can use StackHawk to automatically validate that your CORS implementation works correctly without creating new attack vectors.

While static testing might help you spot some CORS errors, youโ€™ll need dynamic testing to ensure the runtime environment where CORS interactions occur is also free of errors. StackHawk is a DAST tool (Dynamic Application Security Testing) that will test your CORS implementation for common security issues, including:

  • Wildcard origin acceptance with credentials: Testing if your API dangerously accepts * as an origin while allowing credentials
  • Origin reflection vulnerabilities: Checking if your API blindly reflects the Origin header without proper validation
  • Missing security headers: Identifying CORS setups that lack proper CSRF protection
  • Overly permissive configurations: Finding CORS policies that are broader than necessary

Instead of waiting for our AppSec team to notify us of an issue later in development, letโ€™s use StackHawk to automatically identify this vulnerability for us. To do this, youโ€™ll need to ensure you have a StackHawk account. If you need one, you can sign up for a trial account or log into an existing account.

If youโ€™re logging into an existing StackHawk account, from the Applications screen, youโ€™ll click Add Application.

Applications 52 findings dashboard

If youโ€™re new to StackHawk, youโ€™ll be automatically brought into the Add an App flow. On the Scanner screen, youโ€™ll see the instructions for installing the StackHawk CLI. Since we will be running our testing locally, we will use this option. Once the hawk init command is executed successfully, click the Next button.

On the next screen, you will fill out an Application Name, Environment, and URL. Once filled out, click Next.

Application Details My CORS App

Since we will be testing a RESTful API, on the next page, we will choose our Application Type as โ€œDynamic Web Application/Single Page Applicationโ€.

Application Type details page

Depending on what you have set up as a backend API, youโ€™ll also plug these details in. For example, if you have a REST API running, set the API Type to โ€œREST / OpenAPIโ€ and point to our OpenAPI Specification file by selecting the URL Path and entering the path to your OpenAPI spec in the text box. Alternatively, as Iโ€™ve done here, we can also click โ€œSkip for nowโ€ if youโ€™re unsure. Once complete, click Next.

Application Type API REST/OpenAPI

Lastly, we will need to add a stackhawk.yml file to the root of our project. Once the file is added, copy the screenโ€™s contents, paste them into the file, and save it. Lastly, we can click the Finish button.

YAML Download and Scan setup steps

In our root directory, we should see the stackhawk.yml file weโ€™ve added:

stackhawk yml code

Lastly, depending on our scan policy, CORS misconfiguration detection may not be enabled. To ensure this, go back to StackHawk, navigate to the Applications page, and select your app. Once on the config page, click on the Settings tab, then the Active Scan Plugins tab, located just below it. Then, locate the CORS Header plugin in the list and select it. You can find it easily by typing “cors” into the plugin search bar.

My CORS App Active Scan Plugins

Lastly, click Save, located just above the Plugins list, to save the new configuration.

Run HawkScan

Next, we can go ahead with testing our application. In a terminal pointing to the root of our project, we will run HawkScan using the following command:

hawk scan

After running the command, the tests should execute in the terminal.

Terminal HawkScan 4.4.0 node-cors example

Note that if you get an error similar to:

HawkScan Target Not Found Error: Unable to access https://localhost:4000. Check if the web server is listening on the specified port.

This means that your API is not running in HTTPS, and that is how HawkScan is trying to call the API. To fix this, either add HTTPS capabilities to your API or, more simply, change the host entry in your stackhawk.yml to use only “http”.

Terminal HawkScan app ID example

This will run tests against our Node.js application and the corresponding backend. Once the tests have run, we can begin to explore any findings that were discovered.

Explore The Initial Findings

Once the tests are complete, the terminal will contain some information about any vulnerabilities found. Below, we can see that StackHawk has found a few CORS vulnerabilities within my code that are present on multiple paths.

Terminal Scan Results example

To explore this further, we will click on the test link at the bottom of the output. This will take us into the StackHawk platform to explore further.

Terminal Scan Results Risks example

After clicking on the link, we can now view the test results in a nicely formatted display. Next, we will click on the CORS Misconfiguration entry.

CORS Misconfig My CORS App

Within this entry, we can see an Overview and Resources that can help us with fixing this vulnerability, as well as the Request and Response that the API returned on the right side of the screen. Above this, you will also see a Validate button, which will display a cURL command with the exact HTTP request used to expose the vulnerability.

CORS Misconfig Remediation and Fixes

Understanding and Fixing CORS Security Issues

When StackHawk identifies CORS vulnerabilities, you’ll see detailed findings that indicate which paths are affected and provide potential remediation techniques (as shown in the image above). Using the techniques in this guide or the remediation advice provided by StackHawk for the vulnerability, you can then make the necessary adjustments to your code and configuration. Once fixed, ensure that you stop your web servers and redeploy the latest code. Next, we can ensure that the fix implemented actually resolves our CORS misconfiguration issues.

Confirm the fix!

With the latest code deployed, letโ€™s confirm the fix in StackHawk. To do this, we will click the “Rescan Findings” button in StackHawk.

Rescan Findings to Confirm Fix

Then, we will see a modal containing the โ€œhawk rescanโ€ command that includes the correct Scan ID. Youโ€™ll run this command in the same terminal where you ran the initial set of tests.

Rescan findings window

In the output, you will again see any vulnerabilities that were found during the scan. In this case, youโ€™ll see that the CORS misconfiguration vulnerabilities are no longer showing. Clicking on the link at the bottom of the terminal output, you can confirm that the CORS misconfiguration vulnerabilities have now been added to the Fixed Findings from Previous Scan, confirming that the vulnerability has been successfully fixed and has passed any vulnerability tests.

My CORS App Scan Results Fixed- CORS MisConfig

With that, weโ€™ve successfully remedied and retested our application to ensure its safety from potential CORS misconfiguration attacks.

Conclusion

Effective CORS implementation in Node.js requires striking a balance between accessibility and security considerations. While Node.js provides flexible options for CORS configuration through headers and middleware, understanding the security implications of each setting is crucial.

Key takeaways for Node.js CORS implementation:

  • Enable CORS selectively for endpoints that genuinely need cross-origin access
  • Prefer explicit origin lists over wildcard configurations in production
  • Always handle preflight OPTIONS requests appropriately
  • Validate your configuration thoroughly across development and production environments
  • Conduct regular security audits of your CORS settings

If youโ€™d like to gain an understanding of CORS in frameworks other than Node.js, check out one of our other guides:

Remember that properly resolving CORS issues means ensuring legitimate requests succeed while blocking potential security threats. Automated dynamic security testing tools like StackHawk provide confidence that your Node.js CORS implementation achieves both functionality and security objectivesโ€”before you ship code.

Ready to secure your Node.js CORS configuration? Sign up for StackHawk today to automatically test your CORS setup and identify potential vulnerabilities with a free trial.

More Hawksome Posts

Discover the Best API Discovery Tools in 2025

Discover the Best API Discovery Tools in 2025

APIs power todayโ€™s software, but with AI tools accelerating development, many organizations donโ€™t even know how many APIs they haveโ€”or how secure they are. Shadow, zombie, and rogue APIs can quietly expand your attack surface, leaving critical vulnerabilities unchecked. Thatโ€™s why modern API discovery tools are essential. This guide breaks down what API discovery is, why it matters more than ever in 2025, and how to choose the right tool to secure your entire API landscape.