Make security scan stale_after duration a configurable instance setting

Summary

The stale_after duration that controls when security scans and their associated findings partitions are purged is currently hardcoded as a class method in Security::Scan:

# ee/app/models/security/scan.rb:87-93
def self.stale_after
  if Gitlab.com?
    30.days
  else
    90.days
  end
end

This should be configurable by instance administrators to allow organizations to tune retention based on storage constraints or operational needs.

Current Behavior

  • GitLab.com: Scans are considered stale after 30 days
  • Self-managed: Scans are considered stale after 90 days
  • These values are not configurable

The stale_after value is used to:

  1. Identify stale scans via the stale scope
  2. Determine when scan findings can be purged (findings_can_be_purged?)
  3. Decide when to create new sliding list partitions for security_findings (oldest_record_stale?)

Note: This data is ephemeral/intermediary storage used during security scan processing before being transformed into more persistent data structures. There is no compliance interest in extended retention.

Proposal

Add a new configurable setting security_scan_stale_after_days (or similar) that allows administrators to configure this duration.

Implementation approach

Add to the existing ApplicationSetting model, either as:

  1. Option A: Direct column - security_scan_stale_after_days integer column
  2. Option B: JSONB column - Add to a new or existing JSONB settings group (e.g., security_settings)

The JSONB approach is the preferred modern pattern per recent GitLab conventions.

Requirements

  1. Default values: Maintain current defaults

    • GitLab.com: 30 days
    • Self-managed: 90 days
  2. Minimum duration: Enforce a minimum of 7 days

    • Shorter durations would cause excessive redundant rescanning as findings would be purged too quickly
    • This protects users from accidentally degrading their security scanning experience
  3. Maximum duration: Enforce a maximum of 90 days

    • This data is ephemeral and serves no purpose beyond processing
    • Holding findings longer than 3 months provides no benefit and wastes storage

Admin UI Location

The setting should be added to the Admin > Settings > Security and Compliance page:

  • Page: ee/app/views/admin/application_settings/security_and_compliance.html.haml
  • Create a new "Security Scans" section with a dedicated partial (e.g., _security_scans.html.haml)

This should be a separate section from "Security policies" since this setting controls scan data retention rather than policy configuration. However, they are notionally related as security policies are informed by security finding information that gets ingested through these scans.

Files to modify

File Changes
db/migrate/ Add migration for new setting
app/models/application_setting.rb Add accessor and validations
app/models/application_setting_implementation.rb Add default values
ee/app/models/security/scan.rb Update stale_after to read from settings
ee/app/helpers/ee/application_settings_helper.rb Add to visible_attributes and possible_licensed_attributes
ee/app/controllers/ee/admin/application_settings_controller.rb Add to permitted attributes
ee/app/views/admin/application_settings/_security_scans.html.haml New partial with form field for the setting
ee/app/views/admin/application_settings/security_and_compliance.html.haml Include the new _security_scans partial
lib/api/settings.rb Add API parameter
app/validators/json_schemas/ Add JSON schema if using JSONB approach

Example implementation

# application_setting.rb
validates :security_scan_stale_after_days,
  numericality: {
    only_integer: true,
    greater_than_or_equal_to: 7,
    less_than_or_equal_to: 90,
    message: N_('must be between 7 and 90 days')
  }

# application_setting_implementation.rb
def security_scan_stale_after_days
  super || (Gitlab.com? ? 30 : 90)
end

# ee/app/models/security/scan.rb
def self.stale_after
  Gitlab::CurrentSettings.security_scan_stale_after_days.days
end

Benefits

  • Storage management: Administrators can reduce retention for storage-constrained instances
  • Operational tuning: Self-managed instances with frequent scanning can reduce retention to free resources
Edited by 🤖 GitLab Bot 🤖