Plan skip restoration leaves false-positive findings with stale reopened metadata
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 25/100
Direzione di ricerca
Start with the reproduction steps, which use only in-memory state: call upsert_issues in desloppify/engine/_state/merge_issues.py, then reconcile_plan_after_scan in desloppify/engine/_plan/scan_issue_reconcile.py, and compare the row's note, reopen_count, and resolution fields. The maintainers have not decided which side owns the fix, so confirm the contract with them before editing. Done means a regression test asserts the agreed terminal fields for a plan-skipped false positive.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Problem
A finding with a durable plan skip --false-positive disposition can be returned by the next scan, briefly reopened by scan merge, and then restored to false_positive during post-scan plan reconciliation. The terminal state can retain the scan's Reopened (×N) note, a higher reopen_count, and null resolved_at/resolution_attestation even though the final status is false_positive and the plan still contains the accepted skip evidence.
This makes the terminal state ambiguous: it looks both accepted and unresolved, and the reopen counter reports churn that was immediately superseded by the durable plan disposition.
Minimal in-memory reproduction
No project files or persisted state are required:
- Create one synthetic
test_coveragework item with statusfalse_positive, a priorresolved_at, and aresolution_attestation. - Add a matching plan entry under
plan["skipped"]with kindfalse_positive, noteaccepted, and attestationreviewed. - Pass the same finding through
engine._state.merge_issues.upsert_issues. - Pass the plan and state through
engine._plan.scan_issue_reconcile.reconcile_plan_after_scan.
Observed after upsert_issues:
status = open
reopen_count = 1
note = "Reopened (×1) — reappeared in scan (was false_positive)"
resolved_at = null
resolution_attestation = null
Observed after reconcile_plan_after_scan:
status = false_positive
reopen_count = 1
note = "Reopened (×1) — reappeared in scan (was false_positive)"
resolved_at = null
resolution_attestation = null
plan["skipped"][id]["kind"] = "false_positive"
plan["skipped"][id]["note"] = "accepted"
plan["skipped"][id]["attestation"] = "reviewed"
Code path
desloppify/engine/_state/merge_issues.py::upsert_issuesincrementsreopen_count, clears resolution metadata, and writes theReopenednote when a previously resolved finding is present in current detector output.desloppify/engine/_plan/scan_issue_reconcile.py::_sync_skipped_issue_statusesrestores an open skipped finding to the skip-kind status by assigningstatusonly.desloppify/app/commands/scan/workflow.pypersists state after scan merge and again after post-scan reporting, so the restored terminal status can be persisted.
Expected behavior / question
Please clarify the supported contract for a durable plan skip:
- If the plan skip is the canonical disposition, should scan merge avoid treating the accepted finding as a user-resolution reopen, or should reconciliation restore coherent state metadata from the plan skip?
- If the reopen event is intentionally retained as history, should it be represented separately so a final
false_positiverow does not carry an unresolved-looking note and null resolution metadata?
A regression test should assert the chosen terminal contract for status, reopen count, note, resolved_at, resolution_attestation, and plan skip evidence.
Related work
- PR836 preserves deliberate skip dispositions across scans and cleans stale queue/cluster references. This report concerns the state-row metadata left after status restoration.
- PR798 persists reconciled scan scores and history. This report concerns per-finding terminal metadata, not score persistence.
- Issue807 tracks conflicting scan scores in one invocation and is related to the pre/post-reconciliation visibility problem.
- Lingua principale
- Python
- Stelle
- 4.1k
- Fork
- 313
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di peteromallet/desloppify
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
peteromallet/desloppify#966 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
peteromallet/desloppify#965 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
peteromallet/desloppify#964 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
peteromallet/desloppify#950 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
peteromallet/desloppify#947 ·
Tutte le issue di peteromallet/desloppify
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100
SACGF/variantgrid#2791 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 1 giorno
-
bot-triaged oncall: cpu inductor
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
kubescape/cel-admission-library#141 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno