fix(tests): merge approved procedure suggestions instead of overwriting
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled

Approving a suggestion was replacing the template's whole procedure
field with just that submission's extracted text, silently dropping
whatever an earlier approved round had already added. Now it appends
only the genuinely new lines, so templates accumulate commands across
rounds instead of losing them.
This commit is contained in:
kitos
2026-07-14 16:25:24 +02:00
parent 4692a8b93e
commit 8fcd733d4a
2 changed files with 87 additions and 5 deletions
+43 -1
View File
@@ -151,7 +151,7 @@ def test_approving_a_suggestion_writes_it_into_the_template(
assert approve.json()["status"] == "approved"
reloaded = api("get", f"/api/v1/test-templates/{template['id']}", red_lead_headers)
assert reloaded.json()["attack_procedure"] == "whoami /priv"
assert reloaded.json()["attack_procedure"] == "Run a discovery command on the target.\nwhoami /priv"
listed = api("get", "/api/v1/procedure-suggestions", red_lead_headers)
assert listed.json() == []
@@ -180,6 +180,48 @@ def test_rejecting_a_suggestion_leaves_the_template_untouched(
assert reloaded.json()["attack_procedure"] == "Run a discovery command on the target."
def test_approving_a_later_suggestion_does_not_erase_an_earlier_approved_one(
client, db, api, test_from_template, template, red_tech_headers, red_lead_headers,
):
"""Two separate rounds, each contributing a different command, must
both survive in the template once their suggestions are approved —
approving round 2's suggestion must not wipe out what round 1 added."""
test_id = test_from_template
api("post", f"/api/v1/tests/{test_id}/start-execution", red_tech_headers)
api(
"patch", f"/api/v1/tests/{test_id}/red", red_tech_headers,
json={"procedure_text": "Ran discovery.\nwhoami /priv\nDone."},
)
_add_evidence(db, test_id, TeamSide.red)
api("post", f"/api/v1/tests/{test_id}/submit-red", red_tech_headers)
first_suggestion = api("get", "/api/v1/procedure-suggestions", red_lead_headers).json()[0]
api("post", f"/api/v1/procedure-suggestions/{first_suggestion['id']}/approve", red_lead_headers)
api(
"post", f"/api/v1/tests/{test_id}/review-red", red_lead_headers,
json={"decision": "reopen", "notes": "one more pass"},
)
api(
"patch", f"/api/v1/tests/{test_id}/red", red_tech_headers,
json={"procedure_text": "Ran a follow-up check.\nnltest /dsgetdc:corp\nDone."},
)
_add_evidence(db, test_id, TeamSide.red)
api("post", f"/api/v1/tests/{test_id}/submit-red", red_tech_headers)
second_suggestion = api("get", "/api/v1/procedure-suggestions", red_lead_headers).json()[0]
assert second_suggestion["suggested_text"] == "nltest /dsgetdc:corp"
approve_second = api(
"post", f"/api/v1/procedure-suggestions/{second_suggestion['id']}/approve", red_lead_headers,
)
assert approve_second.status_code == 200, approve_second.text
reloaded = api("get", f"/api/v1/test-templates/{template['id']}", red_lead_headers)
assert reloaded.json()["attack_procedure"] == (
"Run a discovery command on the target.\nwhoami /priv\nnltest /dsgetdc:corp"
)
def test_blue_lead_cannot_review_a_red_suggestion(
client, db, api, test_from_template, red_tech_headers, red_lead_headers, blue_lead_headers,
):