Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Scenario progress double-counts an attack result after its timestamp is bumped

Cerrado
#3,183 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

@ManoharPaturi ya está trabajando en esto.

Desde el 13/10/2026.

  • #3184 de @ManoharPaturi — abierto

Evaluación

Dificultad
3/5
Tiempo estimado
Medio día
Aptitud para principiantes
25/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
python
Área
backend

Línea de trabajo

Start in ScenarioProgressReadModel._hydrate_new_deltas_async, where each page is appended with entry.deltas.extend(page) and nothing is deduplicated by attack_result_id. Then read get_scenario_attack_result_deltas_async to see how the keyset cursor over (timestamp, id) re-emits bumped rows. A re-emitted delta should update the cached copy of that attempt, not add a second one. Linked PR #3184 is already open against this, so check it before starting.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Describe the bug

The scenario progress read model double-counts an attack result whose row timestamp is later bumped.

get_scenario_attack_result_deltas_async pages rows in ascending keyset order over (timestamp, id), so any row whose timestamp moves forward compares greater than the stored cursor and is emitted again. That happens today: AttackService.update_attack_async and remove_human_score_async write "timestamp": datetime.now(UTC) on every edit, and promote_attack_conversation rewrites timestamps too.

ScenarioProgressReadModel._hydrate_new_deltas_async handles each page with entry.deltas.extend(page) and no dedup by attack_result_id, so the re-emitted row is appended as a second copy of the same attempt. The snapshot's results then contains the same attack twice, which inflates per-unit attempt counts and retry pressure for the lifetime of the cache entry.

Steps/Code to Reproduce
  1. Poll GET /scenarios/{id}/progress once so the read model caches the run's deltas and cursor.
  2. Edit any attack result that belongs to that scenario (for example PUT /attacks/{attack_result_id}), which bumps the row's timestamp.
  3. Poll the scenario progress endpoint again.

The storage feed re-emits the edited row (keyset timestamp > cursor), and the read model appends it again.

Minimal reproduction against the read model:

memory.get_scenario_attack_result_deltas_async = AsyncMock(
    side_effect=[([delta], False), ([bumped_delta_with_same_id], False)]
)
read_model = ScenarioProgressReadModel(memory=memory)
first = await read_model.get_snapshot_async(scenario_result_id="run", ...)
second = await read_model.get_snapshot_async(scenario_result_id="run", ...)
# second.results holds the same attack_result_id twice
Expected Results

A re-emitted delta updates the already cached copy of that attempt instead of adding a second one.

Actual Results

The same attack result id appears twice in the snapshot results, inflating attempt counts.

Screenshots

N/A

Versions

OS: macOS
Python version: 3.14
PyRIT version: installed from main (66c41fa)

Lenguaje dominante
Python
Estrellas
4.6k
Forks
944
Merge medio
2 d 18 h
PR fusionados (30 d)
358

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

  • Sin Dockerfile ni archivo de Docker Compose
  • Tiene una plantilla de pull request
  • Sin guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de microsoft/PyRIT

Todos los issues de microsoft/PyRIT

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.