3a3ec8b5707ef96c4b187b3a9df8179395fa6307
galt
Wed Feb 15 12:14:44 2017 -0800
CSP Cleanup. Moving detailed CSP3 discussion to a separate README. refs #18737
diff --git src/lib/htmshell.c src/lib/htmshell.c
index f6a8528..7a97294 100644
--- src/lib/htmshell.c
+++ src/lib/htmshell.c
@@ -557,71 +557,58 @@
return;
htmlWarnBoxSetUpAlready=TRUE;
// NOTE: There is a duplicate of this function in hg/js/utils.js
// NOTE: Making both IE and FF work is almost impossible. Currently, in IE, if the message
// is forced to the top (calling this routine after
then the box is not resizable
// (dynamically adjusting to its contents). But if this setup is done later in the page
// (at first warning), then IE does resize it. Why?
// FF3.0 (but not FF2.0) was resizable with the following, but it took some experimentation.
// Remember what worked nicely on FF3.0:
// "var app=navigator.appName.substr(0,9); "
// "if(app == 'Microsoft') {warnBox.style.display='';}
// else {warnBox.style.display=''; warnBox.style.width='auto';}"
struct dyString *dy = dyStringNew(2048);
-//fprintf(f, "
"
- //"
"
-// NEW TEST ATTEMPT DEBUG GALT
-// Simply emit the html now. // Seems to be working fine on Chrome so far.
fprintf(f,"
"
"
"
"
"
"
"
"
"
"
\n");
-
-/* ORIGINAL DYNAMIC WAY
-dyStringPrintf(dy,"document.write(\"
"
- "
"
- "
"
- "
"
- "
"
- "
\");\n");
-*/
-
+// TODO we should just move these warnBox functions to utils.js or warning.js or something.
dyStringPrintf(dy,"function showWarnBox() {"
"document.getElementById('warnOK').innerHTML=' OK ';"
"var warnBox=document.getElementById('warnBox');"
"warnBox.style.display=''; warnBox.style.width='65%%';"
"document.getElementById('warnHead').innerHTML='Warning/Error(s):';"
"window.scrollTo(0, 0);"
"}\n");
dyStringPrintf(dy,"function hideWarnBox() {"
"var warnBox=document.getElementById('warnBox');"
"warnBox.style.display='none';"
"var warnList=document.getElementById('warnList');"
"warnList.innerHTML='';"
"var endOfPage = document.body.innerHTML.substr(document.body.innerHTML.length-20);"
-// TODO GALT maybe just looking at the last 20 characters of the html page is no longer enough
-// because the final js inline trash temp gets emitted. Looks like it is 93 characters long.
+// TODO maybe just looking at the last 20 characters of the html page is no longer enough
+// because the final js inline trash temp gets emitted. Looks like it is 93 characters long but could be longer.
+// This might be old cruft needed for a browser issue that no longer exists?
"if(endOfPage.lastIndexOf('-- ERROR --') > 0) { history.back(); }"
"}\n"); // Note OK button goes to prev page when this page is interrupted by the error.
// Added by Galt
dyStringPrintf(dy,"document.getElementById('warnOK').onclick = function() {hideWarnBox();return false;};\n");
-//dyStringPrintf(dy,"$('#warnOK').click(function() {hideWarnBox();return false;});\n"); // jquery version
dyStringPrintf(dy,"window.onunload = function(){}; // Trick to avoid FF back button issue.\n");
jsInline(dy->string);
dyStringFree(&dy);
}
void htmlVaWarn(char *format, va_list args)
/* Write an error message. */
{
va_list argscp;
va_copy(argscp, args);
htmlWarnBoxSetup(stdout); // sets up the warnBox if it hasn't already been done.
char warning[1024];
// html-encode arguments to fight XSS
@@ -887,71 +874,33 @@
safef(nonceClause, sizeof nonceClause, "'nonce-%s'", getNonce());
return cloneString(nonceClause);
}
/* CSP2 Usage Notes
One can add js scripts to a DOM dynamically.
It is critical to use script.setAttribute('nonce', pageNonce);
instead of script.nonce = pageNonce; because nonce is an html attribute,
not a javascript attribute. In places where this is used (like alleles.js)
we should mark this with CSP2 comment because someday CSP3 will automatically
be able to pass the nonce to script children and the command will no longer be
needed.
*/
/* CSP3 Usage Notes
-(NOT IN USE YET).
-We almost went with CSP3 even though it is very new at this time (2017-01-26).
-It has one important new script-src directive 'strict-dynamic' which does 3
-things:
-
-First, the word "strict" means that it only uses nonces -- the whitelist of sites and paths
-is completely ignored. When we adopt it someday we will need to go through
-our source code and add the nonce='random' to our non-inline js script includes.
-There are probably only a few dozen places in the code that do this and it should
-be easy. The reason that whitelists can be a big problem is that they are brittle,
-can grow to be very large and unweildy and hard to maintain. Furthermore, an
-entire large portal often has other stuff there which hackers can exploit and which
-you were not intending to authorize. If the whitelisted site has jsonp endpoints,
-redirection-scripts, AugustusJS, and other fancy js frameworks, or even old jquery includes with bugs,
-then there are exploits that whitelists do not protect against.
-
-Second, the word "dynamic" in the directive means that it dynamically delegates trust authorization
-to other scripts, so that whatever stuff libraries include are automaically trusted recursively.
-Non-inline script libraries, both local and off-site will require nonces alike.
-
-Third, the final thing that 'strict-dynamic' does is that
-when a nonced-script dynamically adds a script to the DOM dynamically with createElement('script')
-and document.head.appendChild(script);, the nonce value is added automatically,
-unlike CSP2. 'script-dynamic' specifically encourages such DOM dynamic additions
-while discouraging more dangerous methods which require raw html string parsing followed by eval such as
-innerHTML and document.write.
-
-These changes are aimed at making CSP more user-friendly and deployable.
-
-So to deploy CSP3 is fairly easy from a code-change point of view. Just add 'strict-dynamic'
-to the CSP policy and add some nonces to the js library include lines. But we do not
-accrue that much value from it over CSP2 at this time. Plus, because there is currently
-no easy way to tell which CSP level a browser supports, and we have no huge whitelist at this time,
-there is not much benefit. Also with CSP2, they gave us the trick of using 'unsafe-inline' together
-with 'nonce=random' so that CSP1 would have no enforcement, but would at least run without errors
-and allow inline js, while CSP2 DOES have nonce-protected inline js. BUT They did not create
-any equivalent policy for backwards compatibility that would likewise disable enforcement in CSP2 browsers
-while enabling full enforcement in CSP3 browsers. Without that trick we are basically stuck
-with a CSP2 level policy until basically nearly all browsers have CSP3. This could take several years,
-even though Chrome and FF already support CSP3 and even MS Edge will have it soon.
-I contacted the designers of 'strict-dynamic', but it was too late to change CSP3.
+ Because of technical backwards-compatibility issues, we cannot use CSP3 until virtually all browsers
+ our users use support it. That could mean perhaps around the year 2021.
+ See README-CSP3.txt for details.
*/
char *getCspPolicyString()
/* get the policy string */
{
// example "default-src 'self'; child-src 'none'; object-src 'none'"
struct dyString *policy = dyStringNew(1024);
dyStringAppend(policy, "default-src *;");
/* more secure method not used yet
dyStringAppend(policy, "default-src 'self';");
dyStringAppend(policy, " child-src 'self';");
*/