123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /**
- * The Security devtool supports the following arguments:
- * * Security CSP
- * Provides feedback about the current CSP
- *
- * * Security referrer
- * Provides information about the current referrer policy
- */
- "use strict";
- const { Cc, Ci, Cu, CC } = require("chrome");
- const l10n = require("gcli/l10n");
- const CSP = Cc["@mozilla.org/cspcontext;1"].getService(Ci.nsIContentSecurityPolicy);
- const GOOD_IMG_SRC = "chrome://browser/content/gcli_sec_good.svg";
- const MOD_IMG_SRC = "chrome://browser/content/gcli_sec_moderate.svg";
- const BAD_IMG_SRC = "chrome://browser/content/gcli_sec_bad.svg";
- // special handling within policy
- const POLICY_REPORT_ONLY = "report-only"
- // special handling of directives
- const DIR_UPGRADE_INSECURE = "upgrade-insecure-requests";
- const DIR_BLOCK_ALL_MIXED_CONTENT = "block-all-mixed-content";
- // special handling of sources
- const SRC_UNSAFE_INLINE = "'unsafe-inline'";
- const SRC_UNSAFE_EVAL = "'unsafe-eval'";
- const WILDCARD_MSG = l10n.lookup("securityCSPRemWildCard");
- const XSS_WARNING_MSG = l10n.lookup("securityCSPPotentialXSS");
- const NO_CSP_ON_PAGE_MSG = l10n.lookup("securityCSPNoCSPOnPage");
- const CONTENT_SECURITY_POLICY_MSG = l10n.lookup("securityCSPHeaderOnPage");
- const CONTENT_SECURITY_POLICY_REPORT_ONLY_MSG = l10n.lookup("securityCSPROHeaderOnPage");
- const NEXT_URI_HEADER = l10n.lookup("securityReferrerNextURI");
- const CALCULATED_REFERRER_HEADER = l10n.lookup("securityReferrerCalculatedReferrer");
- /* The official names from the W3C Referrer Policy Draft http://www.w3.org/TR/referrer-policy/ */
- const REFERRER_POLICY_NAMES = [ "None When Downgrade (default)", "None", "Origin Only", "Origin When Cross-Origin", "Unsafe URL" ];
- exports.items = [
- {
- // --- General Security information
- name: "security",
- description: l10n.lookup("securityPrivacyDesc"),
- manual: l10n.lookup("securityManual")
- },
- {
- // --- CSP specific Security information
- item: "command",
- runAt: "server",
- name: "security csp",
- description: l10n.lookup("securityCSPDesc"),
- manual: l10n.lookup("securityCSPManual"),
- returnType: "securityCSPInfo",
- exec: function(args, context) {
- var cspJSON = context.environment.document.nodePrincipal.cspJSON;
- var cspOBJ = JSON.parse(cspJSON);
- var outPolicies = [];
- var policies = cspOBJ["csp-policies"];
- // loop over all the different policies
- for (var csp in policies) {
- var curPolicy = policies[csp];
- // loop over all the directive-values within that policy
- var outDirectives = [];
- var outHeader = CONTENT_SECURITY_POLICY_MSG;
- for (var dir in curPolicy) {
- var curDir = curPolicy[dir];
- // when iterating properties within the obj we might also
- // encounter the 'report-only' flag, which is not a csp directive.
- if (dir === POLICY_REPORT_ONLY) {
- outHeader = curPolicy[POLICY_REPORT_ONLY] === true ?
- CONTENT_SECURITY_POLICY_REPORT_ONLY_MSG :
- CONTENT_SECURITY_POLICY_MSG;
- continue;
- }
- // loop over all the directive-sources within that directive
- var outSrcs = [];
- // special case handling for the directives
- // upgrade-insecure-requests and block-all-mixed-content
- // which do not include any srcs
- if (dir === DIR_UPGRADE_INSECURE ||
- dir === DIR_BLOCK_ALL_MIXED_CONTENT) {
- outSrcs.push({
- icon: GOOD_IMG_SRC,
- src: "", // no src
- desc: "" // no description
- });
- }
- for (var src in curDir) {
- var curSrc = curDir[src];
- // the default icon and descritpion of the directive-src
- var outIcon = GOOD_IMG_SRC;
- var outDesc = "";
- if (curSrc.indexOf("*") > -1) {
- outIcon = MOD_IMG_SRC;
- outDesc = WILDCARD_MSG;
- }
- if (curSrc == SRC_UNSAFE_INLINE || curSrc == SRC_UNSAFE_EVAL) {
- outIcon = BAD_IMG_SRC;
- outDesc = XSS_WARNING_MSG;
- }
- outSrcs.push({
- icon: outIcon,
- src: curSrc,
- desc: outDesc
- });
- }
- // append info about that directive to the directives array
- outDirectives.push({
- dirValue: dir,
- dirSrc: outSrcs
- });
- }
- // append info about the policy to the policies array
- outPolicies.push({
- header: outHeader,
- directives: outDirectives
- });
- }
- return outPolicies;
- }
- },
- {
- item: "converter",
- from: "securityCSPInfo",
- to: "view",
- exec: function(cspInfo, context) {
- var url = context.environment.target.url;
- if (cspInfo.length == 0) {
- return context.createView({
- html:
- "<table class='gcli-csp-detail' cellspacing='10' valign='top'>" +
- " <tr>" +
- " <td> <img src='chrome://browser/content/gcli_sec_bad.svg' width='20px' /> </td> " +
- " <td>" + NO_CSP_ON_PAGE_MSG + " <b>" + url + "</b></td>" +
- " </tr>" +
- "</table>"});
- }
- return context.createView({
- html:
- "<table class='gcli-csp-detail' cellspacing='10' valign='top'>" +
- // iterate all policies
- " <tr foreach='csp in ${cspinfo}' >" +
- " <td> ${csp.header} <b>" + url + "</b><br/><br/>" +
- " <table class='gcli-csp-dir-detail' valign='top'>" +
- // >> iterate all directives
- " <tr foreach='dir in ${csp.directives}' >" +
- " <td valign='top'> ${dir.dirValue} </td>" +
- " <td valign='top'>" +
- " <table class='gcli-csp-src-detail' valign='top'>" +
- // >> >> iterate all srs
- " <tr foreach='src in ${dir.dirSrc}' >" +
- " <td valign='center' width='20px'> <img src= \"${src.icon}\" width='20px' /> </td> " +
- " <td valign='center' width='200px'> ${src.src} </td>" +
- " <td valign='center'> ${src.desc} </td>" +
- " </tr>" +
- " </table>" +
- " </td>" +
- " </tr>" +
- " </table>" +
- " </td>" +
- " </tr>" +
- "</table>",
- data: {
- cspinfo: cspInfo,
- }
- });
- }
- },
- {
- // --- Referrer Policy specific Security information
- item: "command",
- runAt: "server",
- name: "security referrer",
- description: l10n.lookup("securityReferrerPolicyDesc"),
- manual: l10n.lookup("securityReferrerPolicyManual"),
- returnType: "securityReferrerPolicyInfo",
- exec: function(args, context) {
- var doc = context.environment.document;
- var referrerPolicy = doc.referrerPolicy;
- var pageURI = doc.documentURIObject;
- var sameDomainReferrer = "";
- var otherDomainReferrer = "";
- var downgradeReferrer = "";
- var otherDowngradeReferrer = "";
- var origin = pageURI.prePath;
- switch (referrerPolicy) {
- case Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER:
- // sends no referrer
- sameDomainReferrer
- = otherDomainReferrer
- = downgradeReferrer
- = otherDowngradeReferrer
- = "(no referrer)";
- break;
- case Ci.nsIHttpChannel.REFERRER_POLICY_ORIGIN:
- // only sends the origin of the referring URL
- sameDomainReferrer
- = otherDomainReferrer
- = downgradeReferrer
- = otherDowngradeReferrer
- = origin;
- break;
- case Ci.nsIHttpChannel.REFERRER_POLICY_ORIGIN_WHEN_XORIGIN:
- // same as default, but reduced to ORIGIN when cross-origin.
- sameDomainReferrer = pageURI.spec;
- otherDomainReferrer
- = downgradeReferrer
- = otherDowngradeReferrer
- = origin;
- break;
- case Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL:
- // always sends the referrer, even on downgrade.
- sameDomainReferrer
- = otherDomainReferrer
- = downgradeReferrer
- = otherDowngradeReferrer
- = pageURI.spec;
- break;
- case Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE:
- // default state, doesn't send referrer from https->http
- sameDomainReferrer = otherDomainReferrer = pageURI.spec;
- downgradeReferrer = otherDowngradeReferrer = "(no referrer)";
- break;
- default:
- // this is a new referrer policy which we do not know about
- sameDomainReferrer
- = otherDomainReferrer
- = downgradeReferrer
- = otherDowngradeReferrer
- = "(unknown Referrer Policy)";
- break;
- }
- var sameDomainUri = origin + "/*";
- var referrerUrls = [
- // add the referrer uri 'referrer' we would send when visiting 'uri'
- {
- uri: pageURI.scheme+'://example.com/',
- referrer: otherDomainReferrer,
- description: l10n.lookup('securityReferrerPolicyOtherDomain')},
- {
- uri: sameDomainUri,
- referrer: sameDomainReferrer,
- description: l10n.lookup('securityReferrerPolicySameDomain')}
- ];
- if (pageURI.schemeIs('https')) {
- // add the referrer we would send on downgrading http->https
- if (sameDomainReferrer != downgradeReferrer) {
- referrerUrls.push({
- uri: "http://"+pageURI.hostPort+"/*",
- referrer: downgradeReferrer,
- description:
- l10n.lookup('securityReferrerPolicySameDomainDowngrade')
- });
- }
- if (otherDomainReferrer != otherDowngradeReferrer) {
- referrerUrls.push({
- uri: "http://example.com/",
- referrer: otherDowngradeReferrer,
- description:
- l10n.lookup('securityReferrerPolicyOtherDomainDowngrade')
- });
- }
- }
- return {
- header: l10n.lookupFormat("securityReferrerPolicyReportHeader",
- [pageURI.spec]),
- policyName: REFERRER_POLICY_NAMES[referrerPolicy],
- urls: referrerUrls
- }
- }
- },
- {
- item: "converter",
- from: "securityReferrerPolicyInfo",
- to: "view",
- exec: function(referrerPolicyInfo, context) {
- return context.createView({
- html:
- "<div class='gcli-referrer-policy'>" +
- " <strong> ${rpi.header} </strong> <br />" +
- " ${rpi.policyName} <br />" +
- " <table class='gcli-referrer-policy-detail' cellspacing='10' >" +
- " <tr>" +
- " <th> " + NEXT_URI_HEADER + " </th>" +
- " <th> " + CALCULATED_REFERRER_HEADER + " </th>" +
- " </tr>" +
- // iterate all policies
- " <tr foreach='nextURI in ${rpi.urls}' >" +
- " <td> ${nextURI.description} (e.g., ${nextURI.uri}) </td>" +
- " <td> ${nextURI.referrer} </td>" +
- " </tr>" +
- " </table>" +
- "</div>",
- data: {
- rpi: referrerPolicyInfo,
- }
- });
- }
- }
- ];
|