{"action":"created","comment":{"url":"https://api.github.com/repos/edx/edx-documentation/pulls/comments/57166150","id":57166150,"diff_hunk":"@@ -0,0 +1,1176 @@\n+.. _Safe Templates:\n+\n+###############################################\n+Preventing Cross Site Scripting Vulnerabilities\n+###############################################\n+\n+Cross Site Scripting (XSS) vulnerabilities allow user-supplied data to be\n+incorrectly executed as code in a web browser. It can be difficult to write\n+templates that are safe from XSS security vulnerabilities. This section\n+presents best practices for handling proper escaping in the Open edX platform\n+to avoid these vulnerabilities.\n+\n+.. note:: If you become aware of security issues, do not report them in\n+   public. Instead, please email security@edx.org.\n+\n+.. contents::\n+   :depth: 1\n+   :local:\n+\n+\n+Philosophy and General Rules\n+****************************\n+\n+The philosophy behind the recommendations in this section is to make things as\n+simple as possible for developers. Protecting against XSS vulnerabilities\n+typically requires properly escaping user-provided data before it is placed on\n+the page. Rather than trying to determine if data is user-provided and could\n+be compromised, we will play it safe and escape data whether it is user-provided\n+or not. Unfortunately, because there are many different rules for escaping, you\n+still must choose the proper type of escaping.\n+\n+Here are some general rules.\n+\n+#. **Escape always.** Assume that all data is untrusted and escape it\n+   appropriately. Do not try to determine whether data could or could not be\n+   manipulated by a user.\n+\n+#. **Escape late.** Delay escaping as long as possible, until you can see the\n+   actual context and understand the proper escaping that is required for\n+   the context. Browsers interpret different contexts such as HTML, URLs,\n+   CSS, and Javascript/JSON with different rules, so there are different\n+   escaping requirements based on where the data is being used in a page.\n+\n+#. **Escape appropriately.** Know what kind of data you have (HTML, plain text,\n+   JSON, etc.) and where it is going (HTML, JavaScript, etc.). Choose the\n+   proper escaping function based on these details.\n+\n+#. **Validation is not sufficient.** Validating inputs does not replace the\n+   need to properly escape. In some cases, this may reduce the likelihood of\n+   potential problems, but proper escaping is always necessary.\n+\n+#. **Do not store escaped data.** Again, because you do not know ahead of time\n+   all the places that the data will be used, you must wait until you have\n+   the proper context to decide on the proper escaping.\n+\n+\n+Types of Context and Escaping\n+*****************************\n+\n+.. contents::\n+   :depth: 1\n+   :local:\n+\n+Overview of Contexts\n+====================\n+\n+The following diagram provides a high-level overview of the relationship\n+between the different templates, different contexts of DOM creation and\n+manipulation, and different types of escaping. As a general rule, proper\n+escaping is related to the context in which the data is being written, and\n+might not match the context that will eventually be reading the data.\n+\n+.. image:: ../images/safe-templates.png\n+    :width: 666px\n+    :height: 289px\n+    :align: center\n+    :alt: A diagram detailing how data flows from Django applications and Django\n+     models through Mako templates and Django templates into an HTML page. Data can\n+     then flow from the HTML page into JavaScript, and back down into the DOM\n+     through jQuery or Underscore.js templates.\n+\n+In the Open edX platform, data flows from the application to the initial HTML page\n+mainly through the use of Mako templates.\n+\n+.. Make sure the numbers in the list below are in sync with the numbered arrows in\n+.. the safe-templates.png diagram above, if either the diagram or the list is modified.\n+\n+Descriptions of each numbered arrow in the diagram follow.\n+\n+#. This step represents the use of Mako templates to write general HTML tags\n+   (that is, tags other than ``<script>`` tags) to create the HTML page. Any\n+   data written to the page inside one of these HTML tags or HTML attributes\n+   must be HTML-escaped to be treated as plain text.\n+\n+#. This step represents the use of Mako templates to write JavaScript inside\n+   a ``<script>`` tag in the HTML page. Data written to this context must all\n+   be JavaScript-escaped to keep it from mistakenly being treated as HTML.\n+   Note that this data should not be HTML-escaped, which must happen in a\n+   later step if it is written back to the DOM by JavaScript.\n+\n+#. This step represents the loading and executing of JavaScript from the HTML\n+   page by the JavaScript engine. This step should be safe, if data was\n+   properly JavaScript-escaped earlier.\n+\n+#. In this step, JavaScript might load additional data from HTML tags and\n+   attributes using the DOM. Sometimes data is passed in this way via data\n+   attributes. This data is typically read using jQuery functions, but it can\n+   be read using other JavaScript functions. The data can be in the form of\n+   plain text strings or JSON. If it is in the form of strings, this data\n+   should mostly be plain text. Be careful with the escaping in this case.\n+   Although the data is used in JavaScript, it is transmitted as HTML, and so\n+   must be HTML-escaped.\n+\n+#. In this step, JavaScript is being used to edit the DOM, often by creating\n+   HTML tags or setting HTML attributes. Often this is done using jQuery\n+   functions. Since HTML tags and attributes are being written here, any plain\n+   text must be properly HTML-escaped.\n+\n+#. This step represents a subset of DOM manipulation using JavaScript,\n+   specifically through use of Underscore.js templates. Although these\n+   templates have a specific syntax for escaping, because HTML tags and\n+   attributes are being written any plain text must be properly HTML-escaped.\n+\n+\n+HTML Context and Escaping\n+=========================\n+\n+The outtermost context of an HTML file is HTML. In an HTML context inside an\n+HTML file, data is kept safe by HTML-escaping.\n+\n+How HTML-Escaping Makes HTML Safe\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+.. highlight:: mako\n+\n+Let's review a simple example of an XSS attack and how proper escaping might\n+prevent such an attack. Imagine that we find the following expression in a\n+Mako template.\n+\n+.. code-block:: mako\n+\n+    <div>${course_name}</div>\n+\n+Imagine further that someone uses Studio to set the course name as shown in\n+this example, including the HTML ``<script>`` tag.\n+\n+.. code-block:: mako\n+\n+    <script>alert('XSS attack!');</script>\n+\n+The following resulting unsafe page source is sent to the browser.\n+\n+.. code-block:: mako\n+\n+    <div><script>alert('XSS attack!');</script></div>\n+\n+The browser would execute the JavaScript code in the ``<script>alert('XSS\n+attack!');</script>`` tag. The user has injected code into the page that would\n+display a pop-up alert, which we would not want to allow. Because this attack\n+could contain arbitrary JavaScript that would be executed by the browser with\n+the same trust as any JavaScript that is sent from the application, it has the\n+potential to do something much more malicious than simply displaying a pop-up.\n+An example might be to steal and email the user's cookies.\n+\n+In Mako, you can introduce HTML-escaping for all expressions on a page using\n+the page directive with the ``h`` filter. Here is an example of an expression\n+that is properly HTML-escaped.\n+\n+.. code-block:: mako\n+\n+    <%page expression_filter=\"h\"/>\n+    ...\n+    <div>${course_name}</div>\n+\n+The resulting safe page source is as follows.\n+\n+.. code-block:: mako\n+\n+    <div>&lt;script&gt;alert(&#39;XSS!&#39;);&lt;/script&gt;</div>\n+\n+This time, the browser will not interpret the ``<script>`` tag as a JavaScript\n+context, and instead simply displays the original string in the page.\n+\n+\n+JavaScript Context and Escaping\n+===============================\n+\n+The outtermost context of a JavaScript file is JavaScript. An HTML file also\n+contains a JavaScript context inside any `<script>` tag. Inside a JavaScript\n+context, data is kept safe by JavaScript-escaping.\n+\n+How JavaScript-Escaping Makes HTML Safe\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Here is an example of an expression used in a valid JavaScript context created\n+using a ``<script>`` tag inside a Mako template.\n+\n+.. code-block:: mako\n+\n+    <script type=\"text/javascript\">\n+       var courseName = \"${course_name}\";\n+       ...\n+    </script>\n+\n+For this example, imagine that someone uses Studio to set the course name as\n+shown here.\n+\n+.. code-block:: mako\n+\n+    \";alert('XSS attack!');\"\n+\n+The resulting unsafe page source, sent to the browser with no escaping, would look\n+like this.\n+\n+.. code-block:: mako\n+\n+    <script type=\"text/javascript\">\n+       var courseName = \"\";alert('XSS attack!');\"\";\n+       ...\n+    </script>\n+\n+You can see how the attacker closed out the string and again tricked the browser\n+into executing the malicious JavaScript in the context of JavaScript. There\n+are several reasons why you do not want to use the default HTML-escaping here.\n+\n+#. JavaScript-escaping will also escape all characters that are special\n+   characters in HTML, such as ``<``. However, JavaScript-escaping will\n+   escape ``<`` to ``\\u003C``, rather than to ``&lt;``. This will still keep\n+   the browser from finding an HTML tag where it does not belong.\n+\n+#. The resulting string might not ultimately be used in an HTML context, so\n+   HTML entities might not be the proper escaping.\n+\n+The way to properly JavaScript-escape code in Mako is shown in the following\n+example.\n+\n+.. code-block:: mako\n+\n+    <%! from openedx.core.djangolib.js_utils import js_escaped_string %>\n+    ...\n+    <script type=\"text/javascript\">\n+       var courseName = \"${course_name | n, js_escaped_string}\";\n+       ...\n+    </script>\n+\n+The code above would produce the following safe page source.\n+\n+.. code-block:: mako\n+\n+    <script type=\"text/javascript\">\n+       var courseName = \"\\u0022\\u003Balert(\\u0027XSS attack!\\u0027)\\u003B\\u0022\\u0022\\u003B\";\n+       ...\n+    </script>\n+\n+.. _CSS Context:\n+\n+CSS Context and Escaping\n+========================\n+\n+The browser will treat any code inside a ``<style>`` tag or ``style`` attribute\n+in an HTML page as a CSS context, or something that requires CSS parsing. CSS\n+parsing has its own rules, and requires CSS-escaping.\n+\n+In a CSS context, user supplied data has some additional constraints required\n+for keeping it safe:\n+\n+* User supplied data can only appear as the value of a style property. In other\n+  words, never allow a user to supply the entire contents of the style tag or\n+  style property, or anything outside of the limited scope of an individual\n+  property value.\n+\n+* User supplied URLs must use a whitelisted or acceptable protocol (e.g. http).\n+  This is to avoid users being able to supply a URL that uses the \"javascript\"\n+  protocol as an example.\n+\n+* User supplied style property values must not contain ``expression(...)`` due\n+  to an IE feature that would enable arbitrary JavaScript to run.\n+\n+There are no existing helper functions for this in the platform. If you need to\n+use user supplied data in a CSS context you must work with edX to help expand\n+the suite of available helpers.\n+\n+For more information, see\n+`OWASP: CSS and XSS <https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.234_-_CSS_Escape_And_Strictly_Validate_Before_Inserting_Untrusted_Data_into_HTML_Style_Property_Values>`_.\n+\n+.. _URL Context:\n+\n+URL Context and Escaping\n+========================\n+\n+URLs require multiple types of escaping. This typically involves both\n+URL-escaping, in addition to either HTML-escaping or JavaScript-escaping.\n+\n+There are many special characters that are meaningful in a URL. For example,\n+both `&` and `=` are used to designate parts of the query string. If data is\n+being provided as a query parameter, and it may contain special characters, it\n+must be fully URL-escaped. This is especially true with user provided data which\n+could contain any character. Using the JavaScript URL-escaping functions as an\n+example, you would use the ``encodeURIComponent`` function on the data which\n+will URL-escape all special characters.  Here is an example.\n+\n+.. code-block:: javascript\n+\n+    var url = \"http://test.com/?data=\" + encodeURIComponent(userData)\n+\n+URL-escaping is susceptible to double-escaping, meaning you must URL-escape its\n+parts exactly once. It is best to perform the URL-escaping at the time the URL\n+is being assembled.\n+\n+Additionally, you will typically HTML-escape or JavaScript-escape a URL\n+following the same rules for any other data added to the page, since a properly\n+URL-escaped URL may still contain characters that are meaningful in an HTML\n+context, like ``&`` and ``'``.\n+\n+For example, when adding a URL to the ``href`` attribute of an anchor tag\n+(``<a>``), it should already be properly URL-escaped, and would need to be\n+HTML-escaped at the time it is added to the HTML.\n+\n+.. note:: If the entire URL is user provided, additional validation is required.\n+\n+When an entire URL is user provided, and not just some query parameters, you\n+must also validate the URL to ensure it uses a whitelisted or acceptable\n+protocol (e.g. https). This is to avoid users being able to supply a URL that\n+uses the \"javascript\" protocol as an example.\n+\n+For more information, see `oWASP: URL Escape <https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.235_-_URL_Escape_Before_Inserting_Untrusted_Data_into_HTML_URL_Parameter_Values>`_.\n+\n+\n+Editing Template Files\n+**********************\n+\n+When you edit template files (including Mako templates, Underscore templates,\n+or JavaScript), use the appropriate conventions.\n+\n+The topics that follow address these points for each type of file.\n+\n+#. What has to be at the top of the file (if anything) to make it safe?\n+\n+#. How is code properly escaped? The answer is different depending on the\n+   templating language and the context.\n+\n+#. How do you properly handle internationalization and escaping together? For\n+   more information, see :ref:`i18n`.\n+\n+.. note:: Remember to take into account the type of file in addition to the\n+   programming language involved. For example, JavaScript embedded in an HTML\n+   Mako template is treated differently than JavaScript in a pure .js file.\n+\n+To find the proper guidelines to follow, first start with the appropriate file\n+type below.\n+\n+.. contents::\n+   :depth: 2\n+   :local:\n+\n+.. _Safe Django Template Files:\n+\n+Django Template Files\n+=====================\n+\n+.. highlight:: django\n+\n+Django templates are considered \"safe by default\", meaning that expressions\n+are HTML-escaped by default. HTML-escaping is not always the right choice for\n+escaping, for example, with embedded JavaScript.\n+\n+\n+.. _Safe Mako Template Calls:\n+\n+Mako Template() Calls in Python Files\n+=====================================\n+\n+.. highlight:: mako\n+\n+If a Mako template is loaded from Python outside of the general template loading\n+scheme, the following default filters should be provided to make the template\n+safe by default (i.e. use HTML-escaping by default).\n+\n+.. code-block:: mako\n+\n+    template = Template(\" ... \",\n+        default_filters=['decode.utf8', 'h'],\n+    )\n+\n+\n+.. _Safe Mako Template Files:\n+\n+Mako Template Files\n+===================\n+\n+This topic covers the best practices for protecting Mako template files from XSS\n+vulnerabilities.\n+\n+If you need to convert a legacy Mako template to be safe by default, it is\n+recommended that you do the following:\n+\n+* First read through the following subtopics and become familiar with the\n+  current best practices.\n+\n+* Next, follow the step-by-step instructions detailed in\n+  :ref:`Making Mako Templates Safe By Default`, which will often refer back to\n+  this topic.\n+\n+.. _HTML-Escape Mako by Default:\n+\n+HTML-Escape by Default in Mako\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+.. highlight:: mako\n+\n+For Mako templates, all expressions will use HTML-escaping by default. This is\n+accomplished by adding the following directive to the very top of each\n+template. ::\n+\n+    <%page expression_filter=\"h\"/>\n+\n+Using this default HTML-escaping, the following combination will represent an\n+HTML-escaped expression. ::\n+\n+    <%page expression_filter=\"h\"/>\n+    ...\n+    ${data}\n+\n+the first filter. This can be seen in some of the examples below.\n+\n+If you need to disable the default filters, you must use the ``n`` filter as","path":"en_us/developers/source/conventions/safe_templates.rst","position":426,"original_position":426,"commit_id":"e1d4da9dcd5fbfff68b7ca2a31ed404a211509ea","original_commit_id":"e1d4da9dcd5fbfff68b7ca2a31ed404a211509ea","user":{"login":"nasthagiri","id":6772826,"avatar_url":"https://avatars.githubusercontent.com/u/6772826?v=3","gravatar_id":"","url":"https://api.github.com/users/nasthagiri","html_url":"https://github.com/nasthagiri","followers_url":"https://api.github.com/users/nasthagiri/followers","following_url":"https://api.github.com/users/nasthagiri/following{/other_user}","gists_url":"https://api.github.com/users/nasthagiri/gists{/gist_id}","starred_url":"https://api.github.com/users/nasthagiri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nasthagiri/subscriptions","organizations_url":"https://api.github.com/users/nasthagiri/orgs","repos_url":"https://api.github.com/users/nasthagiri/repos","events_url":"https://api.github.com/users/nasthagiri/events{/privacy}","received_events_url":"https://api.github.com/users/nasthagiri/received_events","type":"User","site_admin":false},"body":"incomplete sentence?  \"filter as\".. ?","created_at":"2016-03-23T14:20:09Z","updated_at":"2016-03-23T14:20:09Z","html_url":"https://github.com/edx/edx-documentation/pull/914#discussion_r57166150","pull_request_url":"https://api.github.com/repos/edx/edx-documentation/pulls/914","_links":{"self":{"href":"https://api.github.com/repos/edx/edx-documentation/pulls/comments/57166150"},"html":{"href":"https://github.com/edx/edx-documentation/pull/914#discussion_r57166150"},"pull_request":{"href":"https://api.github.com/repos/edx/edx-documentation/pulls/914"}}},"pull_request":{"url":"https://api.github.com/repos/edx/edx-documentation/pulls/914","id":62755579,"html_url":"https://github.com/edx/edx-documentation/pull/914","diff_url":"https://github.com/edx/edx-documentation/pull/914.diff","patch_url":"https://github.com/edx/edx-documentation/pull/914.patch","issue_url":"https://api.github.com/repos/edx/edx-documentation/issues/914","number":914,"state":"open","locked":false,"title":"Complete Safe Templates doc","user":{"login":"robrap","id":14576445,"avatar_url":"https://avatars.githubusercontent.com/u/14576445?v=3","gravatar_id":"","url":"https://api.github.com/users/robrap","html_url":"https://github.com/robrap","followers_url":"https://api.github.com/users/robrap/followers","following_url":"https://api.github.com/users/robrap/following{/other_user}","gists_url":"https://api.github.com/users/robrap/gists{/gist_id}","starred_url":"https://api.github.com/users/robrap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robrap/subscriptions","organizations_url":"https://api.github.com/users/robrap/orgs","repos_url":"https://api.github.com/users/robrap/repos","events_url":"https://api.github.com/users/robrap/events{/privacy}","received_events_url":"https://api.github.com/users/robrap/received_events","type":"User","site_admin":false},"body":"This PR can be used to provide feedback on any part of the Preventing Cross-Site Scripting Vulnerabilities documentation.\r\n\r\nThis PR will be used during the [Safe Template Marathon](https://openedx.atlassian.net/wiki/display/TNL/Safe+Template+Marathon).\r\n\r\nUse this link if you want to view the latest [draft documentation in Read the Docs](http://draft-safe-templates-2016-03-23.readthedocs.org/en/latest/conventions/safe_templates.html).","created_at":"2016-03-14T14:25:35Z","updated_at":"2016-03-23T14:20:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"39bd46b0ae946843d41d645cb586506d6723bbe5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/edx/edx-documentation/pulls/914/commits","review_comments_url":"https://api.github.com/repos/edx/edx-documentation/pulls/914/comments","review_comment_url":"https://api.github.com/repos/edx/edx-documentation/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/edx-documentation/issues/914/comments","statuses_url":"https://api.github.com/repos/edx/edx-documentation/statuses/e1d4da9dcd5fbfff68b7ca2a31ed404a211509ea","head":{"label":"edx:robrap/safe-templates-all","ref":"robrap/safe-templates-all","sha":"e1d4da9dcd5fbfff68b7ca2a31ed404a211509ea","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":23839256,"name":"edx-documentation","full_name":"edx/edx-documentation","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-documentation","description":"For published versions of the edX documentation, visit:","fork":false,"url":"https://api.github.com/repos/edx/edx-documentation","forks_url":"https://api.github.com/repos/edx/edx-documentation/forks","keys_url":"https://api.github.com/repos/edx/edx-documentation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-documentation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-documentation/teams","hooks_url":"https://api.github.com/repos/edx/edx-documentation/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-documentation/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-documentation/events","assignees_url":"https://api.github.com/repos/edx/edx-documentation/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-documentation/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-documentation/tags","blobs_url":"https://api.github.com/repos/edx/edx-documentation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-documentation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-documentation/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-documentation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-documentation/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-documentation/languages","stargazers_url":"https://api.github.com/repos/edx/edx-documentation/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-documentation/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-documentation/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-documentation/subscription","commits_url":"https://api.github.com/repos/edx/edx-documentation/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-documentation/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-documentation/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-documentation/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-documentation/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-documentation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-documentation/merges","archive_url":"https://api.github.com/repos/edx/edx-documentation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-documentation/downloads","issues_url":"https://api.github.com/repos/edx/edx-documentation/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-documentation/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-documentation/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-documentation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-documentation/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-documentation/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-documentation/deployments","created_at":"2014-09-09T15:29:04Z","updated_at":"2016-03-23T13:58:11Z","pushed_at":"2016-03-23T14:02:36Z","git_url":"git://github.com/edx/edx-documentation.git","ssh_url":"git@github.com:edx/edx-documentation.git","clone_url":"https://github.com/edx/edx-documentation.git","svn_url":"https://github.com/edx/edx-documentation","homepage":" http://docs.edx.org","size":96046,"stargazers_count":34,"watchers_count":34,"language":"Makefile","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":125,"mirror_url":null,"open_issues_count":23,"forks":125,"open_issues":23,"watchers":34,"default_branch":"master"}},"base":{"label":"edx:robrap/safe-templates-fresh","ref":"robrap/safe-templates-fresh","sha":"2596c987cbd70f3acbaaaebbbd478a4507be086c","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":23839256,"name":"edx-documentation","full_name":"edx/edx-documentation","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-documentation","description":"For published versions of the edX documentation, visit:","fork":false,"url":"https://api.github.com/repos/edx/edx-documentation","forks_url":"https://api.github.com/repos/edx/edx-documentation/forks","keys_url":"https://api.github.com/repos/edx/edx-documentation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-documentation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-documentation/teams","hooks_url":"https://api.github.com/repos/edx/edx-documentation/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-documentation/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-documentation/events","assignees_url":"https://api.github.com/repos/edx/edx-documentation/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-documentation/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-documentation/tags","blobs_url":"https://api.github.com/repos/edx/edx-documentation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-documentation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-documentation/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-documentation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-documentation/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-documentation/languages","stargazers_url":"https://api.github.com/repos/edx/edx-documentation/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-documentation/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-documentation/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-documentation/subscription","commits_url":"https://api.github.com/repos/edx/edx-documentation/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-documentation/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-documentation/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-documentation/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-documentation/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-documentation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-documentation/merges","archive_url":"https://api.github.com/repos/edx/edx-documentation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-documentation/downloads","issues_url":"https://api.github.com/repos/edx/edx-documentation/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-documentation/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-documentation/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-documentation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-documentation/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-documentation/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-documentation/deployments","created_at":"2014-09-09T15:29:04Z","updated_at":"2016-03-23T13:58:11Z","pushed_at":"2016-03-23T14:02:36Z","git_url":"git://github.com/edx/edx-documentation.git","ssh_url":"git@github.com:edx/edx-documentation.git","clone_url":"https://github.com/edx/edx-documentation.git","svn_url":"https://github.com/edx/edx-documentation","homepage":" http://docs.edx.org","size":96046,"stargazers_count":34,"watchers_count":34,"language":"Makefile","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":125,"mirror_url":null,"open_issues_count":23,"forks":125,"open_issues":23,"watchers":34,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/edx-documentation/pulls/914"},"html":{"href":"https://github.com/edx/edx-documentation/pull/914"},"issue":{"href":"https://api.github.com/repos/edx/edx-documentation/issues/914"},"comments":{"href":"https://api.github.com/repos/edx/edx-documentation/issues/914/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/edx-documentation/pulls/914/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/edx-documentation/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/edx-documentation/pulls/914/commits"},"statuses":{"href":"https://api.github.com/repos/edx/edx-documentation/statuses/e1d4da9dcd5fbfff68b7ca2a31ed404a211509ea"}}}}