diff --git a/datasets/agentdataflow_toolexchange_traces/croissant.json b/datasets/agentdataflow_toolexchange_traces/croissant.json index 3586886..3599a60 100644 --- a/datasets/agentdataflow_toolexchange_traces/croissant.json +++ b/datasets/agentdataflow_toolexchange_traces/croissant.json @@ -51,7 +51,7 @@ "description": "Agent Data Flow and Tool Exchange Traces. Sanitized traces of agentic AI tool calls, plugin data exchanges and delegation chains: typed spans, data classes and sensitivity, findings mapped to DSGAI risks, and a provenance tier with cited evidence.", "conformsTo": "http://mlcommons.org/croissant/1.1", "citeAs": "OWASP GenAI Data Security Initiative. Agent Data Flow and Tool Exchange Traces (version 1.0.0). OWASP GenAI Security Project. https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/tree/main/datasets/agentdataflow_toolexchange_traces", - "dateModified": "2026-09-15", + "dateModified": "2026-10-12", "datePublished": "2026-08-07", "license": "https://creativecommons.org/licenses/by-sa/4.0/", "rai:dataBiases": "Centred on MCP-based tool ecosystems, where most public agent data-flow documentation exists.", @@ -80,7 +80,7 @@ "name": "index.csv", "contentUrl": "index.csv", "encodingFormat": "text/csv", - "sha256": "e6f02ff2e11f9b3bd6381eb3d4900ffafc52a82fa2f4598f8092e75bbc97297b" + "sha256": "5daed500bacc2858b364a63a10930e28d3250e59007f40a273c775c57b1cc706" }, { "@type": "cr:FileObject", diff --git a/datasets/agentdataflow_toolexchange_traces/entries/DSGAI-TRACE-derived-summary-memory-outlives-column-entitlement.json b/datasets/agentdataflow_toolexchange_traces/entries/DSGAI-TRACE-derived-summary-memory-outlives-column-entitlement.json new file mode 100644 index 0000000..4647c93 --- /dev/null +++ b/datasets/agentdataflow_toolexchange_traces/entries/DSGAI-TRACE-derived-summary-memory-outlives-column-entitlement.json @@ -0,0 +1,301 @@ +{ + "$schema": "../schema.json", + "trace_id": "DSGAI-TRACE-derived-summary-memory-outlives-column-entitlement", + "title": "Summary derived from a restricted column is written to shared agent memory and served to a user who lacks that column entitlement", + "description": "An analytics agent answers an entitled user's question by querying a warehouse through a governed tool that enforces column-level access, then writes its natural-language summary to a long-term memory store shared across a workspace. The memory item carries a namespace, a key and a value, but nothing about which source columns it was derived from or who was entitled to read them. Days later a second user, who is not entitled to the restricted column, asks a related question; the store returns the summary by semantic similarity, the only check applied is workspace membership on the namespace, and the derived figures reach that user. Every individual access check passes; the entitlement was enforced on the source read and never carried onto the derived artifact.", + "category": "memory_read_write", + "disposition": "unintentional_failure", + + "dsgai_mapping": ["DSGAI01", "DSGAI11", "DSGAI07", "DSGAI15", "DSGAI18"], + "owasp_llm_top10_mapping": ["LLM02:2025", "LLM02:2026"], + "owasp_agentic_top10_mapping": ["ASI03:2026"], + + "agent": { + "framework": "custom", + "tool_protocol": "mcp", + "topology": "single analytics agent + governed warehouse query tool + workspace-shared long-term memory store", + "autonomy": "fully_autonomous" + }, + + "provenance": { + "tier": "derived_from_public_documentation", + "collection_method": "Hand-constructed around two documented preconditions: a widely used agent memory store whose items carry only namespace, key, value and timestamps, with namespaces defined by the application; and a long-standing database convention in which a derived relation is, by default, authorized independently of the reader's rights on the base data. The agent, warehouse, columns, users, figures and offsets are all synthetic.", + "evidence": [ + { + "type": "url", + "citation": "https://docs.langchain.com/oss/python/langgraph/stores", + "locator": "Basic usage (Item attributes); Namespace design; Semantic search", + "supports": "A stored memory Item is described by value, key, namespace, created_at and updated_at; namespaces are application-defined tuples of strings (the documented example is a user id); and retrieval supports semantic search by meaning. The documented item model has no field for the source data a memory was derived from or the entitlements that applied to it, so any such restriction has to be carried by the application or it is lost at write time." + }, + { + "type": "url", + "citation": "https://www.postgresql.org/docs/current/sql-createview.html", + "locator": "Notes, paragraphs on base-relation access and security_invoker", + "supports": "'By default, access to the underlying base relations referenced in the view is determined by the permissions of the view owner', with invoker-side checking available only as an opt-in (security_invoker). This is the established precedent that a derived artifact is not automatically bound to the reader's rights on its sources; this trace models the same gap in a store that has no invoker-side option at all." + } + ] + }, + + "sanitization": { + "attestation": true, + "techniques": ["not_applicable_fully_synthetic", "name_generalization", "shape_only_payloads"], + "notes": "Fully synthetic. No system, organization, schema or figure here was taken from a real deployment; column, team and user identifiers are invented." + }, + + "spans": [ + { + "span_id": "s1", + "parent_span_id": null, + "t_offset_ms": 0, + "actor": "user", + "actor_id": "user://analyst-a", + "operation": "model.prompt", + "summary": "User A, entitled to the restricted compensation column, asks for average compensation by team for one small organization.", + "payload": { + "prompt": "", + "workspace": "workspace://org-planning", + "user_entitlements": ["hr.compensation:read", "org.headcount:read"] + }, + "data_classes": ["user_prompt"], + "sensitivity": "low" + }, + { + "span_id": "s2", + "parent_span_id": "s1", + "t_offset_ms": 1200, + "actor": "agent", + "actor_id": "agent://analytics-assistant", + "operation": "tool.call", + "summary": "Agent calls the governed warehouse tool on behalf of user A, passing A's identity for query-time authorization.", + "payload": { + "tool": "tool://warehouse-gateway/query_metric", + "metric": "avg_compensation", + "group_by": ["team"], + "filter": "", + "on_behalf_of": "user://analyst-a" + }, + "data_classes": ["user_prompt"], + "sensitivity": "low" + }, + { + "span_id": "s3", + "parent_span_id": "s2", + "t_offset_ms": 1350, + "actor": "policy_engine", + "actor_id": "policy://warehouse-column-acl", + "operation": "policy.decision", + "summary": "Column-level check passes for user A: the request touches the restricted column and A holds the entitlement.", + "payload": { + "subject": "user://analyst-a", + "columns_touched": ["employees.compensation", "employees.team_id"], + "restricted_columns": ["employees.compensation"], + "decision": "allow" + }, + "data_classes": ["none"], + "sensitivity": "none" + }, + { + "span_id": "s4", + "parent_span_id": "s2", + "t_offset_ms": 2900, + "actor": "tool", + "actor_id": "tool://warehouse-gateway/query_metric", + "operation": "tool.result", + "summary": "Tool returns per-team averages; three of the teams have three or fewer members.", + "payload": { + "rows": "", + "columns": ["team", "avg_compensation", "headcount"], + "min_group_size": 2, + "source_lineage_returned": ["employees.compensation"] + }, + "data_classes": ["tool_output", "financial", "pii"], + "sensitivity": "high" + }, + { + "span_id": "s5", + "parent_span_id": "s4", + "t_offset_ms": 4100, + "actor": "model", + "actor_id": "model://primary", + "operation": "model.completion", + "summary": "Model writes a narrative summary that restates the per-team averages, including the small teams, and answers user A.", + "payload": { + "completion": "", + "contains_figures_from": ["employees.compensation"] + }, + "data_classes": ["financial", "pii"], + "sensitivity": "high" + }, + { + "span_id": "s6", + "parent_span_id": "s5", + "t_offset_ms": 4300, + "actor": "agent", + "actor_id": "agent://analytics-assistant", + "operation": "memory.write", + "summary": "Agent saves the summary as a reusable insight in the workspace-shared namespace. The item records namespace, key and value only; the source lineage the tool returned in s4 is dropped.", + "payload": { + "store": "memory://long-term", + "namespace": ["org-planning", "insights"], + "key": "", + "value": { "text": "", "topic": "team budgets" }, + "derived_from_columns": null, + "required_entitlements": null, + "embedding_indexed": true + }, + "data_classes": ["memory_state", "financial", "pii"], + "sensitivity": "high", + "finding": { + "dsgai_id": "DSGAI07", + "note": "Lineage is available at write time (s4 returned it) and is discarded. Once the derived value is stored without its source columns, no later reader-side check can recover which entitlement it should require.", + "severity": "High" + } + }, + { + "span_id": "s7", + "parent_span_id": null, + "t_offset_ms": 345600000, + "actor": "user", + "actor_id": "user://manager-b", + "operation": "model.prompt", + "summary": "Four days later, user B, a workspace member without the compensation entitlement, asks why one team's budget is over plan.", + "payload": { + "prompt": "", + "workspace": "workspace://org-planning", + "user_entitlements": ["org.headcount:read", "finance.budget:read"] + }, + "data_classes": ["user_prompt"], + "sensitivity": "low" + }, + { + "span_id": "s8", + "parent_span_id": "s7", + "t_offset_ms": 345600900, + "actor": "policy_engine", + "actor_id": "policy://memory-namespace-acl", + "operation": "policy.decision", + "summary": "Memory access is checked against the namespace only: user B is a workspace member, so reads from the shared insights namespace are allowed.", + "payload": { + "subject": "user://manager-b", + "namespace": ["org-planning", "insights"], + "check": "workspace_membership", + "source_entitlement_checked": false, + "decision": "allow" + }, + "data_classes": ["none"], + "sensitivity": "none", + "finding": { + "dsgai_id": "DSGAI11", + "note": "The authorization question asked here (may this user read this namespace?) is not the one that matters (may this user read data derived from employees.compensation?). The namespace boundary is a tenancy boundary, not an entitlement boundary.", + "severity": "High" + } + }, + { + "span_id": "s9", + "parent_span_id": "s8", + "t_offset_ms": 345601300, + "actor": "memory_store", + "actor_id": "memory://long-term", + "operation": "memory.read", + "summary": "Semantic search on 'team budget' returns the item written in s6 as the top match.", + "payload": { + "query": "", + "namespace_prefix": ["org-planning"], + "results": 1, + "top_score": "", + "item_written_by_span": "s6" + }, + "data_classes": ["memory_state", "financial", "pii"], + "sensitivity": "high" + }, + { + "span_id": "s10", + "parent_span_id": "s9", + "t_offset_ms": 345601400, + "actor": "orchestrator", + "actor_id": "orchestrator://analytics-assistant", + "operation": "context.append", + "summary": "The retrieved summary is appended to user B's context as trusted prior knowledge.", + "payload": { + "appended_bytes": "", + "presented_as": "workspace insight" + }, + "data_classes": ["memory_state", "financial", "pii"], + "sensitivity": "high", + "finding": { + "dsgai_id": "DSGAI15", + "note": "Context assembly treats memory as pre-authorized. Data that would have been denied at the warehouse (s3 would deny B) enters B's context window by a path that never reaches that check.", + "severity": "High" + } + }, + { + "span_id": "s11", + "parent_span_id": "s10", + "t_offset_ms": 345603800, + "actor": "model", + "actor_id": "model://primary", + "operation": "egress", + "summary": "The answer to user B cites the stored per-team compensation averages, including teams of two and three people.", + "payload": { + "completion": "", + "recipient": "user://manager-b", + "contains_figures_from": ["employees.compensation"], + "smallest_group_disclosed": 2 + }, + "data_classes": ["financial", "pii"], + "sensitivity": "high", + "finding": { + "dsgai_id": "DSGAI01", + "note": "Restricted data reaches a user who would be denied a direct query for it. Because two of the averaged groups are tiny, the aggregate is close to individual-level disclosure.", + "severity": "High" + } + }, + { + "span_id": "s12", + "parent_span_id": "s11", + "t_offset_ms": 345603900, + "actor": "orchestrator", + "actor_id": "orchestrator://analytics-assistant", + "operation": "context.append", + "summary": "Run completes as a success; audit shows one allowed memory read and no warehouse access by user B.", + "payload": { + "audit_warehouse_queries_by_subject": 0, + "audit_memory_reads_by_subject": 1, + "alerts": 0 + }, + "data_classes": ["telemetry"], + "sensitivity": "low", + "finding": { + "dsgai_id": "DSGAI18", + "note": "Source-system audit shows user B never touched the restricted column, so the disclosure is invisible to the control that governs it. Small-group aggregates also let B infer individual values.", + "severity": "Medium" + } + } + ], + + "security_observations": [ + "Column-level access control enforced only at the source read does not constrain what an agent later does with values derived from that read.", + "A memory item that records namespace, key and value but not its source columns cannot be authorized against the entitlements of the data it was derived from.", + "Namespace or workspace membership is a tenancy check; in this trace it is the only check between a derived restricted value and a non-entitled reader.", + "Every guard passes: the warehouse correctly allows user A, the memory store correctly allows user B into the namespace, and the source audit correctly shows no access by B. The failure exists only across the derivation step.", + "Semantic retrieval makes the exposure unpredictable: the derived item is returned for a question that does not mention the restricted attribute." + ], + + "mitigations": [ + "Propagate source lineage onto every memory write: record the set of source columns (or their classification labels) a stored value was derived from, using lineage the data tool already returns.", + "Authorize memory reads against the derived item's required entitlements, computed from its lineage, in addition to namespace membership; deny or redact when the reader lacks any source entitlement.", + "Default to user-scoped memory for anything derived from restricted sources, and require an explicit, logged declassification step before such an item can be written to a shared namespace.", + "Apply minimum group-size suppression to aggregates before they are persisted, not only before they are first displayed.", + "Log memory-served disclosures against the source columns' audit trail, so a read of a derived item is visible to the control that governs the underlying data." + ], + + "contributor": { + "name": "Venkata Sangaraju" + }, + + "date_added": "2026-10-12", + + "tags": ["agent-memory", "long-term-memory", "derived-data", "column-level-access-control", "data-lineage", "entitlement-propagation", "shared-namespace", "semantic-retrieval", "small-group-aggregate"], + + "notes": "Scope: models the non-adversarial path, where no one intends the disclosure. An adversarial variant (a user who deliberately phrases questions to pull high-sensitivity items from a shared namespace) belongs in a separate entry. The trace does not claim that any specific product ships this configuration; the cited store documentation establishes only that its item model carries no lineage or entitlement fields, so a shared namespace with namespace-only checks is a reachable configuration unless the application adds them." +} diff --git a/datasets/agentdataflow_toolexchange_traces/index.csv b/datasets/agentdataflow_toolexchange_traces/index.csv index 89f3f51..a4fb1c4 100644 --- a/datasets/agentdataflow_toolexchange_traces/index.csv +++ b/datasets/agentdataflow_toolexchange_traces/index.csv @@ -1,4 +1,5 @@ trace_id,title,category,disposition,provenance_tier,primary_dsgai,dsgai_mapping,owasp_llm_top10_mapping,agent_framework,tool_protocol,span_count,finding_count,max_sensitivity,data_classes,evidence_count,primary_evidence,date_added,tags +DSGAI-TRACE-derived-summary-memory-outlives-column-entitlement,Summary derived from a restricted column is written to shared agent memory and served to a user who lacks that column entitlement,memory_read_write,unintentional_failure,derived_from_public_documentation,DSGAI01,DSGAI01|DSGAI11|DSGAI07|DSGAI15|DSGAI18,LLM02:2025|LLM02:2026,custom,mcp,12,5,high,financial|memory_state|none|pii|telemetry|tool_output|user_prompt,2,https://docs.langchain.com/oss/python/langgraph/stores,2026-10-12,agent-memory|long-term-memory|derived-data|column-level-access-control|data-lineage|entitlement-propagation|shared-namespace|semantic-retrieval|small-group-aggregate DSGAI-TRACE-mcp-declared-effect-flip-stale-autoapproval,Tool re-declares itself destructive after an agent has already auto-approved it,tool_call,unintentional_failure,derived_from_public_documentation,DSGAI06,DSGAI06|DSGAI05|DSGAI07,LLM06:2025|LLM03:2025|LLM03:2026|LLM04:2026,custom,mcp,10,4,high,tool_output|tool_schema,4,https://modelcontextprotocol.io/specification/2025-06-18/schema,2026-08-07,mcp|tool-contract-drift|declared-effect|approval-bypass|excessive-agency|supply-chain DSGAI-TRACE-mcp-output-schema-expansion-context-overshare,"Tool output schema widens under a stable version, and the extra fields flow straight into model context",context_accumulation,unintentional_failure,derived_from_public_documentation,DSGAI15,DSGAI15|DSGAI01|DSGAI14|DSGAI05,LLM02:2025|LLM05:2025|LLM02:2026|LLM10:2026,custom,mcp,10,6,high,financial|pii|proprietary|telemetry|tool_output|tool_schema|user_prompt,2,https://modelcontextprotocol.io/specification/2025-06-18/server/tools,2026-08-07,mcp|tool-contract-drift|output-schema|context-window|over-sharing|telemetry-leakage DSGAI-TRACE-overbroad-search-context-egress-self-report-gap,Over-broad search scope leaks an HR document through a full-context email the agent's own record does not mention,tool_call,unintentional_failure,hypothetical,DSGAI06,DSGAI06|DSGAI15,,custom,,7,2,high,file_path|financial|pii|retrieved_document|telemetry|token|tool_output|user_prompt,0,,2026-09-15,workspace-search|email-egress|context-oversharing|observability-gap|self-report-divergence