<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cors on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/cors/</link><description>Recent content in Cors on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 01 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/cors/index.xml" rel="self" type="application/rss+xml"/><item><title>CORS, What is it good for?</title><link>https://blog.iankulin.com/cors-what-is-it-good-for/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/cors-what-is-it-good-for/</guid><description>&lt;p&gt;Imagine you have two browser tabs open, one to your bank, and one to evil-site.com&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────┐┌──────────────┐ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ BANK ││ EVIL-SITE │ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────┴┴ ┴────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;evil-site.com, knowing you&amp;rsquo;re probably authenticated to your bank, sends a request to it for some data.&lt;/p&gt;
&lt;p&gt;Luckily, your browser complies with the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Same-origin_policy"&gt;Same-origin policy&lt;/a&gt; and won&amp;rsquo;t let the evil-site.com page see the results of this query when the response arrives.&lt;/p&gt;
&lt;p&gt;The basic rule of Same-origin policy is that the Javascript in a web page can only read responses from the same &lt;em&gt;origin&lt;/em&gt; where the &lt;em&gt;origin&lt;/em&gt; is the combination of scheme (http vs https), hostname, and port.&lt;/p&gt;
&lt;p&gt;What URLs have the same origin as &lt;code&gt;https://evil-site.com&lt;/code&gt;?&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;URL / Resource&lt;/th&gt;
					&lt;th&gt;Same origin&lt;/th&gt;
					&lt;th&gt;Why&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://evil-site.com/page&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Yes&lt;/td&gt;
					&lt;td&gt;Same protocol, host, and port&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://evil-site.com:443/api&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Yes&lt;/td&gt;
					&lt;td&gt;Port &lt;code&gt;443&lt;/code&gt; matches HTTPS&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://sub.evil-site.com&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
					&lt;td&gt;Different host/subdomain&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http://evil-site.com&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http&lt;/code&gt; vs &lt;code&gt;https&lt;/code&gt; protocol&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://evil-site.com:8443&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
					&lt;td&gt;Different port&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://evil-site.org&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
					&lt;td&gt;Different domain&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://www.evil-site.com&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;No&lt;/td&gt;
					&lt;td&gt;Different &lt;code&gt;www&lt;/code&gt; subdomain&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The purpose of the same-origin policy (which has been around since about 1995) is to stop a malicious script on one page accessing the data on another page.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s a browser protocol - it doesn&amp;rsquo;t apply to &lt;code&gt;curl&lt;/code&gt; or other methods of fetching resources&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s a Javascript thing - you can still fetch resources such as images, scripts, css etc from other origins in your page using HTML tags.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cors"&gt;CORS&lt;/h2&gt;
&lt;p&gt;So the same-origin policy is a pretty great sensible restriction for preventing a foreseeable and real problem in allowing web sites to run code. But it does cause some pain. Imagine this: We have a pretty React front-end application on our company website at &lt;a href="https://example.com"&gt;https://example.com&lt;/a&gt; and we want it to fetch data from &lt;a href="https://api.example.com"&gt;https://api.example.com&lt;/a&gt; It can make the request, and &lt;a href="https://api.example.com"&gt;https://api.example.com&lt;/a&gt; can send the data, but our application can never see it because the browser says &amp;lsquo;hang on, this is against my same-origin policy because these two addresses are not the same origin&amp;rsquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────┐ ┌─────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ https://example.com │ │ https://api.example.com │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─────────────────────┘ └─────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is obviously bad, so what we need is a safe way to get around the same-origin policy for just this site. &lt;a href="https://api.example.com"&gt;https://api.example.com&lt;/a&gt; needs some way to say &amp;ldquo;I&amp;rsquo;m happy for &lt;a href="https://example.com"&gt;https://example.com&lt;/a&gt; to fetch my data even though we&amp;rsquo;re on different origins&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Welcome to Cross Origin Resource Sharing (CORS).&lt;/p&gt;
&lt;p&gt;All &lt;a href="https://api.example.com"&gt;https://api.example.com&lt;/a&gt; has to do is set a header in its response so that the browser knows this is allowed. The headers in the response from &lt;a href="https://api.example.com"&gt;https://api.example.com&lt;/a&gt; would include:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Access-Control-Allow-Origin: https://example.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or perhaps if &lt;a href="https://api.example.com"&gt;https://api.example.com&lt;/a&gt; is a public API that&amp;rsquo;s happy for anyone to use it&amp;rsquo;s data, it might say:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Access-Control-Allow-Origin: *
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item></channel></rss>