The following cheat sheet serves as a guide for implementing HTML 5 in a secure fashion.

The following cheat sheet serves as a guide for implementing HTML 5 in a secure fashion.

−

== Cross Origin Resource Sharing ==

+

= General Guidelines =

−

*Validate URLs passed to <tt>XMLHttpRequest.open</tt>, current browsers allow these URLs to be cross domain and this behavior can lead to code injection by a remote attacker. Pay special attention to absolute URLs.

+

== Communication APIs ==

+

+

=== Web Messaging ===

+

+

Web Messaging, also known as Cross Domain Messaging provides a means of messaging between documents from different origins in a way which is generally safer than the multiple hacks used in the past to accomplish this task, however, there are still some recommendations to keep in mind:

+

+

*When posting a message, explicitly state the expected origin as the second argument to <tt>postMessage</tt> rather than <tt>*</tt> in order to prevent sending the message to an unknown origin after a redirect or some other means of the target window's origin changing.

+

*The receiving page should '''always''':

+

**Check the <tt>origin</tt> attribute of the sender to verify the data is originating from the expected location, and

+

**Perform input validation on the <tt>data</tt> attribute of the event to ensure it's in the desired format.

+

*Don't assume you have control over data attribute. Single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] flaw in sending page allows attacker to send messages of any given format.

+

*Both pages should only interpret the exchanged messages as '''data'''. Never evaluate passed messages as code (e.g. via eval() )&nbsp;or insert it to a page DOM (e.g. via&nbsp;innerHTML) as that would create a DOM based XSS vulnerability. For more information see [[DOM based XSS Prevention Cheat Sheet|DOM based XSS Prevention Cheat Sheet]].

+

*To assign the data value to an element, instead of using a insecure method like <tt>element.innerHTML = data;</tt> use the safer option <tt>element.textContent = data;</tt>

+

*Check the origin properly exactly to match the FQDN(s) you expect. Note that the following code: <tt> if(message.orgin.indexOf(".owasp.org")!=-1) { /* ... */ }</tt> is very insecure and will not have the desired behavior as www.owasp.org.attacker.com will match.

+

*If you need to embed external content/untrusted gadgets and allow user-controlled scripts which is highly discouraged, consider use a JavaScript rewriting framework such as [http://code.google.com/p/google-caja/ Google Caja] or check the information on [[#Sandboxed frames|sandboxed frames]]

+

+

=== Cross Origin Resource Sharing ===

+

+

*Validate URLs passed to <tt>XMLHttpRequest.open</tt>, current browsers allow these URLs to be cross domain and this behavior can lead to code injection by a remote attacker. Pay extra attention to absolute URLs.

*Ensure that URLs responding with <tt>Access-Control-Allow-Origin: *</tt> do not include any sensitive content or information that might aid attacker in further attacks. Use <tt>Access-Control-Allow-Origin</tt> header only on chosen URLs that need to be accessed cross-domain. Don't use the header for the whole domain.

*Ensure that URLs responding with <tt>Access-Control-Allow-Origin: *</tt> do not include any sensitive content or information that might aid attacker in further attacks. Use <tt>Access-Control-Allow-Origin</tt> header only on chosen URLs that need to be accessed cross-domain. Don't use the header for the whole domain.

*Take special care when using <tt>Access-Control-Allow-Credentials: true</tt> response header. Whitelist the allowed Origins and never echo back the <tt>Origin</tt> request header in <tt>Access-Control-Allow-Origin</tt>.

*Take special care when using <tt>Access-Control-Allow-Credentials: true</tt> response header. Whitelist the allowed Origins and never echo back the <tt>Origin</tt> request header in <tt>Access-Control-Allow-Origin</tt>.

Line 11:

Line 29:

*Keep in mind that CORS does not prevent the requested data from going to an un-authenticated location - it's still important for the server to perform usual [[Cross-Site Request Forgery (CSRF)|CSRF]] prevention.

*Keep in mind that CORS does not prevent the requested data from going to an un-authenticated location - it's still important for the server to perform usual [[Cross-Site Request Forgery (CSRF)|CSRF]] prevention.

*While the RFC recommends a pre-flight request with the <tt>OPTIONS</tt> verb, current implementations might not perform this request, so it's important that "ordinary" (<tt>GET</tt> and <tt>POST</tt>) requests perform any access control necessary.

*While the RFC recommends a pre-flight request with the <tt>OPTIONS</tt> verb, current implementations might not perform this request, so it's important that "ordinary" (<tt>GET</tt> and <tt>POST</tt>) requests perform any access control necessary.

−

*For performance reasons pre-flight requests may be cached in client-side for certain amount of time. The security model of CORS can be bypassed in case of header injection vulnerabilities in combination with pre-flight caching so add measures to prevent [[HTTP_Response_Splitting]] vulnerabilities in server side.

+

*For performance reasons pre-flight requests may be cached in client-side for certain amount of time (controlled by Access-Control-Max-Age header). The security model of CORS can be bypassed in case of header injection vulnerabilities in combination with pre-flight caching so add measures to prevent [[HTTP_Response_Splitting]] vulnerabilities in server side.

*Don't rely only on the Origin header for Access Control checks. Browser always sends this header in CORS requests, but may be spoofed outside the browser. Application-level protocols should be used to protect sensitive data.

−

== Local Storage (a.k.a. Offline Storage, Web Storage) ==

+

=== WebSockets ===

−

*Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

+

*Drop backward compatibility in implemented client/servers and use only protocol versions above hybi-00. Popular Hixie-76 version (hiby-00) and olders are outdated and insecure.

+

*Recommended version supported in latest versions of all current browsers is [http://tools.ietf.org/html/rfc6455 RFC 6455] (Supported by Firefox 11+, Chrome 16+, Safari 6, Opera 12.50 and IE10).

+

*While it is relatively easy to tunnel TCP services through WebSockets (e.g. VNC, FTP), doing so enables access to these tunneled services for the in-browser attacker in case of a Cross-Site-Scripting attack. These services might also be called directly from a malicious page or program.

*Process the messages received by the websocket as data. Don't try to assign it directly to the DOM nor evaluate as code. If the response is JSON never use the insecure eval() function, use the safe option JSON.parse() instead.

+

*Endpoints exposed through <tt>ws://</tt> protocol are easily reversible to plaintext. Only <tt>wss://</tt> (WebSockets over SSL/TLS) should be used for protection against Man-In-The-Middle attacks

+

*Spoofing the client is possible outside browser, so WebSockets server should be able to handle incorrect/malicious input. Always validate input coming from the remote site, as it might have been altered.

+

*When implementing servers, check the <tt>Origin:</tt> header in Websockets handshake. Though it might be spoofed outside browser, browsers always add the Origin of the page which initiated Websockets connection.

+

*As WebSockets client in browser is accessible through Javascript calls, all Websockets communication can be spoofed or hijacked through [[Cross Site Scripting Flaw|Cross-Site-Scripting]]. Always validate data coming through WebSockets connection.

+

+

=== Server-Sent Events ===

+

+

*Validate URLs passed to the <tt>EventSource</tt> constructor, even though only same-origin URLs are allowed.

+

*As mentioned before, process the messages (<tt>event.data</tt>) as data and never evaluate the content as HTML or script code.

+

*Check always the origin attribute of the message (<tt>event.origin</tt>) to ensure the message is coming from a trusted domain, use a whitelist approach.

+

+

== Storage APIs ==

+

+

=== Local Storage ===

+

+

*Also known as Offline Storage, Web Storage. Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

*Use the object sessionStorage instead of localStorage if persistent storage is not needed. sessionStorage object is available only to that window/tab until the window is closed.

*Use the object sessionStorage instead of localStorage if persistent storage is not needed. sessionStorage object is available only to that window/tab until the window is closed.

*A single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] can be used to steal all the data in these objects, so again it's recommended not to store sensitive information in local storage.

*A single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] can be used to steal all the data in these objects, so again it's recommended not to store sensitive information in local storage.

*A single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] can be used to load malicious data into these objects too, so don't consider objects in these to be trusted.

*A single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] can be used to load malicious data into these objects too, so don't consider objects in these to be trusted.

*Pay extra attention to “localStorage.getItem” and “setItem” calls implemented in HTML5 page. It helps in detecting when developers build solutions that put sensitive information in local storage, which is a bad practice.

*Pay extra attention to “localStorage.getItem” and “setItem” calls implemented in HTML5 page. It helps in detecting when developers build solutions that put sensitive information in local storage, which is a bad practice.

+

*Do not store session identifiers in local storage as the data is always accesible by JavaScript. Cookies can mitigate this risk using the <tt>httpOnly</tt> flag.

+

*There is no way to restrict the visibility of an object to a specific path like with the attribute path of HTTP Cookies, every object is shared within an origin and protected with the Same Origin Policy. Avoid host multiple applications on the same origin, all of them would share the same localStorage object, use different subdomains instead.

−

== WebDatabase ==

+

=== Client-side databases ===

+

*On November 2010 the W3C announced Web SQL Database (relational SQL database) as a deprecated specification. A new standard Indexed Database API or IndexedDB (formerly WebSimpleDB) is actively developed which provides key/value database storage and methods for performing advanced queries.

*Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

*Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

*If utilized, WebDatabase content on client side can be vulnerable to SQLInjection and needs to have proper validation and parametrization.

*If utilized, WebDatabase content on client side can be vulnerable to SQLInjection and needs to have proper validation and parametrization.

*Like Local Storage, a single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] can be used to load malicious data into a web database too, so don't consider data in these to be trusted either.

*Like Local Storage, a single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] can be used to load malicious data into a web database too, so don't consider data in these to be trusted either.

+

+

== Geolocation ==

+

+

*The Geolocation RFC recommends that the user agent ask the user's permission before calculating location, but whether or how this decision is remembered varies from browser to browser. Some user agents require the user to visit the page again in order to turn off the ability to get the user's location without asking, so for privacy reasons, it's recommended to require user input before calling <tt>getCurrentPosition</tt> or <tt>watchPosition</tt>.

== Web Workers ==

== Web Workers ==

Line 34:

Line 80:

*Validate messages exchanged with a Web Worker. Do not try to exchange snippets of Javascript for evaluation e.g. via eval() as that could introduce a&nbsp;[[DOM Based XSS|DOM Based XSS]]&nbsp;vulnerability.

*Validate messages exchanged with a Web Worker. Do not try to exchange snippets of Javascript for evaluation e.g. via eval() as that could introduce a&nbsp;[[DOM Based XSS|DOM Based XSS]]&nbsp;vulnerability.

−

== WebSockets ==

+

== Sandboxed frames ==

−

*Drop backward compatibility in implemented client/servers and use only protocol versions above hybi-00. Popular Hixie-76 version (hiby-00) and olders are outdated and insecure.

+

*Use the <tt>sandbox</tt> attribute of an <tt>iframe</tt> for untrusted content

−

*Recommended version due current browser support is hiby-10, supported by Firefox 7 and Chrome 14.

+

−

*While it is relatively easy to tunnel TCP services through WebSockets (e.g. VNC, FTP), doing so enables access to these tunneled services for the in-browser attacker in case of a Cross-Site-Scripting attack. These services might also be called directly from a malicious page or program.

*Endpoints exposed through <tt>ws://</tt> protocol are easily reversible to plaintext. Only <tt>wss://</tt> (WebSockets over SSH) should be used for protection against Man-In-The-Middle attacks

+

−

*Spoofing the client is possible outside browser, so WebSockets server should be able to handle incorrect/malicious input. Always validate input coming from the remote site, as it might have been altered.

+

−

*When implementing servers, check the <tt>Origin:</tt> header in Websockets handshake. Though it might be spoofed outside browser, browsers always add the Origin of the page which initiated Websockets connection.

+

−

*As WebSockets client in browser is accessible through Javascript calls, all Websockets communication can be spoofed or hijacked through [[Cross Site Scripting Flaw|Cross-Site-Scripting]]. Always validate data coming through WebSockets connection.

+

−

+

−

== Geolocation ==

+

−

+

−

*The Geolocation RFC recommends that the user agent ask the user's permission before calculating location, but whether or how this decision is remembered varies from browser to browser. Some user agents require the user to visit the page again in order to turn off the ability to get the user's location without asking, so for privacy reasons, it's recommended to require user input before calling <tt>getCurrentPosition</tt> or <tt>watchPosition</tt>.

+

−

+

−

== Use the <tt>sandbox</tt> attribute of an <tt>iframe</tt> for untrusted content ==

+

*The <tt>sandbox</tt> attribute of an <tt>iframe</tt> enables restrictions on content within a <tt>iframe</tt>. The following restrictions are active when the <tt>sandbox</tt> attribute is set:

*The <tt>sandbox</tt> attribute of an <tt>iframe</tt> enables restrictions on content within a <tt>iframe</tt>. The following restrictions are active when the <tt>sandbox</tt> attribute is set:

Line 61:

Line 94:

It is possible to have a [http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox fine-grained control] over <tt>iframe</tt> capabilities using the value of the <tt>sandbox</tt> attribute.

It is possible to have a [http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox fine-grained control] over <tt>iframe</tt> capabilities using the value of the <tt>sandbox</tt> attribute.

−

== Web Messaging ==

+

*In old versions of user agents where this feature is not supported this attributed will be ignored. Use this feature as an additional layer of protection or check if the browser supports sandboxed frames and only show the untrusted content if supported.

+

*Apart from this attribute, to prevent Clickjacking attacks and unsolicited framing it is encouraged to use the header <tt>X-Frame-Options</tt> which supports the <tt>deny</tt> and <tt>same-origin</tt> values. Other solutions like framebusting <tt>if(window!== window.top) { window.top.location = location; }</tt> are not recommended.

−

Web Messaging provides a means of messaging between documents from different origins in a way which is generally safer than JSON-P, however, there are still some recommendations to keep in mind:

+

== Offline Applications ==

−

*When posting a message, explicitly state the expected origin as the second argument to <tt>postMessage</tt> rather than <tt>*</tt> in order to prevent sending the message to an unknown origin after a redirect or some other means of the target window's origin changing.

+

*Wether the user agent requests permission to the user to store data for offline browsing and when this cache is deleted vary from one browser to the next. Cache poisoning is an issue if a user connects through insecure networks, so for privacy reasons it is encouraged to require user input before sending any <tt>manifest</tt> file.

−

*The receiving page should '''always''':

+

*Users should only cache trusted websites and clean the cache after browsing through open or insecure networks.

−

**Check the <tt>origin</tt> attribute of the sender to verify the data is originating from the expected location, and

+

−

**Perform input validation on the <tt>data</tt> attribute of the event to ensure it's in the desired format.

+

−

*Don't assume you have control over data attribute. Single [[Cross-site_Scripting_(XSS)|Cross Site Scripting]] flaw in sending page allows attacker to send messages of any given format.

+

−

*Both pages should only interpret the exchanged messages as '''data'''. Never evaluate passed messages as code (e.g. via eval() )&nbsp;or insert it to a page DOM (e.g. via&nbsp;innerHTML) as that would create a DOM based XSS vulnerability. For more information see [[DOM based XSS Prevention Cheat Sheet|DOM based XSS Prevention Cheat Sheet]].

+

−

*To assign the data value to an element, instead of using a insecure method like <tt>element.innerHTML = data;</tt> use the safer option <tt>element.textContent = data;</tt>

+

−

*Check the origin properly exactly to match the FQDN you expect. Note that the following code: <tt> if(message.orgin.indexOf(".owasp.org")!=-1) { /* ... */ }</tt> is very insecure and will not have the desired behavior as www.owasp.org.attacker.com will match.

+

== Progressive Enhancements and Graceful Degradation Risks ==

== Progressive Enhancements and Graceful Degradation Risks ==

*The best practice now is to determine the capabilities that a browser supports and augment with some type of substitute for capabilities that are not directly supported. This may mean an onion-like element, e.g. falling through to a Flash Player if the &lt;video&gt; tag is unsupported, or it may mean additional scripting code from various sources that should be code reviewed.

*The best practice now is to determine the capabilities that a browser supports and augment with some type of substitute for capabilities that are not directly supported. This may mean an onion-like element, e.g. falling through to a Flash Player if the &lt;video&gt; tag is unsupported, or it may mean additional scripting code from various sources that should be code reviewed.

+

+

== HTTP Headers to enhance security ==

+

+

=== X-Frame-Options ===

+

+

*This header can be used to prevent ClickJacking in modern browsers (IE6/IE7 don't support this header)

+

*Use the <tt>same-origin</tt> attribute to allow being framed from urls of the same origin or <tt>deny</tt> to block all. Example: <tt>X-Frame-Options: DENY</tt>

+

+

=== X-XSS-Protection ===

+

+

*Enable XSS filter (only works for Reflected XSS)

+

*Example: <tt>X-XSS-Protection: 1; mode=block</tt>

+

+

=== Strict Transport Security ===

+

+

*Force every browser request to be sent over TLS/SSL (this can prevent SSL strip attacks)

Introduction

The following cheat sheet serves as a guide for implementing HTML 5 in a secure fashion.

General Guidelines

Communication APIs

Web Messaging

Web Messaging, also known as Cross Domain Messaging provides a means of messaging between documents from different origins in a way which is generally safer than the multiple hacks used in the past to accomplish this task, however, there are still some recommendations to keep in mind:

When posting a message, explicitly state the expected origin as the second argument to postMessage rather than * in order to prevent sending the message to an unknown origin after a redirect or some other means of the target window's origin changing.

The receiving page should always:

Check the origin attribute of the sender to verify the data is originating from the expected location, and

Perform input validation on the data attribute of the event to ensure it's in the desired format.

Don't assume you have control over data attribute. Single Cross Site Scripting flaw in sending page allows attacker to send messages of any given format.

Both pages should only interpret the exchanged messages as data. Never evaluate passed messages as code (e.g. via eval() ) or insert it to a page DOM (e.g. via innerHTML) as that would create a DOM based XSS vulnerability. For more information see DOM based XSS Prevention Cheat Sheet.

To assign the data value to an element, instead of using a insecure method like element.innerHTML = data; use the safer option element.textContent = data;

Check the origin properly exactly to match the FQDN(s) you expect. Note that the following code: if(message.orgin.indexOf(".owasp.org")!=-1) { /* ... */ } is very insecure and will not have the desired behavior as www.owasp.org.attacker.com will match.

If you need to embed external content/untrusted gadgets and allow user-controlled scripts which is highly discouraged, consider use a JavaScript rewriting framework such as Google Caja or check the information on sandboxed frames

Cross Origin Resource Sharing

Validate URLs passed to XMLHttpRequest.open, current browsers allow these URLs to be cross domain and this behavior can lead to code injection by a remote attacker. Pay extra attention to absolute URLs.

Ensure that URLs responding with Access-Control-Allow-Origin: * do not include any sensitive content or information that might aid attacker in further attacks. Use Access-Control-Allow-Origin header only on chosen URLs that need to be accessed cross-domain. Don't use the header for the whole domain.

Take special care when using Access-Control-Allow-Credentials: true response header. Whitelist the allowed Origins and never echo back the Origin request header in Access-Control-Allow-Origin.

Keep in mind that CORS does not prevent the requested data from going to an un-authenticated location - it's still important for the server to perform usual CSRF prevention.

While the RFC recommends a pre-flight request with the OPTIONS verb, current implementations might not perform this request, so it's important that "ordinary" (GET and POST) requests perform any access control necessary.

For performance reasons pre-flight requests may be cached in client-side for certain amount of time (controlled by Access-Control-Max-Age header). The security model of CORS can be bypassed in case of header injection vulnerabilities in combination with pre-flight caching so add measures to prevent HTTP_Response_Splitting vulnerabilities in server side.

Don't rely only on the Origin header for Access Control checks. Browser always sends this header in CORS requests, but may be spoofed outside the browser. Application-level protocols should be used to protect sensitive data.

WebSockets

Drop backward compatibility in implemented client/servers and use only protocol versions above hybi-00. Popular Hixie-76 version (hiby-00) and olders are outdated and insecure.

Recommended version supported in latest versions of all current browsers is RFC 6455 (Supported by Firefox 11+, Chrome 16+, Safari 6, Opera 12.50 and IE10).

While it is relatively easy to tunnel TCP services through WebSockets (e.g. VNC, FTP), doing so enables access to these tunneled services for the in-browser attacker in case of a Cross-Site-Scripting attack. These services might also be called directly from a malicious page or program.

The protocol doesn't handle authorization and/or authentication. Application-level protocols should handle that separately in case sensitive data is being transferred.

Process the messages received by the websocket as data. Don't try to assign it directly to the DOM nor evaluate as code. If the response is JSON never use the insecure eval() function, use the safe option JSON.parse() instead.

Endpoints exposed through ws:// protocol are easily reversible to plaintext. Only wss:// (WebSockets over SSL/TLS) should be used for protection against Man-In-The-Middle attacks

Spoofing the client is possible outside browser, so WebSockets server should be able to handle incorrect/malicious input. Always validate input coming from the remote site, as it might have been altered.

When implementing servers, check the Origin: header in Websockets handshake. Though it might be spoofed outside browser, browsers always add the Origin of the page which initiated Websockets connection.

As WebSockets client in browser is accessible through Javascript calls, all Websockets communication can be spoofed or hijacked through Cross-Site-Scripting. Always validate data coming through WebSockets connection.

Server-Sent Events

Validate URLs passed to the EventSource constructor, even though only same-origin URLs are allowed.

As mentioned before, process the messages (event.data) as data and never evaluate the content as HTML or script code.

Check always the origin attribute of the message (event.origin) to ensure the message is coming from a trusted domain, use a whitelist approach.

Storage APIs

Local Storage

Also known as Offline Storage, Web Storage. Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

Use the object sessionStorage instead of localStorage if persistent storage is not needed. sessionStorage object is available only to that window/tab until the window is closed.

A single Cross Site Scripting can be used to steal all the data in these objects, so again it's recommended not to store sensitive information in local storage.

A single Cross Site Scripting can be used to load malicious data into these objects too, so don't consider objects in these to be trusted.

Pay extra attention to “localStorage.getItem” and “setItem” calls implemented in HTML5 page. It helps in detecting when developers build solutions that put sensitive information in local storage, which is a bad practice.

Do not store session identifiers in local storage as the data is always accesible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.

There is no way to restrict the visibility of an object to a specific path like with the attribute path of HTTP Cookies, every object is shared within an origin and protected with the Same Origin Policy. Avoid host multiple applications on the same origin, all of them would share the same localStorage object, use different subdomains instead.

Client-side databases

On November 2010 the W3C announced Web SQL Database (relational SQL database) as a deprecated specification. A new standard Indexed Database API or IndexedDB (formerly WebSimpleDB) is actively developed which provides key/value database storage and methods for performing advanced queries.

Underlying storage mechanism may vary from one user agent to the next. In other words, any authentication your application requires can be bypassed by a user with local privileges to the machine on which the data is stored. Therefore, it's recommended not to store any sensitive information in local storage.

If utilized, WebDatabase content on client side can be vulnerable to SQLInjection and needs to have proper validation and parametrization.

Like Local Storage, a single Cross Site Scripting can be used to load malicious data into a web database too, so don't consider data in these to be trusted either.

Geolocation

The Geolocation RFC recommends that the user agent ask the user's permission before calculating location, but whether or how this decision is remembered varies from browser to browser. Some user agents require the user to visit the page again in order to turn off the ability to get the user's location without asking, so for privacy reasons, it's recommended to require user input before calling getCurrentPosition or watchPosition.

Web Workers

Web Workers are allowed to use XMLHttpRequest object to perform in-domain and Cross Origin Resource Sharing requests. See relevant section of this Cheat Sheet to ensure CORS security.

While Web Workers don't have access to DOM of the calling page, malicious Web Workers can use excessive CPU for computation, leading to Denial of Service condition or abuse Cross Origin Resource Sharing for further exploitation. Ensure code in all Web Workers scripts is not malevolent. Don't allow creating Web Worker scripts from user supplied input.

Validate messages exchanged with a Web Worker. Do not try to exchange snippets of Javascript for evaluation e.g. via eval() as that could introduce a DOM Based XSS vulnerability.

Sandboxed frames

Use the sandbox attribute of an iframe for untrusted content

The sandbox attribute of an iframe enables restrictions on content within a iframe. The following restrictions are active when the sandbox attribute is set:

All markup is treated as being from a unique origin

All forms and scripts are disabled

All links are prevented from targeting other browsing contexts

All features that triggers automatically are blocked

All plugins are disabled

It is possible to have a fine-grained control over iframe capabilities using the value of the sandbox attribute.

In old versions of user agents where this feature is not supported this attributed will be ignored. Use this feature as an additional layer of protection or check if the browser supports sandboxed frames and only show the untrusted content if supported.

Apart from this attribute, to prevent Clickjacking attacks and unsolicited framing it is encouraged to use the header X-Frame-Options which supports the deny and same-origin values. Other solutions like framebusting if(window!== window.top) { window.top.location = location; } are not recommended.

Offline Applications

Wether the user agent requests permission to the user to store data for offline browsing and when this cache is deleted vary from one browser to the next. Cache poisoning is an issue if a user connects through insecure networks, so for privacy reasons it is encouraged to require user input before sending any manifest file.

Users should only cache trusted websites and clean the cache after browsing through open or insecure networks.

Progressive Enhancements and Graceful Degradation Risks

The best practice now is to determine the capabilities that a browser supports and augment with some type of substitute for capabilities that are not directly supported. This may mean an onion-like element, e.g. falling through to a Flash Player if the <video> tag is unsupported, or it may mean additional scripting code from various sources that should be code reviewed.

HTTP Headers to enhance security

X-Frame-Options

This header can be used to prevent ClickJacking in modern browsers (IE6/IE7 don't support this header)

Use the same-origin attribute to allow being framed from urls of the same origin or deny to block all. Example: X-Frame-Options: DENY

X-XSS-Protection

Enable XSS filter (only works for Reflected XSS)

Example: X-XSS-Protection: 1; mode=block

Strict Transport Security

Force every browser request to be sent over TLS/SSL (this can prevent SSL strip attacks)