Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Disallow inline javascript unless protected by a nonce. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
ff747b5151fa2edaedfd7dd2b109b1c1 |
User & Date: | drh 2018-08-29 11:06:36.174 |
Context
2018-08-29
| ||
11:17 | Updates to the "How The Download Page Works" document. ... (check-in: 498cfbf7 user: drh tags: trunk) | |
11:06 | Disallow inline javascript unless protected by a nonce. ... (check-in: ff747b51 user: drh tags: trunk) | |
11:04 | Try to start a new write transaction before updating the VCACHE table. This will hopefully prevent occasional "database is locked" errors when browsing the documentation. ... (check-in: 03979823 user: drh tags: trunk) | |
2018-08-26
| ||
03:35 | Applied the new CSP nonce to the <script> tags in the header for the Enhanced Original, Eagle, and Xekri skins, else the clock in the upper right breaks and Chrome gives an error about the CSP violation. ... (Closed-Leaf check-in: b9d86ed2 user: wyoung tags: csp-nonce) | |
Changes
Changes to skins/eagle/header.txt.
︙ | ︙ | |||
69 70 71 72 73 74 75 | if {[info exists login]} { puts "Logged in as $login" } else { puts "Not logged in" } </th1></nobr><small><div id="clock"></div></small></div> </div> | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | if {[info exists login]} { puts "Logged in as $login" } else { puts "Not logged in" } </th1></nobr><small><div id="clock"></div></small></div> </div> <th1>html "<script nonce='$nonce'>"</th1> function updateClock(){ var e = document.getElementById("clock"); if(e){ var d = new Date(); function f(n) { return n < 10 ? '0' + n : n; } |
︙ | ︙ |
Changes to skins/enhanced1/header.txt.
︙ | ︙ | |||
69 70 71 72 73 74 75 | if {[info exists login]} { puts "Logged in as $login" } else { puts "Not logged in" } </th1></nobr><small><div id="clock"></div></small></div> </div> | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | if {[info exists login]} { puts "Logged in as $login" } else { puts "Not logged in" } </th1></nobr><small><div id="clock"></div></small></div> </div> <th1>html "<script nonce='$nonce'>"</th1> function updateClock(){ var e = document.getElementById("clock"); if(e){ var d = new Date(); function f(n) { return n < 10 ? '0' + n : n; } |
︙ | ︙ |
Changes to skins/xekri/header.txt.
︙ | ︙ | |||
69 70 71 72 73 74 75 | if {[info exists login]} { puts "Logged in as $login" } else { puts "Not logged in" } </th1></nobr><small><div id="clock"></div></small></div> </div> | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | if {[info exists login]} { puts "Logged in as $login" } else { puts "Not logged in" } </th1></nobr><small><div id="clock"></div></small></div> </div> <th1>html "<script nonce='$nonce'>"</th1> function updateClock(){ var e = document.getElementById("clock"); if(e){ var d = new Date(); function f(n) { return n < 10 ? '0' + n : n; } |
︙ | ︙ |
Changes to src/codecheck1.c.
︙ | ︙ | |||
396 397 398 399 400 401 402 403 404 405 406 407 408 409 | { "json_new_string_f", 1, 0 }, { "json_set_err", 2, 0 }, { "json_warn", 2, 0 }, { "mprintf", 1, 0 }, { "socket_set_errmsg", 1, 0 }, { "ssl_set_errmsg", 1, 0 }, { "style_header", 1, FMT_HTML }, { "style_set_current_page", 1, FMT_URL }, { "style_submenu_element", 2, FMT_URL }, { "style_submenu_sql", 3, FMT_SQL }, { "webpage_error", 1, FMT_SAFE }, { "xhref", 2, FMT_URL }, }; | > | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | { "json_new_string_f", 1, 0 }, { "json_set_err", 2, 0 }, { "json_warn", 2, 0 }, { "mprintf", 1, 0 }, { "socket_set_errmsg", 1, 0 }, { "ssl_set_errmsg", 1, 0 }, { "style_header", 1, FMT_HTML }, { "style_js_onload", 1, FMT_HTML }, { "style_set_current_page", 1, FMT_URL }, { "style_submenu_element", 2, FMT_URL }, { "style_submenu_sql", 3, FMT_SQL }, { "webpage_error", 1, FMT_SAFE }, { "xhref", 2, FMT_URL }, }; |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | /* ** Flags for various javascript files needed prior to </body> */ static int needHrefJs = 0; /* href.js */ static int needSortJs = 0; /* sorttable.js */ static int needGraphJs = 0; /* graph.js */ /* ** Generate and return a anchor tag like this: ** ** <a href="URL"> ** or <a id="ID"> ** ** The form of the anchor tag is determined by the g.javascriptHyperlink | > > > > > > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* ** Flags for various javascript files needed prior to </body> */ static int needHrefJs = 0; /* href.js */ static int needSortJs = 0; /* sorttable.js */ static int needGraphJs = 0; /* graph.js */ /* ** Extra JS added to the end of the file. */ static Blob blobJs = BLOB_INITIALIZER; static Blob blobOnLoad = BLOB_INITIALIZER; /* ** Generate and return a anchor tag like this: ** ** <a href="URL"> ** or <a id="ID"> ** ** The form of the anchor tag is determined by the g.javascriptHyperlink |
︙ | ︙ | |||
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | static void image_url_var(const char *zImageName){ char *zVarPrefix = mprintf("%s_image", zImageName); char *zConfigName = mprintf("%s-image", zImageName); url_var(zVarPrefix, zConfigName, zImageName); free(zVarPrefix); free(zConfigName); } /* ** Default HTML page header text through <body>. If the repository-specific ** header template lacks a <body> tag, then all of the following is ** prepended. */ static char zDfltHeader[] = @ <html> @ <head> @ <base href="$baseurl/$current_page" /> @ <meta http-equiv="Content-Security-Policy" \ | > > > > > > > > > > > > > > | > > | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | static void image_url_var(const char *zImageName){ char *zVarPrefix = mprintf("%s_image", zImageName); char *zConfigName = mprintf("%s-image", zImageName); url_var(zVarPrefix, zConfigName, zImageName); free(zVarPrefix); free(zConfigName); } /* ** Return a random nonce that is stored in static space. For a particular ** run, the same nonce is always returned. */ char *style_nonce(void){ static char zNonce[52]; if( zNonce[0]==0 ){ unsigned char zSeed[24]; sqlite3_randomness(24, zSeed); encode16(zSeed,(unsigned char*)zNonce,24); } return zNonce; } /* ** Default HTML page header text through <body>. If the repository-specific ** header template lacks a <body> tag, then all of the following is ** prepended. */ static char zDfltHeader[] = @ <html> @ <head> @ <base href="$baseurl/$current_page" /> @ <meta http-equiv="Content-Security-Policy" \ @ content="default-src 'self' data: ; \ @ script-src 'self' 'nonce-$<nonce>' ;\ @ style-src 'self' 'unsafe-inline'" /> @ <meta name="viewport" content="width=device-width, initial-scale=1.0"> @ <title>$<project_name>: $<title></title> @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" \ @ href="$home/timeline.rss" /> @ <link rel="stylesheet" href="$stylesheet_url" type="text/css" \ @ media="screen" /> @ </head> |
︙ | ︙ | |||
400 401 402 403 404 405 406 407 408 409 410 411 412 413 | cgi_destination(CGI_HEADER); @ <!DOCTYPE html> if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); /* Generate the header up through the main menu */ Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); Th_Store("project_description", db_get("project-description","")); Th_Store("title", zTitle); Th_Store("baseurl", g.zBaseURL); Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); Th_Store("home", g.zTop); Th_Store("index_page", db_get("index-page","/home")); | > | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | cgi_destination(CGI_HEADER); @ <!DOCTYPE html> if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); /* Generate the header up through the main menu */ Th_Store("nonce", style_nonce()); Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); Th_Store("project_description", db_get("project-description","")); Th_Store("title", zTitle); Th_Store("baseurl", g.zBaseURL); Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); Th_Store("home", g.zTop); Th_Store("index_page", db_get("index-page","/home")); |
︙ | ︙ | |||
521 522 523 524 525 526 527 | */ void style_load_js(const char *zName){ int i; for(i=0; i<nJsToLoad; i++){ if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return; } if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){ | | > > > | | | | > > > > > > > > > > > > > > > > | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | */ void style_load_js(const char *zName){ int i; for(i=0; i<nJsToLoad; i++){ if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return; } if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){ fossil_panic("too many JS files"); } azJsToLoad[nJsToLoad++] = zName; } /* ** Generate code to load all required javascript files. */ static void style_load_all_js_files(void){ int i; if( needHrefJs ){ int nDelay = db_get_int("auto-hyperlink-delay",0); int bMouseover; /* Load up the page data */ bMouseover = (!g.isHuman || db_get_boolean("auto-hyperlink-ishuman",0)) && db_get_boolean("auto-hyperlink-mouseover",0); @ <script id='href-data' type='application/json'>\ @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> } @ <script nonce="%h(style_nonce())"> if( needHrefJs ){ cgi_append_content(builtin_text("href.js"),-1); } if( needSortJs ){ cgi_append_content(builtin_text("sorttable.js"),-1); } if( needGraphJs ){ cgi_append_content(builtin_text("graph.js"),-1); } for(i=0; i<nJsToLoad; i++){ cgi_append_content(builtin_text(azJsToLoad[i]),-1); } if( blob_size(&blobOnLoad)>0 ){ @ window.onload = function(){ cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad)); cgi_append_content("\n}\n", -1); } @ </script> } /* ** Extra JS to run after all content is loaded. */ void style_js_onload(const char *zFormat, ...){ va_list ap; va_start(ap, zFormat); blob_vappendf(&blobOnLoad, zFormat, ap); va_end(ap); } /* ** Draw the footer at the bottom of the page. */ void style_footer(void){ const char *zFooter; |
︙ | ︙ |