Once a CSP has been correctly configured such that no violations occur in normal circumstances, it seems desirable to place some restrictions on the number of violations which will be logged (by the default Drupal handler) should violations start to occur.

Picking sensible default values for these limits is a bit tricky...

If the CSP is correct and there are violations, then the number of reports will depend on the violation(s) and of course the popularity of the page(s) in which they occur.

If the CSP is incorrect (or becomes incorrect with subsequent changes to the site), then there may be many unintentional violations. (e.g. if triggered by a new global page element on a popular site.)

In either case I don't think that SecKit can predict what those numbers might actually look like for any given site, so my broad inclination is to base restrictions on "what's liable to cause performance problems". Which of course is also incredibly variable, but is probably still a better basis for extracting some practical baseline figures from.

The numbers I've pulled out of the air are:

Maximum CSP reports by all users: 1000 in a 3600 second (1 hr) window
Maximum CSP reports by a single user: 100 in a 900 second (15 min) window
Maximum report size: 4096 bytes (which should be excessive for a real report).

These are high enough that they could still cause some undesirable effects (dblog's default row limit is 1000 for starters), but I don't want to try to detect and adjust figures based on whether any particular watchdog module is enabled and how it's configured.

(Any recommendations are welcomed.)

Each of those limits is configurable, and they can also be disabled entirely, but for sites with existing CSPs, the limits will be enforced by default.

People in the initial stages of configuring a CSP would almost immediately blow past those per-user limits, however, which would mean that useful reports for establishing a CSP would be lost; so hook_install overrides this default in order to allow unlimited reporting, so that we do not cause problems for users who newly install SecKit. Similarly if SecKit is already installed, but the CSP configuration was in its default state, we do the same thing (in an update hook) so that if/when they start working on a CSP, they will start out with unlimited reporting.

n.b. I don't feel there are any sensible values which would cater both for initial CSP development and for subsequent flooding of a stable CSP.

Issue fork seckit-2694029

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jweowu created an issue. See original summary.

jweowu’s picture

StatusFileSize
new11.36 KB
jweowu’s picture

Assigned: jweowu » Unassigned
jweowu’s picture

Status: Needs review » Fixed

I've previously given this a fair amount of testing myself, and no one has commented in the past two months, so I've pushed this to 7.x-1.x.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

jweowu’s picture

Version: 7.x-1.x-dev » 8.x-1.x-dev
Category: Feature request » Task
Status: Closed (fixed) » Active

Needs port to 8.x

kmoll’s picture

I can port this over to D8. Based on the description I feel this is a sensible way to do it. By default things are the same and open. People can then choose to adjust the setting to prevent any sort of performance issue.

kmoll’s picture

Assigned: Unassigned » kmoll
kmoll’s picture

@jweowu I was wondering why there is the disable seckit value in the config. Shouldn't users disable the module to ensure that functionality?

jweowu’s picture

Mostly it's just a convenience which was trivial to add. It lets people toggle the functionality on and off when testing, without the annoyance of a full module disable/enable (which may be irritatingly slow on larger sites).

kmoll’s picture

Fair enough.

One question though, I am trying to write a test for this, but it doesn't seem as if the simpletest browser test case sends the report, so not sure its possible to write automated test for this. Do you know if this is possible or not with simpletest?

kmoll’s picture

StatusFileSize
new14.62 KB

updated patch for D8.

kmoll’s picture

Status: Active » Needs review

The last submitted patch, 2: seckit-csp_flood_control-2694029-2.patch, failed testing.

jribeiro’s picture

Status: Needs review » Reviewed & tested by the community

+1 RTBC

jweowu’s picture

> Do you know if this is possible or not with simpletest?

Not offhand, sorry. I never tried to write a test for this.

naveenvalecha’s picture

Status: Reviewed & tested by the community » Needs work

Thanks for the patch

  1. +++ b/config/install/seckit.settings.yml
    @@ -39,3 +39,13 @@ seckit_various:
    +seckit_advanced:
    +  disable_seckit: FALSE
    +  unlimited_csp_reports: TRUE
    +  csp_limits:
    +    max_size: 4096
    +    flood:
    +      limit_user: 100
    +      window_user: 900
    +      limit_global: 1000
    +      window_global: 3600
    

    We are adding more keys in the config. This needs an hook_post_update_NAME for adding new keys to the config store. and a test class that would extend UpdatePathTestBase

  2. +++ b/src/Form/SecKitSettingsForm.php
    @@ -520,6 +537,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +      '#title' => t('Advanced options'),
    

    use injectable t instead of t i.e. use $this->t
    Address it at other places as well.

  3. +++ b/src/Form/SecKitSettingsForm.php
    @@ -520,6 +537,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +      // '#description' => t(''),
    

    Remove this commented line as the title makes more sense.

  4. +++ b/src/Form/SecKitSettingsForm.php
    @@ -520,6 +537,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +    if ($config->get('seckit_advanced.disable_seckit') && empty($_POST)) {
    

    Inject the request stack instead of naked usage of $_POST

  5. +++ b/src/Form/SecKitSettingsForm.php
    @@ -520,6 +537,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +      '#open' => TRUE, //($options['seckit_advanced']['csp_limits']['flood'] == $defaults['seckit_advanced']['csp_limits']['flood']),
    

    is commented code needed here ? if not remove it.

kmoll’s picture

StatusFileSize
new52.86 KB

I have updated the patch to reflect these comments.

kmoll’s picture

Status: Needs work » Needs review
jweowu’s picture

Could someone please make the unrelated t() vs $this->t() changes into a separate issue/patch so that can be committed independently/first. The patch for this can depend on that one.

If we can separate patches for general D8 changes from patches for specific features, the code history will be rather cleaner. I'm not too fussed for really trivial additions; but in this case the patch jumped from 15K to 53K, which is a lot of extra noise.

naveenvalecha’s picture

Assigned: kmoll » Unassigned
Status: Needs review » Needs work

Regarding #17.1,
Maintainers,
As the module has relesed a alpha yet and in the alpha phase the changes in config schema is possible as drupal core follows. So do we really need the hook_post_update_NAME ? If yes then I think no.

#20.1

Could someone please make the unrelated t() vs $this->t() changes into a separate issue/patch so that can be committed independently/first. The patch for this can depend on that one.

I'm +1 to this. Let's limit the scope of this issue.

kmoll’s picture

As far as the update, I don't think its completely necessary given the alpha state, but Its there in the patch, so I don't see any harm in keeping it in, unless there is some precedence that states that it absolutely shouldn't be there.

I am also +1 for removing the $this->t, I can create another issue for that and update this patch.

kmoll’s picture

Assigned: Unassigned » kmoll
naveenvalecha’s picture

but Its there in the patch,

I was more concerned about the hook_update_n in the module which is not unit-testable.So in my opinion instead of pushing the non-testable code, better to remove it if its not needed.Rest is all on maintainers.

kmoll’s picture

StatusFileSize
new14.43 KB

I've reverted the $this->t() so the patch doesn't have to put a dependency on another patch.

kmoll’s picture

StatusFileSize
new14.55 KB

actually, need to update the 'seckit_advanced' section to use $this->t() because that section is not in the patch for #2788701: Use t() using DI in SecKitSettingsForm

kmoll’s picture

Status: Needs work » Needs review
naveenvalecha’s picture

Status: Needs review » Needs work

Great thanks for the patch! Few more that are needed to let me RTBC it

  1. +++ b/seckit.module
    @@ -45,3 +54,55 @@ function _seckit_form_alter_login_form(&$form, FormStateInterface &$form_state)
    +function _seckit_csp_report_flooding_detected() {
    

    Move this function to a service with name may be "seckit.helper" choose a better name if you know.

  2. +++ b/src/EventSubscriber/SecKitEventSubscriber.php
    @@ -32,6 +32,11 @@ class SecKitEventSubscriber implements EventSubscriberInterface {
    +    $config = \Drupal::config('seckit.settings');
    +    if ($config->get('seckit_advanced.disable_seckit')) {
    +      return;
    +    }
    

    What's the need of getting the seckit settings again. you can access it from $this->config which is getting set in constructor

  3. +++ b/src/EventSubscriber/SecKitEventSubscriber.php
    @@ -41,6 +46,11 @@ class SecKitEventSubscriber implements EventSubscriberInterface {
    +    $config = \Drupal::config('seckit.settings');
    +    if ($config->get('seckit_advanced.disable_seckit')) {
    +      return;
    +    }
    

    same as above. access it from $this->config

  4. +++ b/src/EventSubscriber/SecKitEventSubscriber.php
    @@ -106,7 +116,6 @@ class SecKitEventSubscriber implements EventSubscriberInterface {
    -    global $base_root;
    

    +1

  5. +++ b/src/EventSubscriber/SecKitEventSubscriber.php
    @@ -131,7 +140,6 @@ class SecKitEventSubscriber implements EventSubscriberInterface {
    -    $warning = t($message, $args);
    

    +1 Nice :)

  6. +++ b/src/Form/SecKitSettingsForm.php
    @@ -522,6 +539,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +      drupal_set_message(t("Security Kit is currently disabled in the Advanced options (below)."), 'warning');
    

    use injectable $this->t and use single quotes

  7. +++ b/src/Form/SecKitSettingsForm.php
    @@ -522,6 +539,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +    // CSP report limits
    

    dot at the end of the comment.

  8. +++ b/src/Form/SecKitSettingsForm.php
    @@ -522,6 +539,94 @@ class SecKitSettingsForm extends ConfigFormBase {
    +      '#description' => $this->t("Reports breaching these limits will not be logged."),
    

    use single quotes. Its not a standard yet but php gives performance hits using single quotes over doubel

The last submitted patch, 26: 2694029-flood-control-26.patch, failed testing.

jweowu’s picture

kmoll’s picture

StatusFileSize
new15.84 KB

as far as #1, I think there are a lot of methods that need to go in this. I agree that we need a service and it should be implemented. I think its outside the scope of this 1 issue. I think we should create another issue for it. I've addressed all the other issues as well as implemented the patch that @jweowu just posted.

kmoll’s picture

Status: Needs work » Needs review
naveenvalecha’s picture

Status: Needs review » Needs work

as far as #1, I think there are a lot of methods that need to go in this. I agree that we need a service and it should be implemented. I think its outside the scope of this 1 issue. I think we should create another issue for it.

+1 Create a followup issue for it

  1. +++ b/seckit.install
    @@ -0,0 +1,21 @@
    +<?php
    +
    +/**
    + * @file
    + *   Install file for seckit module.
    + */
    +
    +/**
    + * Set defaults for seckit_advanced settings.
    + */
    +function seckit_update_8001() {
    +  $config = \Drupal::configFactory()->getEditable('seckit.settings');
    +  $config->set('seckit_advanced.disable_seckit', FALSE)
    +    ->set('seckit_advanced.unlimited_csp_reports', TRUE)
    +    ->set('seckit_advanced.csp_limits.max_size', 4096)
    +    ->set('seckit_advanced.csp_limits.flood.limit_user', 100)
    +    ->set('seckit_advanced.csp_limits.flood.window_user', 900)
    +    ->set('seckit_advanced.csp_limits.flood.limit_global', 1000)
    +    ->set('seckit_advanced.csp_limits.flood.window_global', 3600)
    +    ->save();
    +}
    

    As specified above we need hook_post_update_NAME for the config update changes. Profit for this is hook_post_update_NAME is testable as well.

  2. +++ b/seckit.module
    @@ -20,6 +20,15 @@ define('SECKIT_X_FRAME_ALLOW_FROM', 3); // set X-Frame-Options HTTP header to Al
    +define('SECKIT_CSP_REPORT_MAX_SIZE', 4096); // Max accepted byte count
    +define('SECKIT_CSP_REPORT_FLOOD_LIMIT_USER', 100); // Max reports per IP address...
    +define('SECKIT_CSP_REPORT_FLOOD_WINDOW_USER', 900); // ...per time window (in seconds)
    +define('SECKIT_CSP_REPORT_FLOOD_LIMIT_GLOBAL', 1000); // Max reports globally...
    +define('SECKIT_CSP_REPORT_FLOOD_WINDOW_GLOBAL', 3600); // ...per time window (in seconds)
    

    Move the comments to above. This is violating the coding standards.Address it at other places as well.

kmoll’s picture

StatusFileSize
new15.03 KB

Rather than having the update at all, I am removing this since its an alpha release and we don't necessarily need to support this. I fixed #2 for the code added in the patch, but there is already an issue to fix coding style for the rest of the module here #2715611: Fix coding style to meet Drupal standards so I did not address it in other places.

kmoll’s picture

Status: Needs work » Needs review
naveenvalecha’s picture

Rather than having the update at all, I am removing this since its an alpha release and we don't necessarily need to support this.

yup we don't need during alpha phase

I fixed #2 for the code added in the patch, but there is already an issue to fix coding style for the rest of the module here #2715611: Fix coding style to meet Drupal standards so I did not address it in other places.

Thanks but we should not pollute more.Fix this at other places too. I'll be more comfortable to RTBC it after these gets fixed

jweowu’s picture

I recently edited a second 7.x commit into my comment #30, so that will need to be included too. Apologies for the reduced visibility on that change.

naveenvalecha’s picture

@jweowu ,
could you share the link of the commit & issue ?

jweowu’s picture

I'm just referring to comment #30 above.

The first commit linked in that comment has been incorporated in the 8.x patch, but the second one (which is more recent) has not.

kmoll’s picture

StatusFileSize
new16.7 KB

I've updated this with the updates from the second patch.

@naveenvalecha, I updated the coding style for the sections that I updated with this patch to not pollute it more. I disagree with updating it in other places as that is already taken care of by the issue I linked to above.

jweowu’s picture

It's not correct to throw new NotFoundHttpException(); when the module or CSP option is disabled. The violation report may be entirely valid (from a cached page).

In the 7.x branch I never return a non-success response, even if I'm ignoring the report.

(Unless there's some beneficial standardised behaviour for user agents if they receive a 404 that you're aware of?)

kmoll’s picture

jweowu, I don't necessarily need to throw a 404, but I can not just return, The API controller requires a specific Response object, I can return a blank object I believe which will be a 200. But if CSP is not enabled, I would think that it should act as if the call back doesn't exist, which IMO would be a 404.

naveenvalecha’s picture

I disagree with updating it in other places as that is already taken care of by the issue I linked to above.

I'm fine with that

RTBC +1 leaving this for @jweowu to see his changes in #30 got accomodated

jweowu’s picture

if CSP is not enabled, I would think that it should act as if the call back doesn't exist, which IMO would be a 404.

We don't differentiate between "never been enabled" and "temporarily disabled" though, and I also don't know whether a user-agent might react differently if it gets a 404. If they don't, then there is no benefit to using an error response over a 200. If they do then there is a real potential to cause problems for CSP testing.

Consider that a user agent might decide not to send any more violation reports for some duration, if it has received a 404...

When the site admin enables the CSP feature, pages will start being cached with CSP headers and so browsers may send violation reports. If the feature is then disabled, the cached pages will still contain the headers, and the site then responds to subsequent reports with a 404. When the feature is re-enabled, the browser may fail to send the violation reports that it should send (which may or may not be apparent to the site admin, depending on the significance of the violation; but it won't be clear what's gone wrong either way).

In short, I don't think there's any problems with using a 200 response in all cases, whereas there might be problems not doing that, and this is why I haven't used a menu access callback, or returned errors.

Tangentially, while D8 code in general is all kinds of different to D7 code, I don't wish the essential behaviour of this module to diverge between the two versions. Behavioural changes really need to be flagged for discussion and porting (in one direction or the other).

Furthermore, I'd really prefer if this approach extended to not arbitrarily modifying the original code in areas where the two versions can actually coincide. Once the D8 version stabilises, we're going to want to maintain both versions together as much as possible, and the fewer unnecessary differences between the versions, the easier that's going to be.

A simple example in this patch being the change from:

  $enforce_limits = !$options['seckit_advanced']['unlimited_csp_reports'];
  if ($enforce_limits && _seckit_csp_report_flooding_detected()) { ...

to

$unlimited_reports = $config->get('seckit_advanced.unlimited_csp_reports');
if (!$unlimited_reports && _seckit_csp_report_flooding_detected()) { ...

Here we have a double-negative in "not unlimited" which hinders comprehension. I had purposefully countered that by assigning it the positive label "enforce limits" to use in the subsequent conditionals. I would argue therefore that this change is (a) worse for code readability and (b) worse (on account of being arbitrarily different) for subsequent module maintenance across versions, as any later changes need to take the inversion into account.

In the same patch, we have a sequential change. In the D7 code I check the server variables first, before loading the seckit config, in order to defer loading the config until we need to. In the D8 patch the order has changed. I don't think this specific instance is super important -- loading the config isn't going to be slow, and the violation requests aren't likely to fail those tests -- but it's different which in general means (a) we might have a logical bug in one version and not the other; and (b) when porting changes people need to question why it's different, and then expend mental effort considering whether the differences have consequences.

Multiply this by any number of unnecessary changes, and it has a practical effect on the ease of maintenance that I would be glad to avoid.

If the code can be improved by doing something differently to the D7 version, that's great -- but let's make those changes in both versions; and let's not just change things unnecessarily? Sometimes things are the way they are for a reason, after all.

kmoll’s picture

while D8 code in general is all kinds of different to D7 code, I don't wish the essential behavior of this module to diverge between the two versions

I completely agree. Makes sense about returning a 200 rather than a 404. I had not thought of the case of the browser agent response if it had already received a 404.

As far as the code, I see your point with the way the variables are named and used. There are a few methods in D8 that we used as improvements, i.e. loading things from the config rather than using the defaults array, I am not sure that affects functionality and there should be no performance hits to calling the settings from config, but I see your point about code readability and comprehension and can update those sections to ensure that the essence of the code remains intact with the D7 version. Do you prefer its update in this patch, or should we create an issue to review the code and update things like that?

jweowu’s picture

If you could update the bits which are specific to this patch, that would be good.

Differences which are reflected throughout the D8 version of the module should be deferred to a later review, as presumably we'll either want to keep them all or change them all.

kmoll’s picture

Status: Needs review » Needs work
kmoll’s picture

@jweowu sounds good, I will take a quick look to ensure the changes specific to this patch are updated, then we can do a deeper review of the entire port.

kmoll’s picture

StatusFileSize
new17 KB
new3.73 KB

I've updated the responses to be 200 instead of 404, and updated the logic in conditionals to exactly match D7 version.

kmoll’s picture

Status: Needs work » Needs review
kmoll’s picture

@jweowu are you able to review the latest patch?

jweowu’s picture

(edit: I should have marked that as "no-test" for the test bot -- I forgot that I'd needed to apply the original patch from #49 to HEAD^ , so this all needs re-rolling....)

I've just looked at SeckitExportController.php vs http://cgit.drupalcode.org/seckit/tree/seckit.module?h=7.x-1.x#n307 and have updated the D8 code to better align with the D7 code, re-organising the sequence of checks, updating comments, and eliminating the last NotFoundHttpException(). This is from eye-balling the code only; I have not tested the changes.

It occurs to me that I don't understand why this controller/method is named "export". To me, that term does not seem at all relevant to the behaviour. Why was that name used? (I feel that either there's some standard D8 use for the term "export" that I'm unaware of, or else that it should be changed. Something like SeckitCspViolationReportController::processReport() perhaps? I'm even wondering whether this was a typo -- "export" in place of "report" ??)

Lastly, the following comment appears twice:

// An exception gets logged, if we are preventing for performance reasons
// we don't want this logged because it could cause a db write if dblog
// is enabled.

I find the phrasing/grammar a bit awkward and unclear, but I'm also not sure exactly what it's referring to in context. Which exception? What code raises it? The only explicit throw in that method (which I've now removed) was happening before either of these comments.

Status: Needs review » Needs work

The last submitted patch, 52: 2694029-support-flood-control-52.patch, failed testing.

chop’s picture

+++ b/seckit.module
@@ -45,3 +59,58 @@ function _seckit_form_alter_login_form(&$form, FormStateInterface &$form_state)
+    // flood_is_allowed() does not presently allow us to ignore the identifier,
+    // meaning we would need to log two flood events per CSP report in order to
+    // check both the global and per-user counts using the API function. This
+    // query enables us to do this while only registering one event per report.
+    // @see https://www.drupal.org/node/2472941
+    $connection = \Drupal::database();
+    $global_count = $connection->select('flood', 'f')
+      ->condition('event', 'seckit_csp_report')
+      ->condition('timestamp', REQUEST_TIME - $global_window, '>')
+      ->countQuery()
+      ->execute()
+      ->fetchField();

+++ b/src/Form/SecKitSettingsForm.php
@@ -69,9 +68,9 @@ class SecKitSettingsForm extends ConfigFormBase {
     // CSP report-only mode

Wouldn't registering two flood events would be safer and simpler than copying the Database Backed Flood service query into Seckit?

Couldn't you register a global and user flood event like this:

// Using identifier 'any' for global limit from any Client IP address.
$flood_service->register('seckit_csp_report', $global_window, 'any');
$flood_service->register('seckit_csp_report', $user_window);

Then, couldn't you check a global and user flood event like this:

// Using identifier 'any' for global limit from any Client IP address.
$global_allowed = flood_service->isAllowed('seckit_csp_report', $global_limit, $global_window, 'any');
$user_allowed = flood_service->isAllowed('seckit_csp_report', $user_limit, $user_window);

IMO this would be safer, as it doesn't need the Seckit module to assume / understand the schema and queries used by the Flood service.

chop’s picture

Priority: Normal » Major

Increasing priority.

For as long as this issue remains unresolved seckit with CSP on Drupal 8 represents a potential DDOS vector.

We have client sites where we've had to block the csp violation report URI at the edge WAF because misconfiguration of Seckit CSP rules (by the client) has lead to Database deadlock exceptions.

The core problem is that these POST requests bypass all cache layers used in a high availability architecture. They are passed through Cloudflare CDN, Varnish. A percentage of reports are also causing the HTTP 404 page, bypassing fast 404, because the browser didn't conform with the expected HTTP Request Content-Type headers.

We'll be applying this patch above as it currently stands and then testing some more. I've raised this with our team here and we'll try to get some resources focused on helping to progress with the fix.

jweowu’s picture

Wouldn't registering two flood events would be safer and simpler than copying the Database Backed Flood service query into Seckit?

The chosen solution isn't ideal, but neither is the alternative. I recommend that we keep things as they are. If the core enhancement is implemented then we can transition to that API. (Maybe you'd even be interested in implementing that API improvement?)

FYI my comments at the time to the security team were:

So flood_is_allowed() has an annoying deficiency in that one can't use it to test all events of a given name against a threshold value (i.e. irrespective of the user identifier).

If I register a single event per violation report, then I can perform the per-user flood check with flood_is_allowed(), and I can use a custom database query to perform the all-users (DDOS) flood check by querying those same events (effectively the same query that the API uses, but ignoring the identifiers).

If I don't use a custom query, then I would need to register a second event for each violation report, with a static identifier, so that I can also use flood_is_allowed() to test the global threshold.

Do you have any issues with using a custom query for this? I don't much like to be adding effectively-duplicate data into the database for no good reason.

I've logged a core issue for this: https://www.drupal.org/node/2472941

To which the response was:

As long as the security issue is fixed it's your decision. I agree with your analysis - basically you have to choose between putting too much data in the flood table or going around the API - neither is ideal so I'd say to go with whichever feels best to you.

chop’s picture

neither is ideal so I'd say to go with whichever feels best to you.

It's arguably better to use the API we have and maintain the separation of concerns, rather than creating a tight coupling between Seckit and the current Flood service.

That's all.

mxr576’s picture

What is missing to get this fixed?

jweowu’s picture

Primarily #2472941: Facilitate global (spanning all users) flood tests, which addresses the API deficiency which was under dispute above. I started work on that as a result of this, but stalled when I couldn't work out how to run the tests manually so that I could work out what I was doing wrong. (The testing framework seemed to be an absolute beast of a thing, and after trying and failing with about three separate approaches to running them, I set it aside, and never got back to it. I don't work with Drupal 8, so I have no familiarity with these things.)

So you could help with that issue.

chop’s picture

Linking the related core enhancement issue for Flood control API.

Agree with @jweowu that if we're to use Drupal core Flood Control API it needs to be extended to support global event logging without duplicating stored events using a static key.

It is a pity that #2472941: Facilitate global (spanning all users) flood tests hasn't had any real attention. I think the proposal is solid and you said the security team were at least receptive to it. We just really need to get that core issue tested and sorted so this can proceed.

geoffreyr made their first commit to this issue’s fork.

geoffreyr’s picture

We're actively looking at using the patch from #52 in production so we've created a MR for it. It also incorporates some minor fixes for D10 compatibility; there may be more adjustments to come. Will look at 2472941 when I have the chance.

geoffreyr’s picture

Rerolled for 2.x in MR 52.

geoffreyr’s picture

Revisiting this patch after a while on a 10.6 site. It's still got a reference to REQUEST_TIME in there which I'll have to remove.