Mailing List Archive

rt branch 5.0/strict-browser-security created. rt-5.0.5-96-g585bfdba32
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/strict-browser-security has been created
at 585bfdba32dd2d0a17bbbe504b15d1c39a0afd1d (commit)

- Log -----------------------------------------------------------------
commit 585bfdba32dd2d0a17bbbe504b15d1c39a0afd1d
Author: Jim Brandt <jbrandt@bestpractical.com>
Date: Fri Dec 22 13:57:15 2023 -0500

Convert other Mason templates to new headers template

27bd738eaf created a single method in Web.pm, CacheControlExpiresHeaders
to generate HTTP response headers, specifically those related to
caching instructions for browsers. That was applied to Helpers, but
wasn't used for regular RT pages.

Later, 915eb4b7d0 sought to fix a regression that resulted in
cache headers not being sent for static files returned via
Plack::Middleware::Static. That fix went to great lengths to
try to re-use functionality from CacheControlExpiresHeaders,
including moving all of the code to GetStaticHeaders. This
probably wasn't really needed since it's reasonable to allow
the special case static handler to send it's own one or two headers.
It also made the code confusing since dynamic pages in Mason
called CacheControlExpiresHeaders, which then called GetStaticHeaders
to get headers for responses that were not static.

This update gets all of the Mason web pages using the same code
for these headers. It leaves the current methods in place to continue
handling static files. That can likely be simplified and cleaned up
in a future commit.

diff --git a/share/html/Helpers/Autocomplete/autohandler b/share/html/Helpers/Autocomplete/autohandler
index a51884ac96..f5bd474ea6 100644
--- a/share/html/Helpers/Autocomplete/autohandler
+++ b/share/html/Helpers/Autocomplete/autohandler
@@ -46,8 +46,6 @@
%#
%# END BPS TAGGED BLOCK }}}
<%init>
- RT::Interface::Web::CacheControlExpiresHeaders( Time => 2 * 60 );
-
- $m->call_next;
+$m->comp('/Elements/HttpResponseHeaders', MaxAgeSeconds => 2 * 60);
+$m->call_next;
</%init>
-
diff --git a/share/html/Helpers/RightsInspector/Search b/share/html/Helpers/RightsInspector/Search
index f3829c8f4a..7f82bf6de9 100644
--- a/share/html/Helpers/RightsInspector/Search
+++ b/share/html/Helpers/RightsInspector/Search
@@ -49,7 +49,7 @@
use RT::RightsInspector;
my $results = RT::RightsInspector->Search(%ARGS);
$r->content_type('application/json; charset=utf-8');
-RT::Interface::Web::CacheControlExpiresHeaders( Time => 'no-cache' );
+$m->comp('/Elements/HttpResponseHeaders');
$m->out(JSON($results));
$m->abort;
</%INIT>
diff --git a/share/html/Helpers/autohandler b/share/html/Helpers/autohandler
index 870487a8cf..9247a4195a 100644
--- a/share/html/Helpers/autohandler
+++ b/share/html/Helpers/autohandler
@@ -46,7 +46,6 @@
%#
%# END BPS TAGGED BLOCK }}}
<%init>
- RT::Interface::Web::CacheControlExpiresHeaders( Time => 'no-cache' );
-
- $m->call_next;
+$m->comp('/Elements/HttpResponseHeaders');
+$m->call_next;
</%init>
diff --git a/t/web/helpers-http-cache-headers.t b/t/web/helpers-http-cache-headers.t
index 2e661a231b..cb8799d119 100644
--- a/t/web/helpers-http-cache-headers.t
+++ b/t/web/helpers-http-cache-headers.t
@@ -73,8 +73,8 @@ diag "set up expected date headers";
'Expires' => 'Sun, 05 May 2013 15:28:19 GMT',
},
default => {
- 'Cache-Control' => 'no-cache',
- 'Expires' => 'Fri, 05 Apr 2013 15:28:19 GMT',
+ 'Cache-Control' => 'no-cache, max-age=0',
+ 'Expires' => 'Fri, 05 Apr 2013 15:27:49 GMT',
},
};


commit 4782390ca780113b62fbe1510d056c028803cdef
Author: Jim Brandt <jbrandt@bestpractical.com>
Date: Mon Dec 18 16:01:06 2023 -0500

Add $WebStrictBrowserCache option to disable browser cache

RT systems that store sensitive data may want to disable all
browser cache and back button behavior. This option enables
that and moves these headers to a separate Mason template
for easy override.

See: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/04-Authentication_Testing/06-Testing_for_Browser_Cache_Weaknesses

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 6433198a36..39b4e296f6 100644
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1573,6 +1573,20 @@ off I<unless> user connections to RT are secured by some other method.

Set($WebSecureCookies, 1);

+=item C<$WebStrictBrowserCache>
+
+As part of normal operation, browsers typically store some browsing
+history, enabling the Back button to work. Browsers also often
+cache pages in the browsing history to improve performance.
+
+Enable this option if you are using RT with highly ssensitive
+information and want to signal the browser to not store any history
+or cache any data. The default is disabled.
+
+=cut
+
+Set($WebStrictBrowserCache, 0);
+
=item C<$WebHttpOnlyCookies>

Default RT's session cookie to not being directly accessible to
diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm
index 04fbe3dcd5..5a7edccc35 100644
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@ -1889,6 +1889,9 @@ our %META;
WebSecureCookies => {
Widget => '/Widgets/Form/Boolean',
},
+ WebStrictBrowserCache => {
+ Widget => '/Widgets/Form/Boolean',
+ },
WikiImplicitLinks => {
Widget => '/Widgets/Form/Boolean',
},
diff --git a/share/html/Elements/Header b/share/html/Elements/Header
index 14be9196af..6dc9396461 100644
--- a/share/html/Elements/Header
+++ b/share/html/Elements/Header
@@ -123,8 +123,7 @@ $lang = $session{'CurrentUser'}->LanguageHandle->language_tag
&& $session{'CurrentUser'}->LanguageHandle
&& $session{'CurrentUser'}->LanguageHandle->language_tag;

-$r->headers_out->{'Pragma'} = 'no-cache';
-$r->headers_out->{'Cache-control'} = 'no-cache';
+$m->comp('/Elements/HttpResponseHeaders');

my $id = $m->request_comp->path;
$id =~ s|^/||g;
diff --git a/share/html/m/_elements/header b/share/html/Elements/HttpResponseHeaders
similarity index 57%
copy from share/html/m/_elements/header
copy to share/html/Elements/HttpResponseHeaders
index fbf873c61f..3b452f01a1 100644
--- a/share/html/m/_elements/header
+++ b/share/html/Elements/HttpResponseHeaders
@@ -45,30 +45,55 @@
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
-<%args>
-$title => loc('RT for [_1]', RT->Config->Get('rtname'))
-$show_home_button => 1
-</%args>
-<%init>
+<%INIT>
+
+# Since data in the DB can change at any time, the default headers
+# for dynamic content (content generated from most Mason templates) is:
+#
+# Cache-control: no-cache
+# Pragma: no-cache
+# Expires: [.a short time in the past to account for any time drift]
+
+# Pragma is deprecated and usually ignored if Cache-control is sent.
+# Should only be used by HTTP/1.0 clients.
$r->headers_out->{'Pragma'} = 'no-cache';
-$r->headers_out->{'Cache-control'} = 'no-cache';
-</%init>
-<html>
-<head>
-<link rel="stylesheet" type="text/css" href="<%RT->Config->Get('WebPath')%>/static/css/mobile.css"/>
-<title><%$title%></title>
-% my ($jquery) = grep { /^jquery-\d+\./ } RT::Interface::Web->JSFiles;
-<script src="<% RT->Config->Get('WebPath') %>/static/js/<% $jquery %>"></script>
-<meta name="viewport" content="width=device-width height=device-height user-scalable=yes"/>
-<& /Elements/Framekiller &>
-</head>
-<body>
-% if ($show_home_button) {
-% # The align is for older browsers, like the blackberry
-<div id="gohome" align="right">
-<a href="<%RT->Config->Get('WebPath')%>/m/"><&|/l&>Homepage</&></a>
-</div>
-% }
-% if ($title) {
-<h1><%$title%></h1>
-% }
+
+my $cache_control = 'no-cache';
+
+my $expires = RT::Date->new(RT->SystemUser);
+$expires->SetToNow;
+
+if ( $MaxAgeSeconds && !RT->Config->Get('WebStrictBrowserCache') ) {
+ $expires->AddSeconds($MaxAgeSeconds);
+
+ # Expires is an older header and has been superseded by Cache-control
+ # and max-age, so set that also. New browsers will use max-age and
+ # ignore Expires.
+
+ # We're allowing a short cache, so replace no-cache with max-age.
+
+ $cache_control = "max-age=$MaxAgeSeconds, private"
+}
+else {
+ # Setting Expires to 0, a common approach to "immediately expired"
+ # doesn't send an Expires header from Mason, so set a little in the past.
+
+ $expires->AddSeconds(-30);
+ $cache_control .= ', max-age=0';
+}
+
+$r->headers_out->{'Expires'} = $expires->RFC2616;
+
+if ( RT->Config->Get('WebStrictBrowserCache') ) {
+
+ # Instruct the browser not to cache or store anything
+ $cache_control .= ', no-store, must-revalidate, s-maxage=0';
+}
+
+$r->headers_out->{'Cache-control'} = $cache_control;
+
+$m->callback( %ARGS, CallbackName => 'End' );
+</%INIT>
+<%ARGS>
+$MaxAgeSeconds => undef # Time in seconds to allow for cache
+</%ARGS>
diff --git a/share/html/m/_elements/header b/share/html/m/_elements/header
index fbf873c61f..e82459e578 100644
--- a/share/html/m/_elements/header
+++ b/share/html/m/_elements/header
@@ -50,8 +50,7 @@ $title => loc('RT for [_1]', RT->Config->Get('rtname'))
$show_home_button => 1
</%args>
<%init>
-$r->headers_out->{'Pragma'} = 'no-cache';
-$r->headers_out->{'Cache-control'} = 'no-cache';
+$m->comp('/Elements/HttpResponseHeaders');
</%init>
<html>
<head>

-----------------------------------------------------------------------


hooks/post-receive
--
rt
_______________________________________________
rt-commit mailing list
rt-commit@lists.bestpractical.com
https://lists.bestpractical.com/mailman/listinfo/rt-commit