mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-16 20:02:20 +02:00
fix(agent): taint stored document tool results
This commit is contained in:
@@ -132,7 +132,6 @@ _register(
|
|||||||
"create_session",
|
"create_session",
|
||||||
"draft_email",
|
"draft_email",
|
||||||
"draft_email_reply",
|
"draft_email_reply",
|
||||||
"edit_document",
|
|
||||||
"manage_calendar",
|
"manage_calendar",
|
||||||
"manage_contact",
|
"manage_contact",
|
||||||
"manage_documents",
|
"manage_documents",
|
||||||
@@ -144,10 +143,17 @@ _register(
|
|||||||
"manage_tasks",
|
"manage_tasks",
|
||||||
"suggest_document",
|
"suggest_document",
|
||||||
"todowrite",
|
"todowrite",
|
||||||
"update_document",
|
|
||||||
},
|
},
|
||||||
ToolEffect.WRITE_PRIVATE,
|
ToolEffect.WRITE_PRIVATE,
|
||||||
)
|
)
|
||||||
|
_register(
|
||||||
|
{"edit_document", "update_document"},
|
||||||
|
ToolEffect.WRITE_PRIVATE,
|
||||||
|
# These tools can echo stored document content that was not present in
|
||||||
|
# their arguments. edit_document returns the complete edited document;
|
||||||
|
# update_document also preserves stored email headers/thread history.
|
||||||
|
result_integrity=ResultIntegrity.EXTERNAL_UNTRUSTED,
|
||||||
|
)
|
||||||
_register(
|
_register(
|
||||||
{"pipeline"},
|
{"pipeline"},
|
||||||
ToolEffect.NETWORK_EGRESS,
|
ToolEffect.NETWORK_EGRESS,
|
||||||
|
|||||||
@@ -341,6 +341,22 @@ def test_cross_model_results_taint_before_later_host_actions(tool_name):
|
|||||||
assert context.decision_for("bash").allowed is False
|
assert context.decision_for("bash").allowed is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("tool_name", ["edit_document", "update_document"])
|
||||||
|
def test_stored_document_results_taint_before_later_host_actions(tool_name):
|
||||||
|
context = ToolRunSecurityContext()
|
||||||
|
|
||||||
|
capabilities = capabilities_for_tool(tool_name)
|
||||||
|
assert capabilities.result_integrity is ResultIntegrity.EXTERNAL_UNTRUSTED
|
||||||
|
context.observe_tool_result(
|
||||||
|
tool_name,
|
||||||
|
{"content": "stored attacker-controlled content", "exit_code": 0},
|
||||||
|
"model-proposed replacement",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert context.external_untrusted_context_seen is True
|
||||||
|
assert context.decision_for("bash").allowed is False
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"tool_name,content",
|
"tool_name,content",
|
||||||
[
|
[
|
||||||
@@ -403,6 +419,7 @@ def test_ambiguous_private_manager_action_fails_high():
|
|||||||
("web_search", {"output": "external", "exit_code": 0}, True),
|
("web_search", {"output": "external", "exit_code": 0}, True),
|
||||||
("web_search", {"error": "offline", "exit_code": 1}, False),
|
("web_search", {"error": "offline", "exit_code": 1}, False),
|
||||||
("list_served_models", {"output": "local status", "exit_code": 0}, False),
|
("list_served_models", {"output": "local status", "exit_code": 0}, False),
|
||||||
|
("edit_document", {"content": "stored content", "exit_code": 0}, True),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_result_folding_is_transport_and_status_consistent(
|
def test_result_folding_is_transport_and_status_consistent(
|
||||||
|
|||||||
Reference in New Issue
Block a user