Security of your Vendure application includes considering how to prevent and protect against common security threats such as:
Vendure itself is designed with security in mind, but you must also consider the security of your own application code, the server environment, and the network architecture.
Here are some basic measures you should use to secure your Vendure application. These are not exhaustive, but they are a good starting point.
Do not deploy any public Vendure instance with the default superadmin credentials (superadmin:superadmin). Use your hosting platform's environment variables to set a strong password for the Superadmin account.
The default apiOptions.cors setting is:
origin: true makes the server echo back whatever Origin the caller sent. Together with
credentials: true, this permits any website to make cross-origin requests to your Shop and Admin
APIs. The default exists so that a new project works with a storefront on any port or domain during
development. Replace it with an explicit list before you deploy:
Vendure logs a warning at startup when it finds origin: true together with credentials: true.
cookieOptions.sameSite: 'lax' blocks part of this, but not all of it. Browsers do not attach a
SameSite=Lax cookie to a cross-site fetch or XMLHttpRequest, so an attacker's page cannot make
authenticated API calls or read authenticated responses with the defaults in place.
SameSite does not stop a cross-site HTML form POST from creating a session. A top-level navigation
may store a cookie with any SameSite value, even when that cookie would not have been sent on the
request (RFC 6265bis, section 5.5). A form that posts
query=mutation { login(...) } as application/x-www-form-urlencoded needs no CORS permission and no
JavaScript, and the response sets a session cookie in the victim's browser. That is Login CSRF: the
victim ends up browsing your store logged in as the attacker, and anything they enter after that
(addresses, saved payment details, order history) sits in the attacker's account.
The control that stops this is Apollo Server's CSRF prevention, not SameSite and not CORS. Turn it
on with apiOptions.csrfPrevention:
It rejects any POST whose content type is one a browser lets a form send
(application/x-www-form-urlencoded, multipart/form-data, text/plain) unless the caller also sends
Apollo-Require-Preflight or x-apollo-operation-name. Requests sent as application/json, which is
what Vendure clients use for normal operations, are unaffected. GET requests carry no content type at
all, so they are rejected too unless they send the header.
The default is false so that existing clients keep working. It is expected to change to true in a
future major release.
Before you enable it, check every client that uploads files to your API. Multipart uploads use one of
the blocked content types, so the client must send Apollo-Require-Preflight. @vendure/admin-ui,
@vendure/dashboard and @vendure/testing all send it. A custom admin client built on
apollo-upload-client does not send it unless you add it. The same applies to any storefront that
uses GET for cacheable queries. The storefront starters offered by @vendure/create live in separate
repositories, so check the one you used before you turn this on.
The CORS default is a separate problem on top of that, and it becomes serious in these cases:
cookieOptions.sameSite: 'none'. This is a common setting when the storefront is on a different
site to the server. The browser now does attach the session cookie to cross-site requests, so any
website can make fully authenticated calls as the logged-in user and read the responses. An origin
allowlist is the only control that stops this.tokenMethod: 'bearer'. sameSite gives no protection here. The browser does not attach the
token by itself, so an attacker page still needs to obtain a token first, for example through an XSS
on your own origin. An origin allowlist removes the CORS step from that chain.apiOptions.cors applies to the Shop API and the Admin API together.
You cannot allow a storefront origin on /shop-api without allowing it on /admin-api as well, so
keep the list to the origins that need both, and put the Admin API behind a gateway if you need
tighter separation.Set an explicit origin list in every case. It costs nothing and it is the one control that works for every session transport.
It is recommended that you install and configure the HardenPlugin for all production deployments. This plugin locks down your schema (disabling introspection and field suggestions) and protects your Shop API against malicious queries that could otherwise overwhelm your server.
Install the plugin:
Then add it to your VendureConfig:
For a detailed explanation of how to best configure this plugin, see the HardenPlugin docs.
If you are using the AssetServerPlugin, it is possible by default to use the dynamic image transform feature to overload the server with requests for new image sizes & formats. To prevent this, you can configure the plugin to only allow transformations for the preset sizes, and limited quality levels and formats. Since v3.1 we ship the PresetOnlyStrategy for this purpose, and you can also create your own strategies.
The Open Worldwide Application Security Project (OWASP) is a nonprofit foundation that works to improve the security of software.
It publishes a top 10 list of common web application vulnerabilities: https://owasp.org/Top10
This section assesses Vendure against this list, stating what is covered out of the box (built in to the framework or easily configurable) and what needs to be additionally considered.
Out of the box:
To consider:
Out of the box:
To consider:
Reference: https://owasp.org/Top10/A03_2021-Injection/
Out of the box:
To consider:
Out of the box:
To consider:
Out of the box:
To consider:
apiOptions.cors setting of { origin: true, credentials: true } with an explicit list of the origins you serveOut of the box:
To consider:
Out of the box:
To consider:
To consider:
Out of the box:
To consider:
Out of the box:
To consider:
Architecture reviews, custom plugin work, migrations, ongoing support. Get a hand from the team that builds Vendure.
Talk to the team