Custom Agents - Secret-shaped value in observed tool result
Custom Secrets In Tool Result
Query
let Evidence=materialize(CustomAgentInlineContent(1h));
Evidence
| where IsTool and ToolResult matches regex @'(-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----|(?:AKIA|ASIA)[A-Z0-9]{16}|gh[pousr]_[A-Za-z0-9]{36,}|sk-[A-Za-z0-9_-]{20,})'
| summarize arg_min(EventTime, *) by _ResourceId, OperationId, AgentKey
| extend Signal='Observed tool result contains a credential-shaped pattern'
| extend TimeGenerated=EventTime, ResourceId=_ResourceId, TraceId=OperationId,
EventCount=tolong(column_ifexists('EventCount', 1)),
SuccessfulCalls=tolong(column_ifexists('SuccessfulCalls', 0)),
FailedCalls=tolong(column_ifexists('FailedCalls', 0))
| project TimeGenerated, ResourceId, Agent, AgentId, AgentKey, AppRoleName,
TraceId, SpanId, Conversation, Model, Tool, TargetHost, ServerDisplay,
Signal, EventCount, SuccessfulCalls, FailedCalls,
TriggerSpanId=tostring(column_ifexists('TriggerSpanId', '')),
TriggerTime=todatetime(column_ifexists('TriggerTime', datetime(null))),
TriggerTool=tostring(column_ifexists('TriggerTool', '')),
TriggerToolResult=tostring(column_ifexists('TriggerToolResult', '')),
TriggerServerDisplay=tostring(column_ifexists('TriggerServerDisplay', '')),
TriggerTargetHost=tostring(column_ifexists('TriggerTargetHost', '')),
RiskyOutputKind=tostring(column_ifexists('RiskyOutputKind', '')),
RelatedToolResults=tolong(column_ifexists('RelatedToolResults', 0)),
MatchedIntentPrompt=tostring(column_ifexists('IntentPrompt', '')),
MatchedIntentSpanId=tostring(column_ifexists('IntentSpanId', ''))
| join kind=leftouter (Evidence
| project ResourceId=_ResourceId, TraceId=OperationId, SpanId, AgentKey, Prompt, Output, ToolArguments, ToolResult, InputMessages, OutputMessages,
EvidenceSource, PromptEvidenceOrigin, OutputEvidenceOrigin, PromptEvidenceSpanId, OutputEvidenceSpanId,
InputParseState, OutputParseState, ToolArgumentsState, ToolResultState)
on ResourceId, TraceId, SpanId, AgentKey
| extend Prompt=coalesce(MatchedIntentPrompt, Prompt),
PromptEvidenceOrigin=iff(isnotempty(MatchedIntentPrompt), 'Matched intent span: user role', PromptEvidenceOrigin),
PromptEvidenceSpanId=coalesce(MatchedIntentSpanId, PromptEvidenceSpanId)
| extend PreviewCharacters=toint(min_of(160, max_of(0, (1500 - string_size(tostring(bag_pack(
'AgentId', AgentId, 'AgentKey', AgentKey, 'TraceId', TraceId, 'SpanId', SpanId,
'Conversation', Conversation, 'ResourceId', ResourceId, 'Signal', Signal)))) / 12)))
| extend PromptPreview=substring(Prompt, 0, PreviewCharacters),
OutputPreview=substring(Output, 0, PreviewCharacters)
| extend EvidencePreviewStatus=case(PreviewCharacters == 0, 'Metadata exhausted preview budget; inspect full query results',
strlen(Prompt) > PreviewCharacters or strlen(Output) > PreviewCharacters, 'Inline evidence; previews shortened; full text in query results',
isempty(Prompt) and isempty(Output), 'No prompt/output captured or parsed; not a protection verdict',
'Inline evidence; full recorded text in query results')
| project TimeGenerated, ResourceId, Agent, AgentId, AgentKey, AppRoleName,
TraceId, SpanId, Conversation, Model, Tool, TargetHost, ServerDisplay,
Signal, EventCount, SuccessfulCalls, FailedCalls, Prompt, Output, ToolArguments, ToolResult, InputMessages, OutputMessages,
EvidenceSource, PromptEvidenceOrigin, OutputEvidenceOrigin, PromptEvidenceSpanId, OutputEvidenceSpanId,
InputParseState, OutputParseState, ToolArgumentsState, ToolResultState,
PromptPreview, OutputPreview, EvidencePreviewStatus, TriggerSpanId, TriggerTime, TriggerTool, TriggerToolResult,
TriggerServerDisplay, TriggerTargetHost, RiskyOutputKind, RelatedToolResults
| order by TimeGenerated descExplanation
This query is designed to detect patterns that resemble credentials (like private keys or access tokens) in the results of tools executed within a specific environment. Here's a simplified breakdown of what the query does:
-
Purpose: It aims to identify potential credential-like patterns in the results of tools used within a system. This doesn't confirm the presence of valid credentials but highlights patterns that look like them.
-
Data Source: The query uses data from Application Insights, specifically focusing on application requests and dependencies.
-
Frequency and Duration: It runs every hour and looks back over the past 14 days.
-
Severity: The alert generated by this query is considered "High" severity.
-
Detection Logic:
- It first collects evidence of tool executions over the past hour.
- It filters these results to find patterns that match known credential formats (e.g., private keys, AWS keys, GitHub tokens).
- It summarizes the findings by the resource and operation identifiers.
-
Output:
- It generates alerts with details like the time of the event, resource ID, agent details, and a signal indicating the detection of a credential-like pattern.
- It provides a preview of the prompt and output where the pattern was found, along with a status message about the evidence preview.
-
Alert and Incident Management:
- Alerts are configured to create incidents, with settings to group related alerts based on specific fields like AgentKey and ResourceId.
-
Status: The query is currently disabled (
enabled: false). -
Additional Information:
- It includes mappings to Azure resources and cloud applications for better context.
- Custom details and tags are used for categorization and further analysis.
Overall, this query is part of a security monitoring setup to help detect potential security risks related to credential exposure in tool outputs.