CORS blocking image loading

All my images are hosted on my own server, as I imagine they are supposed to be, and I cannot get the Hosted extension to access the images due to CORS. I’ve done everything I could find and broke down and asked chatGPT a few times and it hasn’t figured anything out on this end. The backend code for CORS is as follows

const cors = require('cors');

// Serve static files from the root directory
app.use(express.static('public'));
app.use(bodyParser.json());

// Add CORS middleware
app.use(cors({
    origin: 'https://8mftrftzbi8nza2ifx7o8wyx7tz82z.ext-twitch.tv', 
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type'],
    credentials: true // Include credentials
}));

// Serve static files from the avatars directory with proper CORS headers
app.use('/avatars', express.static('avatars', {
    setHeaders: (res, path, stat) => {
        res.set('Access-Control-Allow-Origin', 'https://8mftrftzbi8nza2ifx7o8wyx7tz82z.ext-twitch.tv'); 
        res.set('Access-Control-Allow-Credentials', 'true'); // Allow credentials
    }
}));

With this, I am still getting the following error for every single image

GET https://liked-wildly-dolphin.ngrok-free.app/avatars/avatar2.png net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200 (OK)

I forgot to include my helmet config

// Use Helmet for security headers
app.use(helmet());

// Define CSP using Helmet
app.use(
    helmet.contentSecurityPolicy({
        directives: {
            defaultSrc: ["'self'"],
            scriptSrc: ["'self'", "https://cdn.jsdelivr.net", "https://extension-files.twitch.tv", "https://api.sprig.com", "https://liked-wildly-dolphin.ngrok-free.app"],
            styleSrc: ["'self'", "'unsafe-inline'"],
            imgSrc: ["'self'", "https://api.sprig.com", "https://liked-wildly-dolphin.ngrok-free.app"],
            connectSrc: ["'self'", "https://api.twitch.tv", "https://api.sprig.com", "wss://sockets.streamlabs.com", "https://liked-wildly-dolphin.ngrok-free.app"],
            frameSrc: ["'self'"],
            objectSrc: ["'none'"],
            upgradeInsecureRequests: [],
            reportUri: '/report-violation',
            baseUri: ["'self'"],
            fontSrc: ["'self'", "https:"]
        }
    })
);

Did you set your images URL in the CSP configuration in the developer console for your extension?

Please don’t do this is just slows you down and gets the wrong answer as it doesn’t understand the specifics of Twitch Extension. And generally people don’t like helping people that tried AI first, becuase we have to train you off what it said when it’s wrong most of the time.

And all that has happened here is that you setup your server but you didn’t setup Twitch side of things which has to be set in the developer console.

As your server doesn’t serve the extension Twitch does. So in hosted test your helmet config does nothing as your server isn’t called for the HTML.

Edit: to elaborate

You have a CSP and a CORS thing

CORS controls server side what can access the server.
CSP controls what a Client can read from

Helmet is CSP and CORS is CORS

But in Hosted test, the server you build with Helmet attached doesn’t get used as Hosted Test uses Twitch’s server and it’s CSP setup. The CSP for Twitch is defined in the develop console now in your Express’ CSP/Helmet

(Or if you are not in hosted test but local test then the origin doesn’t match as you hard coded the origin on your asset server to the URL for hosted test. But you said you are in hosted test so your helmet config doesn’t apply)

Ah, you’re right. I started the project attempting to push the backend to Twitch and learned that was not gonna happen. I guess helmet was just for that. I actually just now resolved this with a simple line that took me several hours to figure out.

`allowedHeaders: ['Content-Type', 'Cross-Origin-Resource-Policy'],`

helmet lets you simulate hosted test and above locally on your server that serves your HTML (js/css or anything you want to put on twitch’s servers that is static content)

So this module I built GitHub - BarryCarlyon/twitchextensioncsp: Easily test the TwitchExtensionCSP in an Express Server uses helmet and assigns the same rules Twitch has to your local test for your HTML serving.

As the frontend HTML is on a different server to the Extnesion backend or any external assets.

For CORS on my backend/EBS I tend to use a flat cors() unless I need extra security which I generally don’t and the default cors setup works fine.

So app.use(cors()); usually does just fine without “interferring” with the configuration.

Thank you, I will definitely put that module in for testing in the future.

And I guess a flat cors() did work all of a sudden. I added a bunch of headers previously when I was trying to get a script to work from my backend to the extension, but I guess that wasn’t necessary either.

Thank you for all the help!

Well for loading images you don’t even need cors.

You just need to setup the developer console to allow the image domain.