Add a variable table to each scan trigger card

What does this MR do and why?

Add a variable table to each scan trigger card

Show the analyzer settings a trigger passes inside its own card in the
scan profile details modal, so each trigger lists every variable it
sets rather than only the ones that differ across triggers.
ScanTriggersDetail renders a Variable and Value table per trigger, and
classifyConfigurationVariables returns those rows alongside the
profile-level ones it already built.

Changelog: added
EE: true

References

Screenshots or screen recordings

Before After
Before, at the parent branch tip b784bfa2: trigger cards with no variable table profile with variables
After: the same profile, each configurable trigger showing a Variable and Value table
profile without variables (no change)
scan-trigger-cards-default-profile-20260922

How to set up and validate locally

  1. git checkout 624190-add-variable-tables-to-trigger-cards
    echo "Feature.enable(:custom_scan_profiles_ui, Group.find(ID))" | gdk rails c
  2. have a GitLab Ultimate licence
  3. go to a group => Secure => Security configuration
  4. open a scan profile's details
  5. there is no user interface yet for setting different values per trigger, so set up a profile with variable values that differ by trigger by calling the securityScanProfileCreate mutation directly:
expand for mutations
mutation {
  securityScanProfileCreate(
    input: {
      namespaceId: "gid://gitlab/Group/24"
      scanType: SECRET_DETECTION
      name: "All settings at profile level"
      description: "Every setting shared across both configurable triggers"
      stripDefaults: false
      triggers: [
        {
          triggerType: MERGE_REQUEST_PIPELINE
          configuration: {
            secretDetection: {
              secureAnalyzersPrefix: "registry.example.com/security-products"
              imageSuffix: FIPS
              historicScan: true
              logOptions: "--all"
              excludedPaths: ["spec/fixtures/**", "tmp/**"]
              rulesetGitReference: "refs/tags/v1.2.0"
            }
          }
        }
        {
          triggerType: DEFAULT_BRANCH_PIPELINE
          configuration: {
            secretDetection: {
              secureAnalyzersPrefix: "registry.example.com/security-products"
              imageSuffix: FIPS
              historicScan: true
              logOptions: "--all"
              excludedPaths: ["spec/fixtures/**", "tmp/**"]
              rulesetGitReference: "refs/tags/v1.2.0"
            }
          }
        }
        { triggerType: GIT_PUSH_EVENT }
      ]
    }
  ) {
    scanProfile {
      id
      name
      triggerSettings {
        triggerType
        configuration {
          ... on SecretDetectionConfiguration {
            secureAnalyzersPrefix
            imageSuffix
            historicScan
            logOptions
            excludedPaths
            rulesetGitReference
          }
        }
      }
    }
    errors
  }
}
mutation {
  securityScanProfileCreate(
    input: {
      namespaceId: "gid://gitlab/Group/24"
      scanType: SECRET_DETECTION
      name: "Mixed profile and trigger settings"
      description: "Three settings shared across triggers, two that differ"
      stripDefaults: false
      triggers: [
        {
          triggerType: MERGE_REQUEST_PIPELINE
          configuration: {
            secretDetection: {
              secureAnalyzersPrefix: "registry.example.com/security-products"
              imageSuffix: FIPS
              excludedPaths: ["spec/fixtures/**", "tmp/**"]
              historicScan: false
              logOptions: "--all"
            }
          }
        }
        {
          triggerType: DEFAULT_BRANCH_PIPELINE
          configuration: {
            secretDetection: {
              secureAnalyzersPrefix: "registry.example.com/security-products"
              imageSuffix: FIPS
              excludedPaths: ["spec/fixtures/**", "tmp/**"]
              historicScan: true
            }
          }
        }
        { triggerType: GIT_PUSH_EVENT }
      ]
    }
  ) {
    scanProfile {
      id
      name
      gitlabRecommended
      triggerSettings {
        triggerType
        configuration {
          ... on SecretDetectionConfiguration {
            secureAnalyzersPrefix
            imageSuffix
            excludedPaths
            historicScan
            logOptions
            rulesetGitReference
          }
        }
      }
    }
    errors
  }
}
mutation {
  securityScanProfileCreate(
    input: {
      namespaceId: "gid://gitlab/Group/<root_group_id>"
      scanType: SECRET_DETECTION
      name: "XSS test <img src=x onerror=alert('profile-name')>"
      description: "\"><script>alert('description')</script> and a [markdown link](javascript:alert('md'))\nsecond line"
      stripDefaults: false
      triggers: [
        {
          triggerType: MERGE_REQUEST_PIPELINE
          configuration: {
            secretDetection: {
              historicScan: true
              imageSuffix: FIPS
              secureAnalyzersPrefix: "<img src=x onerror=alert('secureAnalyzersPrefix')>"
              excludedPaths: [
                "<script>alert('excludedPaths')</script>"
                "\"><img src=x onerror=alert('attr-breakout')>"
                "{{ constructor.constructor('alert(1)')() }}"
                "\\u003cimg src=x onerror=alert('double-decode')\\u003e"
                "<a href=\"javascript:alert('href')\">spec/**</a>"
              ]
              logOptions: "--all <svg onload=alert('logOptions-merge-request')>"
              rulesetGitReference: "javascript:alert('rulesetGitReference')"
            }
          }
        }
        {
          triggerType: DEFAULT_BRANCH_PIPELINE
          configuration: {
            secretDetection: {
              historicScan: true
              imageSuffix: FIPS
              secureAnalyzersPrefix: "<img src=x onerror=alert('secureAnalyzersPrefix')>"
              excludedPaths: [
                "<script>alert('excludedPaths')</script>"
                "\"><img src=x onerror=alert('attr-breakout')>"
                "{{ constructor.constructor('alert(1)')() }}"
                "\\u003cimg src=x onerror=alert('double-decode')\\u003e"
                "<a href=\"javascript:alert('href')\">spec/**</a>"
              ]
              logOptions: "--since=2020-01-01 <iframe srcdoc=\"<script>alert(1)</script>\"></iframe>"
              rulesetGitReference: "<style>body{display:none}</style>refs/tags/v1"
            }
          }
        }
        { triggerType: GIT_PUSH_EVENT }
      ]
    }
  ) {
    scanProfile {
      id
      name
    }
    errors
  }
}
  1. find the Scan triggers section and expand a trigger card
  2. check that a trigger which sets analyzer settings shows a table:
    • headed Variable and Value
    • one row for every setting that trigger sets, not only the ones that differ across triggers
  3. check that a trigger which sets nothing shows no table:
    • the card still renders, with its other details intact
    • secret push protection in secret detection is one such trigger

to run tests

yarn jest ee/spec/frontend/security_configuration/components/scan_profiles
Edited by Miranda Fluharty

Merge request reports

Loading
Loading