Anti-flipping safeguard for vulnerability management policies
Summary
When a vulnerability appears in scan results inconsistently, it can continually transition between detected and resolved states. This can cause these problems:
- Unclear vulnerability status
- Continual growth of
notesandvulnerability_state_transitionsrecords, which will eventually cause performance and storage problems
We should implement "anti-flipping" safeguards to mitigate this problem. After a vulnerability has automatically transitioned between detected and resolved a certain number of times, we should flag that vulnerability as problematic (when I worked at WhiteHat Security, such vulnerabilities were called "flappers"). If a vulnerability has been flagged as problematic then it should be ignored by any further automatic status changes, and should be marked by an indicator in the UI. This will allow someone to manually review, set the correct status, and correct the projects pipeline configuration if necessary.
Implementation
Phase 1
- Create a new table:
vulnerability_flip_guards - Add new model:
Vulnerabilities::FlipGuard - Add specs for all the above
Phase 2
- Introduce a new feature flag:
vulnerability_anti_flip_safeguardwhich is(default: disabled) - Add
has_one :flip_guardassociation to theVulnerabilitymodel - Update
AutoResolveServiceto check and track guards - Update
MarkResolvedAsDetectedto check and track guards - Add logging for blocked transitions
- Add specs for all the above
Guard logic details
- The guard should trigger after 5 automatic transitions within a 30-day window.
- Once a vulnerability hits the threshold, we will set the state to
needs_triage - All the further automatic transitions should be blocked, until the vulnerability has been manually reviewed.
Schema proposal:
CREATE TABLE vulnerability_flip_guards (
id bigserial PRIMARY KEY,
vulnerability_id bigint NOT NULL,
project_id bigint NOT NULL,
automated_transition_count smallint DEFAULT 1,
first_automatic_transition_at timestamp with time zone NOT NULL, # first time the vulnerability's state was changed
last_automatic_transition_at timestamp with time zone NOT NULL, # most recent state change
is_guarded boolean DEFAULT false NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);