Skip to content

Commit efdc08e

Browse files
authored
Fix LLMApprovalMixin to enforce allow_modifications in execute_complete (#64244)
* Fix LLMApprovalMixin to enforce allow_modifications in execute_complete
1 parent 4394583 commit efdc08e

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

providers/common/ai/src/airflow/providers/common/ai/mixins/approval.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,10 @@ def execute_complete(self, context: Context, generated_output: str, event: dict[
168168
output = generated_output
169169
params_input: dict[str, Any] = event.get("params_input") or {}
170170

171-
# If the reviewer provided modified output, return their version
172-
if params_input:
171+
# Only accept modified output when the operator explicitly allows modifications.
172+
# Without this guard a reviewer could craft a request with params_input even
173+
# when allow_modifications=False, bypassing the read-only approval flow.
174+
if getattr(self, "allow_modifications", False) and params_input:
173175
modified = params_input.get("output")
174176
if modified is not None and modified != generated_output:
175177
log.info("output=%s modified by the reviewer=%s ", modified, responded_by_user)

providers/common/ai/tests/unit/common/ai/mixins/test_approval.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,18 @@ def test_approved_no_modifications_ignores_params_input(self, approval_op):
295295

296296
assert result == "original"
297297

298+
def test_approved_no_modifications_rejects_tampered_params_input(self, approval_op):
299+
"""When allow_modifications=False, tampered params_input with output must be ignored."""
300+
event = {
301+
"chosen_options": ["Approve"],
302+
"responded_by_user": "reviewer",
303+
"params_input": {"output": "tampered output"},
304+
}
305+
306+
result = approval_op.execute_complete({}, generated_output="original", event=event)
307+
308+
assert result == "original"
309+
298310
def test_event_missing_responded_by_user(self, approval_op):
299311
event = {"chosen_options": ["Approve"]}
300312

0 commit comments

Comments
 (0)