MagicMirrorOrg/MagicMirror · error
CORS proxy is disabled
Error message
CORS proxy is disabled
What it means
The `/cors` proxy handler in js/server_functions.js:60 refuses to proxy when `global.config.cors` is set to the literal string `"disabled"`. It returns HTTP 403 with a JSON body `{ error: "CORS proxy is disabled" }` and logs that you must set `cors` to `allowAll` or `allowWhitelist`. The proxy exists so modules can fetch cross-origin resources (RSS, calendars, weather APIs) that lack CORS headers.
Source
Thrown at js/server_functions.js:60
// Load the real value from the environment. Fallback to placeholder if missing.
return process.env[secretName] || placeholder;
});
}
/**
* A method that forwards HTTP Get-methods to the internet to avoid CORS-errors.
*
* Example input request url: /cors?sendheaders=header1:value1,header2:value2&expectedheaders=header1,header2&url=http://www.test.com/path?param1=value1
*
* Only the url-param of the input request url is required. It must be the last parameter.
* @param {Request} req - the request
* @param {Response} res - the result
* @returns {Promise<void>} A promise that resolves when the response is sent
*/
async function cors (req, res) {
if (global.config.cors === "disabled") {
Log.error("CORS is disabled, you need to enable it in `config.js` by setting `cors` to `allowAll` or `allowWhitelist`");
return res.status(403).json({ error: "CORS proxy is disabled" });
}
let url;
try {
const urlRegEx = "url=(.+?)$";
const match = new RegExp(urlRegEx, "g").exec(req.url);
if (!match) {
url = `invalid url: ${req.url}`;
Log.error(url);
return res.status(400).send(url);
} else {
url = match[1];
if (typeof global.config !== "undefined") {
if (config.hideConfigSecrets) {
url = replaceSecretPlaceholder(url);
}
}
View on GitHub (pinned to 4b4a59534f)
Solutions
- Set `cors: 'allowAll'` in config.js if you accept unrestricted proxying, or `cors: 'allowWhitelist'` to restrict proxied hosts, then restart the mirror.
- If you intentionally keep the proxy disabled, reconfigure the failing module to fetch its resource without the `/cors` endpoint (enable CORS on the upstream server, or use a module option that calls the backend directly).
- Verify `global.config` is actually loaded from your config.js — check that config.js parses (no syntax errors) so your `cors` setting takes effect.
- Check the server log for the companion message 'CORS is disabled, you need to enable it in `config.js` ...' to confirm which config file was loaded.
Example fix
// before (config.js) cors: 'disabled', // after cors: 'allowWhitelist', // or 'allowAll'
Defensive patterns
Strategy: validation
Validate before calling
// Before calling the proxy, confirm it is enabled on the server config:
async function proxyEnabled(baseUrl) {
const probe = await fetch(`${baseUrl}/cors?url=https://example.com`, { method: 'GET' });
const body = await probe.json().catch(() => ({}));
return !(probe.status === 403 && body.error === 'CORS proxy is disabled');
} Type guard
function isProxyDisabledResponse(body) {
return typeof body === 'object' && body !== null && body.error === 'CORS proxy is disabled';
} Try / catch
const res = await fetch(`/cors?url=${encodeURIComponent(target)}`);
if (res.status === 403) {
const body = await res.json().catch(() => ({}));
if (body.error === 'CORS proxy is disabled') {
// fall back to direct fetch or instruct user to set cors: 'allowAll'|'allowWhitelist'
}
throw new Error(body.error ?? 'CORS proxy rejected the request');
} Prevention
- Set `cors: 'allowAll'` or `cors: 'allowWhitelist'` in config.js whenever any module uses the /cors endpoint
- Prefer 'allowWhitelist' so the proxy stays enabled but restricted
- After MagicMirror upgrades, re-check config.js defaults — the cors setting may have changed
- Document in module READMEs whether the /cors proxy is required
- Surface the 403 JSON error in module UIs so users see the config fix instead of silent failure
When it happens
Trigger: A module or client issues a request like `/cors?url=https://...` while `config.cors === 'disabled'` in config.js (or `global.config` was initialized with that value); the request never reaches the URL parsing/SSRF checks because the feature check runs first.
Common situations: A user upgrades MagicMirror and the newer default `cors: 'disabled'` breaks a module that relied on the proxy; a config template copies `cors: 'disabled'` from a hardened/security-focused setup; deploying behind nginx where someone disabled the proxy thinking the webserver handles CORS, while modules still call `/cors?...`.
Related errors
- This device is not allowed to access your mirror. <br> Pleas
- Forbidden: private or reserved addresses are not allowed
- Forbidden: domain not in corsDomainWhitelist
- <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8
- invalid url: ${req.url}
AI-assisted analysis of MagicMirrorOrg/MagicMirror@4b4a59534f (2026-08-31).
Data as JSON: /api/errors/8e69f7c4143ae5a1.
Report an issue: GitHub.