Permalink
Browse files

Separate browser policy functions into two packages.

* browser-policy uses browser-policy-framing and browser-policy-content, both of
  which set default policies when they are used. This way you get a default
  policy when you add a browser policy package, but you can pick and choose
  different packages if you only want to think about one of them.
* The two packages use different namespaces: BrowserPolicy.framing and
  BrowserPolicy.content, which meant some functions got renamed (e.g. not using
  "framing" or "content in the function name when it's already in the
  namespace).
  • Loading branch information...
1 parent d5159ae commit b5286b941a77a1bdd57abb1ea01385eeaa62f7ea Emily Stark committed Oct 3, 2013
@@ -6,49 +6,53 @@
enforced by newer browsers. These policies help you prevent and mitigate common
attacks like cross-site scripting and clickjacking.
-`browser-policy` lets you configure the HTTP headers X-Frame-Options and
-Content-Security-Policy. X-Frame-Options tells the browser which websites are
-allowed to frame your app. You should only let trusted websites frame your app,
-because malicious sites could harm your users
-with <a href="https://www.owasp.org/index.php/Clickjacking">clickjacking
+When you add `browser-policy` to your app, you get default configurations for
+the HTTP headers X-Frame-Options and Content-Security-Policy. X-Frame-Options
+tells the browser which websites are allowed to frame your app. You should only
+let trusted websites frame your app, because malicious sites could harm your
+users with <a href="https://www.owasp.org/index.php/Clickjacking">clickjacking
attacks</a>.
<a href="https://developer.mozilla.org/en-US/docs/Security/CSP/Introducing_Content_Security_Policy">Content-Security-Policy</a>
tells the browser where your app can load content from, which encourages safe
practices and mitigates the damage of a cross-site-scripting attack.
+`browser-policy` also provides functions for you to configure these policies if
+the defaults are not suitable.
-For most apps, we recommend that you take the following steps when using
-`browser-policy`:
-
-* Call `BrowserPolicy.enableContentSecurityPolicy()` to enable a starter policy
-for your app. With this starter policy, your app's client code will be able to
-load content (images, scripts, fonts, etc.) only from its own origin, except
-that XMLHttpRequests and WebSocket connections can go to any origin. Further,
-your app's client code will not be able to use functions such as `eval()` that
-convert strings to code.
-* You can use the functions described below to customize the content
-security policy. If your app does not need any inline Javascript such as inline
-`<script>` tags, we recommend that you modify the policy by calling
-`BrowserPolicy.disallowInlineScripts()` in server code. This will result in one
-extra round trip when your app is loaded, but will help prevent cross-site
-scripting attacks by disabling all scripts except those loaded from a `script
-src` attribute.
-* If your app does not need to be framed by other websites, call
-`BrowserPolicy.allowFramingBySameOrigin()` to help prevent clickjacking attacks.
+If you only want to use Content-Security-Policy or X-Frame-Options but not both,
+you can add the individual packages `browser-policy-content` or
+`browser-policy-framing` instead of `browser-policy`.
+
+For most apps, we recommend that you take the following steps:
+
+* Add `browser-policy` to your app to enable a starter policy. With this starter
+policy, your app's client code will be able to load content (images, scripts,
+fonts, etc.) only from its own origin, except that XMLHttpRequests and WebSocket
+connections can go to any origin. Further, your app's client code will not be
+able to use functions such as `eval()` that convert strings to code. Users'
+browsers will only let your app be framed by web pages on the same origin as
+your app.
+* You can use the functions described below to customize the policies. If your
+app does not need any inline Javascript such as inline `<script>` tags, we
+recommend that you modify the policy by calling
+`BrowserPolicy.content.disallowInlineScripts()` in server code. This will result
+in one extra round trip when your app is loaded, but will help prevent
+cross-site scripting attacks by disabling all scripts except those loaded from a
+`script src` attribute.
Meteor determines the browser policy when the server starts up, so you should
call `BrowserPolicy` functions in top-level application code or in
`Meteor.startup`.
#### Frame options
-You can use the following functions to specify which websites are allowed to
-frame your app. By default, any website is allowed.
+By default, only web pages on the same origin as your app are allowed to frame
+your app. You can use the following functions to modify this policy.
<dl class="callbacks">
-{{#dtdd "BrowserPolicy.disallowFraming()"}}
+{{#dtdd "BrowserPolicy.framing.disallow()"}}
Your app will never render inside a frame or iframe.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.restrictFramingToOrigin(origin)"}}
+{{#dtdd "BrowserPolicy.framing.restrictToOrigin(origin)"}}
Your app will only render inside frames loaded by `origin`. You can only call
this function once with a single origin, and cannot use wildcards or specify
multiple origins that are allowed to frame your app. (This is a limitation of
@@ -60,47 +64,46 @@
{{/warning}}
{{/dtdd}}
-{{#dtdd "BrowserPolicy.restrictFramingToSameOrigin()"}}
-Your app will only render inside frames loaded by webpages on the same origin as
-your app.
+{{#dtdd "BrowserPolicy.framing.allowAll()"}}
+This unsets the X-Frame-Options header, so that your app can be framed by
+any webpage.
{{/dtdd}}
</dl>
#### Content options
You can use the functions in this section to control how different types of
-content can be loaded on your site. In order to use any of these functions, you
-must first call `BrowserPolicy.enableContentSecurityPolicy()`, which enables the
-starter policy described above. This section covers additional functions that
-you can use to tighten or relax restrictions on what content your app can use.
+content can be loaded on your site.
You can use the following functions to adjust policies on where Javascript and
CSS can be run:
<dl class="callbacks">
-{{#dtdd "BrowserPolicy.allowInlineScripts()"}}
+{{#dtdd "BrowserPolicy.content.allowInlineScripts()"}}
Allows inline `<script>` tags, `javascript:` URLs, and inline event handlers.
+The default policy already allows inline scripts.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.disallowInlineScripts()"}}
+{{#dtdd "BrowserPolicy.content.disallowInlineScripts()"}}
Disallows inline Javascript. Calling this function results in an extra
round-trip on page load to retrieve Meteor runtime configuration that is usually
part of an inline script tag.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.allowEval()"}}
+{{#dtdd "BrowserPolicy.content.allowEval()"}}
Allows the creation of Javascript code from strings using function such as `eval()`.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.disallowEval()"}}
-Disallows eval and related functions.
+{{#dtdd "BrowserPolicy.content.disallowEval()"}}
+Disallows eval and related functions. The default policy already disallows eval.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.allowInlineStyles()"}}
-Allows inline style tags and style attributes.
+{{#dtdd "BrowserPolicy.content.allowInlineStyles()"}}
+Allows inline style tags and style attributes. The default policy already allows
+inline styles.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.disallowInlineStyles()"}}
+{{#dtdd "BrowserPolicy.content.disallowInlineStyles()"}}
Disallows inline CSS.
{{/dtdd}}
</dl>
@@ -110,7 +113,7 @@
script, object, image, media, font, and connect.
<dl class="callbacks">
-{{#dtdd "BrowserPolicy.allow&lt;ContentType&gt;Origin(origin)"}}
+{{#dtdd "BrowserPolicy.content.allow&lt;ContentType&gt;Origin(origin)"}}
Allows this type of content to be loaded from the given origin. `origin` is a
string and can include an optional scheme (such as `http` or `https`), an
optional wildcard at the beginning, and an optional port which can be a
@@ -119,34 +122,41 @@
origins to specify a whitelist of allowed origins.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.allow&lt;ContentType&gt;DataUrl()"}}
+{{#dtdd "BrowserPolicy.content.allow&lt;ContentType&gt;DataUrl()"}}
Allows this type of content to be loaded from a `data:` URL.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.allow&lt;ContentType&gt;SameOrigin()"}}
+{{#dtdd "BrowserPolicy.content.allow&lt;ContentType&gt;SameOrigin()"}}
Allows this type of content to be loaded from the same origin as your app.
{{/dtdd}}
-{{#dtdd "BrowserPolicy.disallow&lt;ContentType&gt;()"}}
+{{#dtdd "BrowserPolicy.content.disallow&lt;ContentType&gt;()"}}
Disallows this type of content on your app.
{{/dtdd}}
</dl>
-These functions are also defined for the content type `AllContent`, which is a
-shorthand for calling one of the above functions once for each content type.
-For example, if you want to allow the origin `https://foo.com` for all types of
-content but you want to disable `<object>` tags, you can call
-`BrowserPolicy.allowAllContentOrigin("https://foo.com")` followed by
-`BrowserPolicy.disallowObject()`.
+You can also set policies for all these types of content at once, using these
+functions:
+
+* `BrowserPolicy.content.allowSameOriginForAll()`,
+* `BrowserPolicy.content.allowDataUrlForAll()`,
+* `BrowserPolicy.content.allowOriginForAll(origin)`
+* `BrowserPolicy.content.disallowAll()`
+
+For example, if you want to allow the
+origin `https://foo.com` for all types of content but you want to disable
+`<object>` tags, you can call
+`BrowserPolicy.content.allowOriginForAll("https://foo.com")` followed by
+`BrowserPolicy.content.disallowObject()`.
-Other examples of using the `BrowserPolicy` API:
+Other examples of using the `BrowserPolicy.content` API:
-* `BrowserPolicy.disallowObject()` causes the browser to disallow all
-`<object>` tags.
-* `BrowserPolicy.allowImageOrigin("https://example.com")`
+* `BrowserPolicy.content.disallowFont()` causes the browser to disallow all
+`<font>` tags.
+* `BrowserPolicy.content.allowImageOrigin("https://example.com")`
allows images to have their `src` attributes point to images served from
`https://example.com`.
-* `BrowserPolicy.allowConnectOrigin("https://example.com")` allows XMLHttpRequest
+* `BrowserPolicy.content.allowConnectOrigin("https://example.com")` allows XMLHttpRequest
and WebSocket connections to `https://example.com`.
@@ -0,0 +1 @@
+.build*
@@ -0,0 +1,27 @@
+BrowserPolicy = {};
+
+var inTest = false;
+
+BrowserPolicy._runningTest = function () {
+ return inTest;
+};
+
+BrowserPolicy._setRunningTest = function () {
+ inTest = true;
+};
+
+WebApp.connectHandlers.use(function (req, res, next) {
+ // Never set headers inside tests because they could break other tests.
+ if (BrowserPolicy._runningTest())
+ return next();
+
+ var xFrameOptions = BrowserPolicy.framing &&
+ BrowserPolicy.framing._constructXFrameOptions();
+ var csp = BrowserPolicy.content &&
+ BrowserPolicy.content._constructCsp();
+ if (xFrameOptions)
+ res.setHeader("X-Frame-Options", xFrameOptions);
+ if (csp)
+ res.setHeader("Content-Security-Policy", csp);
+ next();
+});
@@ -0,0 +1,10 @@
+Package.describe({
+ summary: "Common code for browser-policy packages",
+ internal: true
+});
+
+Package.on_use(function (api) {
+ api.use('webapp', 'server');
+ api.add_files('browser-policy-common.js', 'server');
+ api.export('BrowserPolicy', 'server');
+});
@@ -0,0 +1 @@
+.build*
Oops, something went wrong.

0 comments on commit b5286b9

Please sign in to comment.