From a6831f93bda4e953f670a72c8a60d9f844a1ed01 Mon Sep 17 00:00:00 2001 From: Adam Lin Date: Thu, 2 Jul 2026 04:33:00 +0800 Subject: [PATCH] [New Rule] AWS Bedrock AgentCore Gateway repeated tool invocation failures Seed ES|QL rule for elastic/detection-rules#6126 (Expand LLM and MCP agent detection coverage). Behavior-focused: flags a burst of failed tool invocations against the same AgentCore Gateway target in a short window, using only fields the aws_bedrock_agentcore integration actually populates today (verified against elastic/integrations fields.yml + sample_event.json, not assumed). Also includes the scoped, tool-generated integration-manifests.json.gz entry for aws_bedrock_agentcore (via 'python -m detection_rules dev integrations build-manifests --integration aws_bedrock_agentcore'), required for tests/test_packages.py to pass -- this integration has no prior rule in this repo so it was missing from the local manifest snapshot. --- .../etc/integration-manifests.json.gz | Bin 29542 -> 29803 bytes ...way_repeated_tool_invocation_failures.toml | 110 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 rules/integrations/aws_bedrock_agentcore/aws_bedrock_agentcore_gateway_repeated_tool_invocation_failures.toml diff --git a/detection_rules/etc/integration-manifests.json.gz b/detection_rules/etc/integration-manifests.json.gz index a684e82ee492b934880ad8e83e47884fa9af4573..f8d67da3fbfbd2374bcd2bb32dc54ea8f85dbce9 100644 GIT binary patch delta 2572 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 i_{ka`v4&WYH6%~g@Q5`eI;`Q#m;V8#052Xdu delta 2309 zcmV+g3HtWy=mF;D0S6z82nf*6JFy3TYJXg|+csh_{3=?u3;Ph5;cb~VU1X7_w^cVj zicC8?u_ae>+9W;cvsa?!STSvff~c7vgKTWel19|`149yn0qQXDI-4311D=9pqfq!r z0X`Dq+jGzO!;pLB8TH{#3b<2R+`BC{rPv2WEo!}qPMR=DQ+lKslQc)_c790I4u2E1 zOA<9r z*0~7Zdcl`Eyl$@hDe>Zmm!n^QTaVCNgu4&j`tv9gb#foJD%=*1!_?!;I$dnQ6rl7K zU}PWQ#C>4>v6s`yV!oW8U7s}XCx36ov-9R;KD(ICnv=_Bxg4(^uBOCEvzfB8dk)k0 z-MzGYc{|wXr_EraSM6Y3r6*O|vQ2H-g0{}4w$6gK-ln$RhPGr=+vKmMy4A&H+Ma7tR#d25pMSDsQCYH} zEL&8TEhy_ODl51?E>~A1x|H=6mGu^s%`GaMTTr&JsBB?D+0vr2r3Gaxi^^6Ol&vi) zTU$_;Oa`GO+j$gfYcmW*CbTsfh?2Bsi>K`&JG|MD+u4ESSA%#e`uz++yWOf7RcI76Ma+6iL*`(ZTRc>ceZhvP}Zj-5MTv$DK z7bef$h1GMn$;?EKUoSkm@FugExcVl%$qW~kWVqDFel7fe>-Ux$6QE;D2@v9R|hV!eMa07<@Pk9u`9$Zf?kTpBvh0HbFSt4}u<$!_JY% za+A*&fA5bfbPbnEs%z~OuV3W8esdh+oWYduwb>#2aPr;d-O2F62Kd_Iy22$|I}BLHTkj2QzkV;E*fr_I&H z{KMty$dAUe)78Uun*25|2f)iI;^hH&c{RKM;#{IibALOhl@0|AAnqk9-W3rT0RSUS zz!(4+YXar~fH_UTJOD7S2N*!8T2#U>8Zdy+wWw}VG++R6Yf&khXutr1)}j(F{ACH3 zIOqrf9ce@d5ccOkX*XTEqlx?P+W@NAC`x6Z}Bk;%iN%VotcT2lltOKHlhUhgwETG-F(BaPeZhk*BMA87Uf`7KeN`ocx-j~pageWRP9E==6lOteq z4w{_9B-fTuo?WkAvO0!~53BbqPgai?rZ(|?i+uFuy=o5L(w?5S<4l_k>8*;@ z>+wb}o{zpen=dY##l?rwvybl<&FIJ@%qEuBRz zCEKFcMfKseB#T;7iduS$e(BTn%iN-td4H-}l0_|(oMQ`%ep$%;ayy3^Th-E{s%7e` zRu)yQ(pQx%s!FM=$`)1Sv{kJw&cJo*GjMHj2Ch?|fyv~W_U^s6>Nd`XE9R&6o2&$y zp1-+%BwPCK`JK{D?o!Zyyd9voIG;cA?k`zBGwq1Ki}z~0xL*HH>MPw8W*DBVlYgf} z<>_?t^r$=~(fT4j&m5I!u9Ihh%CpePvqa@t>f~9W@~mV$Wp^RNlkFzXK1TLDBv)B# zD->74;`sL?#q~5eQpM3kfCB1uH zlDy|0{M+w2Of7@^H%~|uSy0I!4u3@lOwlQ#NWc_H4Mhf~sAXRCz#i?@c(e!hXs^bj zJ+Mbhy5R&wmjk=8BwQ2_T>*@)Ku1Tw=m;Af1EXVXbPgDu!$#+U(RpNaCGcsY#6C?_ z!00M$bTu%#8XX-0ql3OUp$wQEWkdHn9~d41`z#68MuNgaj?)u^!$S_wlYaw;ha3qd z4-OAG{zQ2gcmo!PBIKYH6=8W!=9ic6X6wY|eTX98zfq}?DDrI`RT_yR-|bP2M)b+f zpX~t?GELG(laXn%Dw>=jrz2&`Je`rl6`U#abk2Z1oilBojvNhQ(&p)e?CGS<)1i}M zWx=*yEldy16*&&aPF7GG1ad4PgC$I`Pj}vBZ$}pj=4}SEq`r fQ^J*0%>$%n9w1fo0BM*9K7INhzO|93fh!UKgj;j3 diff --git a/rules/integrations/aws_bedrock_agentcore/aws_bedrock_agentcore_gateway_repeated_tool_invocation_failures.toml b/rules/integrations/aws_bedrock_agentcore/aws_bedrock_agentcore_gateway_repeated_tool_invocation_failures.toml new file mode 100644 index 00000000000..b0630dfde4a --- /dev/null +++ b/rules/integrations/aws_bedrock_agentcore/aws_bedrock_agentcore_gateway_repeated_tool_invocation_failures.toml @@ -0,0 +1,110 @@ +[metadata] +creation_date = "2026/07/02" +integration = ["aws_bedrock_agentcore"] +maturity = "development" +updated_date = "2026/07/02" + +[rule] +author = ["Adam Lin"] +description = """ +Identifies a burst of failed tool invocations against the same AgentCore Gateway +target within a short window. A benign tool call fails occasionally (bad input, +transient upstream error), but a concentrated run of failures against one +target from one gateway is also the observable signature of an attacker (or a +compromised/poisoned tool wrapper) probing a tool's parameter surface for an +injection point, an authorization bypass, or a schema weakness before either +giving up or succeeding. This is a behavioral threshold over gateway telemetry +rather than a match on tool-call content, so it is not bypassable by +rephrasing or encoding the probe payload differently. +""" +false_positives = [ + "A genuinely broken or misconfigured downstream target (e.g. a Lambda deployment error) producing errors for all callers, not just one caller probing it.", + "A client-side bug that retries a tool call with the same invalid arguments instead of failing fast.", + "A permission or IAM policy change that has not yet propagated, causing a legitimate integration to fail until the change takes effect.", + "Sanctioned fuzz-testing or contract-testing of a newly deployed gateway target; tune the threshold or add an allowlist for known test targets.", +] +from = "now-60m" +interval = "10m" +language = "esql" +license = "Elastic License v2" +name = "AWS Bedrock AgentCore Gateway Repeated Tool Invocation Failures Against a Single Target" +note = """## Triage and analysis + +### Investigating AWS Bedrock AgentCore Gateway Repeated Tool Invocation Failures Against a Single Target + +A concentrated run of failed tool invocations against the same gateway target in a short window can indicate an +attacker or compromised agent probing the target's argument schema for an injection point, an authorization +bypass, or a way to trigger unintended behavior, rather than ordinary transient failures spread across many +targets and callers. + +#### Possible investigation steps + +- Review the flagged `tool.name` / `target` pair and the surrounding `payload_object.log` lines for the affected + `gateway_name` and `request_id` values to see what arguments were being sent. +- Determine whether the failures come from a single session/actor or are spread across many legitimate callers, + which would point to a broken target instead of probing. +- Check whether the target was recently added, renamed, or had its underlying Lambda/service redeployed. +- Compare the failure burst against the target's normal baseline error rate. + +### False positive analysis + +- Confirm the target is not independently known to be broken or mid-deployment for all callers. +- Rule out a client-side retry bug that resends the same bad request instead of failing after one attempt. +- Check for a recent permissions change that has not finished propagating. + +### Response and remediation + +- If the pattern looks adversarial, disable or quarantine the gateway target and review its access policy and + input validation. +- Review the calling agent session's tool-call history for a subsequent successful call following the failure + burst, which would indicate the probing found a working payload. +""" +references = [ + "https://github.com/Agent-Threat-Rule/agent-threat-rules", + "https://atlas.mitre.org/techniques/AML.T0053", + "https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-observability.html", +] +risk_score = 47 +rule_id = "f0ad6902-ba40-4c20-8502-55a5c5c7e9f3" +severity = "medium" +tags = [ + "Domain: LLM", + "Data Source: AWS Bedrock AgentCore", + "Use Case: Threat Detection", + "Resources: Investigation Guide", +] +timestamp_override = "event.ingested" +type = "esql" + +query = ''' +from logs-aws_bedrock_agentcore.gateway_application_logs-* + +// aws.bedrock_agentcore.gateway.payload_object is an Elasticsearch `flattened` field, so every +// leaf value -- including the JSON boolean isError -- is indexed as a keyword string. Compare +// against the string "true", not the boolean true, or the query silently matches nothing. +| where aws.bedrock_agentcore.gateway.payload_object.isError == "true" + and aws.bedrock_agentcore.gateway.target is not null + +// Bucket into 5-minute windows inside the 60-minute lookback +| eval Esql.time_window = date_trunc(5 minutes, @timestamp) + +| keep + @timestamp, + Esql.time_window, + aws.bedrock_agentcore.gateway.gateway_name, + aws.bedrock_agentcore.gateway.tool.name, + aws.bedrock_agentcore.gateway.target + +// count failed invocations per (gateway, tool, target) per window +| stats Esql.failed_invocations = count() + by aws.bedrock_agentcore.gateway.gateway_name, + aws.bedrock_agentcore.gateway.tool.name, + aws.bedrock_agentcore.gateway.target, + Esql.time_window + +// placeholder threshold -- tune per environment; the FP case is a target that +// is broken for every caller rather than one caller probing it +| where Esql.failed_invocations > 5 + +| sort Esql.failed_invocations desc +'''