Skip to content

Commit

Permalink
improved security by change CORS defaults to more secure values that …
Browse files Browse the repository at this point in the history
…prevent cross-site requests by default
  • Loading branch information
jamesdbloom committed Mar 16, 2022
1 parent 3fc1bb5 commit 7e547f9
Show file tree
Hide file tree
Showing 14 changed files with 289 additions and 97 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- changed client to launch dashboard in HTTP (not HTTPS) to avoid issues with self-signed certificates
- simplified the body field for response template model
- improved XML matching by ignoring element order
- improved security by change CORS defaults to more secure values that prevent cross-site requests by default

### Fixed
- worked around JDK error 'flip()Ljava/nio/ByteBuffer; does not exist in class java.nio.ByteBuffer'
Expand Down
82 changes: 61 additions & 21 deletions jekyll-www.mock-server.com/mock_server/CORS_support.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,104 @@
lastmod: 2019-11-10T08:00:00+01:00
---

<p>MockServer and the proxy has support for CORS. By default CORS support is enabled for the REST API and disabled for all other requests (such as when expectations are matched).</p>
<p>MockServer and the proxy has support for CORS. By default, CORS support is not enabled for the Control Plane API and or for mocked response, such as, when expectations are matched, or proxied requests.</p>

<p>When CORS support is enabled the following headers are added:</p>
<p>When CORS support is enabled the following headers are be added by default:</p>

<pre class="prettyprint code"><code class="code">Access-Control-Allow-Origin: ""
Access-Control-Allow-Methods: ""
Access-Control-Allow-Headers: ""
Access-Control-Expose-Headers: ""
Access-Control-Allow-Credentials: "false"
Access-Control-Max-Age: "0"</code></pre>

<p style="color: darkred"><strong>NOTE:</strong> the default configuration will prevent all cross-site requests</p>

<p>To avoid security risk from cross-site requests CORS headers should be configured to the minimum required values for your use case, using the CORS <a href="#cors_configuration">configuration properties</a>, as below.</p>

<p>A more permission approach that enables most use cases would configure the CORS headers, as follows:</p>

<pre class="prettyprint code"><code class="code">Access-Control-Allow-Origin: "*"
Access-Control-Allow-Methods: "CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE"
Access-Control-Allow-Headers: "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary"
Access-Control-Expose-Headers: "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary"
Access-Control-Allow-Headers: "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization"
Access-Control-Expose-Headers: "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization"
Access-Control-Max-Age: "300"</code></pre>

<p>For example to enable a more permission approach for cross-site requests use <strong>ConfigurationProperties</strong> class as follows:</p>

<pre class="prettyprint code"><code class="code">ConfigurationProperties.enableCORSForAllResponses(true);
ConfigurationProperties.corsAllowOrigin("*");
ConfigurationProperties.corsAllowMethods("CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE");
ConfigurationProperties.corsAllowHeaders("Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization");
ConfigurationProperties.corsMaxAgeInSeconds(300);</code></pre>

{% include_subpage _includes/cors_configuration.html %}

<a id="cors_examples" class="anchor" href="#cors_examples">&nbsp;</a>

<h2>Examples:</h2>

<p>CORS support can be enabled for all enabled for all requests-responses by enabling the <strong>enableCORSForAllResponses</strong> property.</p>

<button id="button_enabled_cors_for_all_response" class="accordion">enabled CORS for all requests-responses</button>
<button id="button_enabled_permissive_cors_for_all_response" class="accordion">enabled permissive CORS for all responses</button>
<div class="panel">
<button class="accordion inner">Java</button>
<div class="panel">
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.enableCORSForAllResponses(true)</code></pre>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.enableCORSForAllResponses(true);
ConfigurationProperties.corsAllowMethods("CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE");
ConfigurationProperties.corsAllowHeaders("Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization");
ConfigurationProperties.corsAllowCredentials(true);
ConfigurationProperties.corsMaxAgeInSeconds(300);</code></pre>
</div>
<button class="accordion inner">Command Line</button>
<div class="panel">
<pre class="prettyprint lang-bash code"><code class="code">java -Dmockserver.enableCORSForAllResponses=true -jar "~/Downloads/mockserver-netty-5.12.0-shaded.jar" -serverPort 1080</code></pre>
<pre class="prettyprint lang-bash code"><code class="code">java -Dmockserver.enableCORSForAllResponses=true \
-Dmockserver.corsAllowMethods="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE" \
-Dmockserver.corsAllowHeaders="Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization" \
-Dmockserver.corsAllowCredentials="true" \
-Dmockserver.corsMaxAgeInSeconds="300" \
-jar "~/Downloads/mockserver-netty-5.12.0-shaded.jar" -serverPort 1080</code></pre>
</div>
<button class="accordion inner">JavaScript: mockserver-node</button>
<div class="panel">
<pre class="prettyprint lang-javascript code"><code class="code">var mockserver = require('mockserver-node');
mockserver.start_mockserver({
serverPort: 1080,
systemProperties: "-Dmockserver.enableCORSForAllResponses=true"
});
}</code></pre>
systemProperties: "-Dmockserver.enableCORSForAllResponses=true " +
"-Dmockserver.corsAllowMethods=\"CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE\" " +
"-Dmockserver.corsAllowHeaders=\"Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization\" " +
"-Dmockserver.corsAllowCredentials=\"true\" " +
"-Dmockserver.corsMaxAgeInSeconds=\"300\""
});</code></pre>
</div>
</div>

<p>CORS support is enabled by default for the REST API. CORS support can be disabled the REST API by disabling the <strong>enableCORSForAPI</strong> property.</p>

<button id="button_disabled_cors_for_rest_api" class="accordion">disabled CORS for REST API</button>
<button id="button_enabled_permissive_cors_for_control_plane_api" class="accordion">enabled permissive CORS for control plane API</button>
<div class="panel">
<button class="accordion inner">Java</button>
<div class="panel">
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.enableCORSForAPI(false)</code></pre>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.enableCORSForAPI(true);
ConfigurationProperties.corsAllowMethods("CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE");
ConfigurationProperties.corsAllowHeaders("Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization");
ConfigurationProperties.corsAllowCredentials(true);
ConfigurationProperties.corsMaxAgeInSeconds(300);</code></pre>
</div>
<button class="accordion inner">Command Line</button>
<div class="panel">
<pre class="prettyprint lang-bash code"><code class="code">java -Dmockserver.enableCORSForAPI=false -jar "~/Downloads/mockserver-netty-5.12.0-shaded.jar" -serverPort 1080</code></pre>
<pre class="prettyprint lang-bash code"><code class="code">java -Dmockserver.enableCORSForAPI=true \
-Dmockserver.corsAllowMethods="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE" \
-Dmockserver.corsAllowHeaders="Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization" \
-Dmockserver.corsAllowCredentials="true" \
-Dmockserver.corsMaxAgeInSeconds="300" \
-jar "~/Downloads/mockserver-netty-5.12.0-shaded.jar" -serverPort 1080</code></pre>
</div>
<button class="accordion inner">JavaScript: mockserver-node</button>
<div class="panel">
<pre class="prettyprint lang-javascript code"><code class="code">var mockserver = require('mockserver-node');
mockserver.start_mockserver({
serverPort: 1080,
systemProperties: "-Dmockserver.enableCORSForAPI=false"
});
}</code></pre>
systemProperties: "-Dmockserver.enableCORSForAPI=true " +
"-Dmockserver.corsAllowMethods=\"CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE\" " +
"-Dmockserver.corsAllowHeaders=\"Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization\" " +
"-Dmockserver.corsAllowCredentials=\"true\" " +
"-Dmockserver.corsMaxAgeInSeconds=\"300\""
});</code></pre>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ <h2>CORS Configuration:</h2>
<p>Property File:</p>
<pre class="code" style="padding: 2px;"><code class="code">mockserver.enableCORSForAPI=...</code></pre>
<p>Example:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.enableCORSForAPI="false"</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.enableCORSForAPI="true"</code></pre>
</div>

<button id="button_configuration_enable_cors_for_all_responses" class="accordion title"><strong>Enable CORS For All Responses</strong></button>
Expand All @@ -34,27 +34,27 @@ <h2>CORS Configuration:</h2>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.enableCORSForAllResponses="true"</code></pre>
</div>

<button id="button_configuration_cors_allow_headers" class="accordion title"><strong>CORS Allow Headers Value</strong></button>
<button id="button_configuration_cors_allow_origin" class="accordion title"><strong>CORS Allow Origin Value</strong></button>
<div class="panel title">
<p>Default value used for CORS in the <span class="constant">access-control-allow-headers</span> and <span class="constant">access-control-expose-headers</span> headers.</p>
<p>In addition to this default value any headers specified in the request header <span class="constant">access-control-request-headers</span> also get added to <span class="constant">access-control-allow-headers</span> and <span class="constant">access-control-expose-headers</span> headers in a CORS response.</p>
<p>Type: <span class="keyword">string</span> Default: <span class="this_value">Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization</span></p>
<p>The value used for CORS in the <span class="constant">access-control-allow-origin</span> header.</p>
<p><strong>Note:</strong> To ensure <span class="constant">access-control-allow-credentials</span> works correct, when <a href="#button_configuration_cors_allow_credentials">corsAllowCredentials</a> is <strong>true</strong> the CORS header <span class="constant">access-control-allow-origin</span> will set its value using the <span class="constant">origin</span> header on requests instead of <a href="#button_configuration_cors_allow_origin">corsAllowCredentials</a> property.</p>
<p>Type: <span class="keyword">string</span> Default: <span class="this_value">""</span></p>
<p>Java Code:</p>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.corsAllowHeaders(String corsAllowHeaders)</code></pre>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.corsAllowOrigin(String corsAllowOrigin)</code></pre>
<p>System Property:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowHeaders=...</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowOrigin=...</code></pre>
<p>Environment Variable:</p>
<pre class="code" style="padding: 2px;"><code class="code">MOCKSERVER_CORS_ALLOW_HEADERS=...</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">MOCKSERVER_CORS_ALLOW_ORIGIN=...</code></pre>
<p>Property File:</p>
<pre class="code" style="padding: 2px;"><code class="code">mockserver.corsAllowHeaders=...</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">mockserver.corsAllowOrigin=...</code></pre>
<p>Example:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowHeaders="Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization"</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowOrigin="*"</code></pre>
</div>

<button id="button_configuration_cors_allow_methods" class="accordion title"><strong>CORS Allow Methods Value</strong></button>
<div class="panel title">
<p>The value used for CORS in the <span class="constant">access-control-allow-methods</span> header.</p>
<p>Type: <span class="keyword">string</span> Default: <span class="this_value">CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE</span></p>
<p>Type: <span class="keyword">string</span> Default: <span class="this_value">""</span></p>
<p>Java Code:</p>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.corsAllowMethods(String corsAllowMethods)</code></pre>
<p>System Property:</p>
Expand All @@ -67,10 +67,28 @@ <h2>CORS Configuration:</h2>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowMethods="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, PATCH, TRACE"</code></pre>
</div>

<button id="button_configuration_cors_allow_headers" class="accordion title"><strong>CORS Allow Headers Value</strong></button>
<div class="panel title">
<p>Default value used for CORS in the <span class="constant">access-control-allow-headers</span> and <span class="constant">access-control-expose-headers</span> headers.</p>
<p>In addition to this default value any headers specified in the request header <span class="constant">access-control-request-headers</span> also get added to <span class="constant">access-control-allow-headers</span> and <span class="constant">access-control-expose-headers</span> headers in a CORS response.</p>
<p>Type: <span class="keyword">string</span> Default: <span class="this_value">""</span></p>
<p>Java Code:</p>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.corsAllowHeaders(String corsAllowHeaders)</code></pre>
<p>System Property:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowHeaders=...</code></pre>
<p>Environment Variable:</p>
<pre class="code" style="padding: 2px;"><code class="code">MOCKSERVER_CORS_ALLOW_HEADERS=...</code></pre>
<p>Property File:</p>
<pre class="code" style="padding: 2px;"><code class="code">mockserver.corsAllowHeaders=...</code></pre>
<p>Example:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowHeaders="Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary, Authorization"</code></pre>
</div>

<button id="button_configuration_cors_allow_credentials" class="accordion title"><strong>CORS Allow Credentials Value</strong></button>
<div class="panel title">
<p>The value used for CORS in the <span class="constant">access-control-allow-credentials</span> header.</p>
<p>Type: <span class="keyword">boolean</span> Default: <span class="this_value">true</span></p>
<p><strong>Note:</strong> To ensure <span class="constant">access-control-allow-credentials</span> works correct, when <a href="#button_configuration_cors_allow_credentials">corsAllowCredentials</a> is <strong>true</strong> the CORS header <span class="constant">access-control-allow-origin</span> will set its value using the <span class="constant">origin</span> header on requests instead of <a href="#button_configuration_cors_allow_origin">corsAllowCredentials</a> property.</p>
<p>Type: <span class="keyword">boolean</span> Default: <span class="this_value">false</span></p>
<p>Java Code:</p>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.corsAllowCredentials(boolean allow)</code></pre>
<p>System Property:</p>
Expand All @@ -80,13 +98,13 @@ <h2>CORS Configuration:</h2>
<p>Property File:</p>
<pre class="code" style="padding: 2px;"><code class="code">mockserver.corsAllowCredentials=...</code></pre>
<p>Example:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowCredentials=false</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsAllowCredentials="true"</code></pre>
</div>

<button id="button_configuration_cors_max_age" class="accordion title"><strong>CORS Max Age Value</strong></button>
<div class="panel title">
<p>The value used for CORS in the <span class="constant">access-control-max-age</span> header.</p>
<p>Type: <span class="keyword">int</span> Default: <span class="this_value">300</span></p>
<p>Type: <span class="keyword">int</span> Default: <span class="this_value">0</span></p>
<p>Java Code:</p>
<pre class="prettyprint lang-java code"><code class="code">ConfigurationProperties.corsMaxAgeInSeconds(int maxAgeInSeconds)</code></pre>
<p>System Property:</p>
Expand All @@ -96,5 +114,5 @@ <h2>CORS Configuration:</h2>
<p>Property File:</p>
<pre class="code" style="padding: 2px;"><code class="code">mockserver.corsMaxAgeInSeconds=...</code></pre>
<p>Example:</p>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsMaxAgeInSeconds=100</code></pre>
<pre class="code" style="padding: 2px;"><code class="code">-Dmockserver.corsMaxAgeInSeconds=300</code></pre>
</div>
Loading

0 comments on commit 7e547f9

Please sign in to comment.