Features
- Ability to seamlessly incorporate HTML elements, custom styling (CSS) and JavaScript without affecting the rest of the page
- Allows for previews to prevent tedious page reloading
Quick Start
- Installation & Setup
The app installation is a standard one for Confluence MarketPlace apps.
- Insert the HTML macro into your page and click Insert
- The Sanitize box should be unchecked if you're inserting JavaScript.
- See Security Considerations section for more information.
- the macro is rendered in one or two levels of IFrames. Therefore, you cannot interact w/ the DOM of the parent and should be familiar with the same-origin policy if you are using advanced client-side code.
- See Security Considerations section for more information.
Specify the height for your macro. You can leave blank and adjust it later by editing the macro after you've previewed the page.
- The Sanitize box should be unchecked if you're inserting JavaScript.
Add your HTML to the box that's now inserted on your page
- Review the macro by viewing the Confluence page or use the "Preview" window in the macro editor.
Security Considerations
Sanitize HTML option
When using the Sanitize option (Sanitize box in macro is checked), only "safe" HTML is allowed (i.e. no JavaScript allowed). This option will load slightly faster.
Unchecking the Sanitize option allows JavaScript in the body of the HTML macro. However, in this case, a second or double iFrame is used from a different domain. This sandboxing insulates the content from the parent Confluence page, which prevents interaction with the parent page DOM and increases safety. Any Cloud app that does not operate in this sandboxed manner would not be inherently safe as JavaScript could make REST calls back to Confluence as the present user. Using the sandbox double iFrame and a different domain adds security by preventing this from occurring.
Sandboxing helps to mitigate the most dangerous aspects of JavaScript running in your macro but you need to be aware that unchecking "Sanitize" adds risk. Despite the insulation of the extra iframe, this enables certain classes of stored XSS attacks (for example, phishing for credentials in a fake login panel), so you need to trust your site users to use the macro responsibly.
When sanitized is unchecked then JavaScript can be executed by your macro and you can make AJAX requests from your code in the body of the HTML macro. The sandbox iFrame does not add any CORS-related headers. However, AJAX requests to services that you do not control may contain CORS response headers that prevent you from using them within the sandbox iFrame.
An administrator can use the "Configure" button for the HTML Macro in the "Manage apps" page to allow or prevent users from creating and viewing unsanitized HTML macros:
The Javascript is limited as to what it can do because we “sandbox” the unsanitized macro in an extra iframe. It cannot spoof the target user or obtain their Confluence access token, or make changes to any content outside the sandboxed macro. There are still some potential attacks. It would be impossible to list all of these, but examples would be a user adding a pop-up or phishing for user information. Because of how Javascript works, there is no way to prevent these types of attacks by a malicious user that is already in the system. Therefore, unsanitized mode should only be enabled when users are trusted not to exploit it. If you are concerned about protecting your instance from these attacks you can limit the users that can access/edit the page to Admins or other trusted groups.
X-Frame-Options Response Header
If you try to include an iFrame in an HTML macro it will not work if the server for the src of the iframe sets the X-Frame-Options response header to DENY or SAMEORIGIN (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options). In this situation, the browser console may say, "Refused to display 'https://www.mysite.com' in a frame, because it set 'X-Frame-Options' to 'SAMEORIGIN."
The X-Frame-Options header value of SAMEORIGIN only allows content to be embedded in an iFrame if the content is from the same origin as the page containing the iframe. The DENY value will disallow it from any origin.
When a server returns the X-Frame-Options response header the server has explicitly set a content security policy that limits it's content rendering in an iFrame, and the browser is honoring that. It is a browser security issue and is not something Artemis can control or bypass.
If you control the remote domain that is serving the src of the iframe, you can disable this setting on that server or you could build a proxy for that domain that strips the header. Many sites do not want to show up in iFrames for Intellectual Property (IP) or security reasons.
Development Considerations
When developing JavaScript or other code to add to this app, please note that it is running in an iFrame inside the macro AND an iFrame on the Confluence page. The innermost iFrame is served from our app domain and not from Atlassian. For instance, if you create an HTML form and submit it, you will likely get a response from our domain indicating that it is "Not authenticated."
Examples
Feel free to copy and paste the HTML into your Confluence Cloud HTML Macro (which you can trial for free) to try out the capabilities. Make sure to deselect the Sanitize parameter for these examples.
You need to deselect the Sanitize checkbox of the macro for most of these examples.
Jira issue collector
Click the button to exercise the Jira issue collector (used to embed a Jira feedback form into your website):
Sample source code used in the Jira issue collector HTML Macro:
<script type="text/javascript" src="https://artemis.atlassian.net/s/401422dda1a927c2b340959d2c5dec66-T/w2fj92/72002/be99fa68111ca9c7c6eda6be8b94fb5d/2.0.13/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?locale=en-US&collectorId=4a20a0b8"></script>
Include forms from Wufoo
Here is a live form being served from Wufoo:
Deselect the Sanitize checkbox of the macro.
HTML source is copied from what Wufoo provides when you create a form.
Sample source code used in the Wufoo HTML Macro:
<div id="wufoo-z1qocwz617m1fv6"> Fill out my <a href="https://artemissoftware.wufoo.com/forms/z1qocwz617m1fv6">online form</a>. </div> <div id="wuf-adv" style="font-family:inherit;font-size: small;color:#a7a7a7;text-align:center;display:block;">HTML Forms powered by <a href="https://www.wufoo.com">Wufoo</a>.</div> <script type="text/javascript">var z1qocwz617m1fv6;(function(d, t) { var s = d.createElement(t), options = { 'userName':'artemissoftware', 'formHash':'z1qocwz617m1fv6', 'autoResize':true, 'height':'663', 'async':true, 'host':'wufoo.com', 'header':'show', 'ssl':true}; s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'www.wufoo.com/scripts/embed/form.js'; s.onload = s.onreadystatechange = function() { var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return; try { z1qocwz617m1fv6 = new WufooForm();z1qocwz617m1fv6.initialize(options);z1qocwz617m1fv6.display(); } catch (e) {}}; var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr); })(document, 'script');</script>
Render CodePen block
CodePen is a playground for the front-end web.
The following code block that renders a walking elephant:
<p data-height="564" data-theme-id="0" data-slug-hash="gaOGja" data-default-tab="result" data-user="FabioG" class='codepen'>See the Pen <a href='Walking'>Walking'>http://codepen.io/FabioG/pen/gaOGja/'>Walking Mr Elephant. NOW WITH MOVING FEET! CSS only animation</a> by Fabio (<a href='@@FabioGFabioGhttp://codepen.io/FabioG'>@FabioG</a>) on <a href='CodePenCodePenhttp://codepen.io'>CodePen</a>.</p> <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
Redirect browser page
Source code used in the window redirect HTML Macro:
<button type="button" onclick="myFunction()">Redirect to Google</button> <script> function myFunction() { window.top.location.href = "http://www.google.com"; } </script>
Redirect to the URL given in the field
<form> Redirect the page to the given URL : <input id="query" type="text" value="http://www.google.com" /> <input type="submit" value="Submit"> </form> <script> document.querySelector('form').addEventListener('submit', ExecuteSearch); function ExecuteSearch(e) { e.preventDefault(); e.stopPropagation(); var query = document.querySelector('#query'); if (!query) return; var value = query.value; if (!value) return; var summary = encodeURIComponent(value); var url = value; window.top.location.href = url; } </script>
Add an image into the HTML macro
Have the image on the page via the attachment, then grab the image link by:
Click the meatballs icon.
Click Attachments.
Right-click the Name and copy the link address.
<html> <body> <h2>Images on Another Server</h2> <img src="https://artemis-test2.atlassian.net/wiki/download/attachments/894664831/largebackground.jpg?api=v2" alt="artemis-test2.atlassian.net" style="width:104px;height:142px;"> </body> </html>
Related Articles