summaryrefslogtreecommitdiffstats
path: root/devtools/client/webconsole/test/browser_webconsole_hpkp_invalid-headers.js
blob: 39870fd547add0fe16b0c1f088b484e14325c245 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

// Tests that errors about invalid HPKP security headers are logged to the web
// console.

"use strict";

const TEST_URI = "data:text/html;charset=utf-8,Web Console HPKP invalid " +
                 "header test";
const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" +
                "test/test_hpkp-invalid-headers.sjs";
const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" +
                       "Public_Key_Pinning" + DOCS_GA_PARAMS;
const HPKP_ENABLED_PREF = "security.cert_pinning.hpkp.enabled";
const NON_BUILTIN_ROOT_PREF = "security.cert_pinning.process_headers_from_" +
                              "non_builtin_roots";

add_task(function* () {
  registerCleanupFunction(() => {
    Services.prefs.clearUserPref(HPKP_ENABLED_PREF);
    Services.prefs.clearUserPref(NON_BUILTIN_ROOT_PREF);
  });

  Services.prefs.setBoolPref(HPKP_ENABLED_PREF, true);
  
  yield loadTab(TEST_URI);

  let hud = yield openConsole();

  yield* checkForMessage({
    url: SJS_URL + "?badSyntax",
    name: "Could not parse header error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that could not be " +
          "parsed successfully."
  }, hud);

  yield* checkForMessage({
    url: SJS_URL + "?noMaxAge",
    name: "No max-age error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that did not include " +
          "a \u2018max-age\u2019 directive."
  }, hud);

  yield* checkForMessage({
    url: SJS_URL + "?invalidIncludeSubDomains",
    name: "Invalid includeSubDomains error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that included an " +
          "invalid \u2018includeSubDomains\u2019 directive."
  }, hud);

  yield* checkForMessage({
    url: SJS_URL + "?invalidMaxAge",
    name: "Invalid max-age error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that included an " +
          "invalid \u2018max-age\u2019 directive."
  }, hud);

  yield* checkForMessage({
    url: SJS_URL + "?multipleIncludeSubDomains",
    name: "Multiple includeSubDomains error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that included " +
          "multiple \u2018includeSubDomains\u2019 directives."
  }, hud);

  yield* checkForMessage({
    url: SJS_URL + "?multipleMaxAge",
    name: "Multiple max-age error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that included " +
          "multiple \u2018max-age\u2019 directives."
  }, hud);

  yield* checkForMessage({
    url: SJS_URL + "?multipleReportURIs",
    name: "Multiple report-uri error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that included " +
          "multiple \u2018report-uri\u2019 directives."
  }, hud);

  // The root used for mochitests is not built-in, so set the relevant pref to
  // true to have the PKP implementation return more specific errors.
  Services.prefs.setBoolPref(NON_BUILTIN_ROOT_PREF, true);

  yield* checkForMessage({
    url: SJS_URL + "?pinsetDoesNotMatch",
    name: "Non-matching pinset error displayed successfully",
    text: "Public-Key-Pins: The site specified a header that did not include " +
          "a matching pin."
  }, hud);

  Services.prefs.setBoolPref(NON_BUILTIN_ROOT_PREF, false);

  yield* checkForMessage({
    url: SJS_URL + "?pinsetDoesNotMatch",
    name: "Non-built-in root error displayed successfully",
    text: "Public-Key-Pins: The certificate used by the site was not issued " +
          "by a certificate in the default root certificate store. To " +
          "prevent accidental breakage, the specified header was ignored."
  }, hud);
});

function* checkForMessage(curTest, hud) {
  hud.jsterm.clearOutput();

  BrowserTestUtils.loadURI(gBrowser.selectedBrowser, curTest.url);

  let results = yield waitForMessages({
    webconsole: hud,
    messages: [
      {
        name: curTest.name,
        text: curTest.text,
        category: CATEGORY_SECURITY,
        severity: SEVERITY_WARNING,
        objects: true,
      },
    ],
  });

  yield testClickOpenNewTab(hud, results);
}

function testClickOpenNewTab(hud, results) {
  let warningNode = results[0].clickableElements[0];
  ok(warningNode, "link element");
  ok(warningNode.classList.contains("learn-more-link"), "link class name");
  return simulateMessageLinkClick(warningNode, LEARN_MORE_URI);
}