davila7/claude-code-templates · warning

Cross-origin request rejected

Error message

Cross-origin request rejected

What it means

HTTP 403 from the sandbox-server CORS middleware: any request carrying an Origin header not in the ALLOWED_ORIGINS set is rejected before reaching the state-changing endpoints. This is deliberate CSRF-style protection for a local sandbox server.

Source

Thrown at cli-tool/src/sandbox-server.js:74

// CORS middleware — restrict to the local Studio UI origin only.
// A wildcard (`*`) origin combined with the command-executing endpoints below
// lets any web page the developer visits drive requests into this server
// (drive-by RCE). Only allow the same-origin UI served from localhost:PORT.
const ALLOWED_ORIGINS = new Set([
    `http://localhost:${PORT}`,
    `http://127.0.0.1:${PORT}`,
]);
app.use((req, res, next) => {
    const origin = req.headers.origin;
    if (origin && ALLOWED_ORIGINS.has(origin)) {
        res.header('Access-Control-Allow-Origin', origin);
    }
    res.header('Vary', 'Origin');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
    // Reject cross-origin requests outright for the state-changing endpoints.
    if (origin && !ALLOWED_ORIGINS.has(origin)) {
        return res.status(403).json({ success: false, error: 'Cross-origin request rejected' });
    }
    if (req.method === 'OPTIONS') {
        res.sendStatus(200);
    } else {
        next();
    }
});

// JSON parsing middleware
app.use(express.json());

// Store active tasks
const activeTasks = new Map();

// Serve the sandbox interface at root
app.get('/', (req, res) => {
    // Try local file first (when running from npm package)
    const localPath = path.join(__dirname, 'sandbox-interface.html');

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Serve your client from an origin that's in ALLOWED_ORIGINS (check sandbox-server.js for the set) or add your exact origin (scheme+host+port) to it
  2. Use http://localhost:PORT consistently rather than mixing 127.0.0.1 and localhost
  3. If calling from Node/curl (no Origin header), the check is skipped — use a non-browser client for scripting
  4. Confirm you're not accidentally embedding the sandbox URL in an external web page

Example fix

// before
// client served at http://localhost:5173, only localhost:3000 allowed -> 403
// after (sandbox-server.js)
const ALLOWED_ORIGINS = new Set(['http://localhost:3000', 'http://localhost:5173']);
Defensive patterns

Strategy: validation

Validate before calling

const allowed = new Set(['http://localhost:3000']); // mirror server set
if (typeof window !== 'undefined' && !allowed.has(window.location.origin)) {
  console.warn('requests to sandbox server will be rejected from', window.location.origin);
}

Try / catch

catch (e) { if (e.status === 403 && /Cross-origin/.test(e.message)) showOriginHint(); else throw e; }

Prevention

When it happens

Trigger: A browser page on a non-allowed origin (e.g. an open port on localhost with a different port number, or a public website) makes a fetch to the sandbox server with credentials/content-type that attach an Origin header, and that origin isn't in ALLOWED_ORIGINS.

Common situations: Serving your frontend on a different port than the one allow-listed (localhost:3000 vs localhost:5173); accessing via 127.0.0.1 when only localhost is allowed (they are distinct origins); a malicious or accidental cross-site request from a web page you have open.

Related errors


AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28). Data as JSON: /api/errors/fff4b5482128fa0f. Report an issue: GitHub.