diff --git a/dotnet/samples/02-agents/AgentSkills/Agent_Step07_SkillsAutoApproval/README.md b/dotnet/samples/02-agents/AgentSkills/Agent_Step07_SkillsAutoApproval/README.md
index d300f8e96f6..4b4aea3d1b4 100644
--- a/dotnet/samples/02-agents/AgentSkills/Agent_Step07_SkillsAutoApproval/README.md
+++ b/dotnet/samples/02-agents/AgentSkills/Agent_Step07_SkillsAutoApproval/README.md
@@ -66,6 +66,18 @@ When using multiple providers (e.g., skills + file access), combine their rules
})
```
+## ⚠️ Security: avoid tool-name collisions
+
+Built-in auto-approval rules match tool calls **solely by tool name**. A rule cannot tell the
+provider's own tool apart from any other registered tool that happens to share the same name. If a
+different tool — especially one with a caller-configurable name, such as the Harness shell tool
+(`HarnessAgentOptions.ShellToolName`) — is registered under a name that one of these rules approves
+(e.g. `load_skill`, `read_skill_resource`, `run_skill_script`, or the `file_access_*` names), that
+tool will be **silently auto-approved**, bypassing the human approval boundary.
+
+When using auto-approval rules, ensure no other tool's name collides with the reserved names the
+rules approve, and never assign a configurable tool name that matches one of them.
+
## Skills Included
### unit-converter
diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step02_WorkingWithData/README.md b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step02_WorkingWithData/README.md
index 48dc0175ebc..9755e8ba6b7 100644
--- a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step02_WorkingWithData/README.md
+++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step02_WorkingWithData/README.md
@@ -14,6 +14,12 @@ It builds on Post 1's personal finance assistant and teaches it to work with *yo
saving and deleting still pause for approval. The `place_trade` tool is also wrapped in an
`ApprovalRequiredAIFunction` (see `TradingTools.cs`), so the harness surfaces an approval prompt
before any trade runs. The trade itself is simulated — no real order is placed.
+
+ > ⚠️ **Security — avoid tool-name collisions:** auto-approval rules such as
+ > `FileAccessProvider.ReadOnlyToolsAutoApprovalRule` match tool calls **solely by tool name**. Any
+ > other registered tool that shares one of the approved names (`file_access_read`, `file_access_ls`,
+ > `file_access_grep`) would be silently auto-approved, bypassing the human
+ > approval boundary. Ensure no other tool's name collides with the reserved names a rule approves.
- **Durable memory, two ways:**
- **File memory** (coarse-grained, explicit) — the agent reads/writes files such as
`watchlist.md`. File memory is on by default; its files live on disk under
diff --git a/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/README.md b/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/README.md
index d06348fa728..2eddb0cadba 100644
--- a/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/README.md
+++ b/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/README.md
@@ -51,6 +51,15 @@ You can ask the agent to:
E.g. try the following prompt `Please process the sales.csv file by first filtering it to only North region sales, and then calculating the sum of sales by person. I'd like to write the results of the processing to north_region_totals.csv`.
+## ⚠️ Security: avoid tool-name collisions
+
+This sample uses `FileAccessProvider.ReadOnlyToolsAutoApprovalRule` to auto-approve read-only file
+access tools. Built-in auto-approval rules match tool calls **solely by tool name**, so any other
+registered tool that shares one of the approved names (`file_access_read`, `file_access_ls`,
+`file_access_grep`) would be **silently auto-approved**, bypassing the
+human approval boundary. Ensure no other tool's name collides with the reserved names an
+auto-approval rule approves.
+
## Sample Data
The included `working/sales.csv` contains sales transactions from January to March 2025 with the following columns:
diff --git a/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs b/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs
index 07bc054f733..9d47be27866 100644
--- a/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs
@@ -375,8 +375,17 @@ public sealed class HarnessAgentOptions
/// Gets or sets the name of the shell execution tool exposed to the model.
///
///
+ ///
/// When (the default), the shell executor's default tool name (run_shell) is used.
/// This property is ignored when is .
+ ///
+ ///
+ /// Security warning: auto-approval rules may match tool calls solely by name. Pay attention to
+ /// the tool names approved by auto-approval rules for other features. Setting this property to a
+ /// value that collides with a tool name that is approved by an auto-approval rule for another feature will cause
+ /// the shell tool to also be auto-approved, bypassing the human approval boundary. Choose a unique
+ /// name that no other registered tool uses.
+ ///
///
public string? ShellToolName { get; set; }
diff --git a/dotnet/src/Microsoft.Agents.AI.Tools.Shell/DockerShellExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Tools.Shell/DockerShellExecutor.cs
index 0da232c9f07..349179b98fd 100644
--- a/dotnet/src/Microsoft.Agents.AI.Tools.Shell/DockerShellExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Tools.Shell/DockerShellExecutor.cs
@@ -255,6 +255,14 @@ internal static string FormatMemoryBytes(long memoryBytes) =>
/// gating. Container configuration alone is not a sufficient signal
/// to safely auto-execute model-generated commands — the
/// approval/policy decision belongs to the agent author.
+ ///
+ /// Security warning: auto-approval rules may match tool calls solely by name. Pay attention to
+ /// the tool names approved by auto-approval rules for other features. Setting
+ /// to a value that collides with a tool name that is approved by an auto-approval rule for another feature will
+ /// cause this shell tool to also be auto-approved even when is
+ /// , bypassing the human approval boundary. Choose a unique name that no other
+ /// registered tool uses.
+ ///
///
/// Function name surfaced to the model.
/// Function description for the model.
diff --git a/dotnet/src/Microsoft.Agents.AI.Tools.Shell/LocalShellExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Tools.Shell/LocalShellExecutor.cs
index 97cc29629b1..51e973d0bf4 100644
--- a/dotnet/src/Microsoft.Agents.AI.Tools.Shell/LocalShellExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Tools.Shell/LocalShellExecutor.cs
@@ -325,6 +325,14 @@ private async Task RunStatelessAsync(string command, CancellationTo
/// container where the tool itself is the boundary).
///
/// An wrapping .
+ ///
+ /// Security warning: auto-approval rules may match tool calls solely by name. Pay attention to
+ /// the tool names approved by auto-approval rules for other features. Setting
+ /// to a value that collides with a tool name that is approved by an auto-approval rule for another feature will
+ /// cause this shell tool to also be auto-approved even when is
+ /// , bypassing the human approval boundary. Choose a unique name that no other
+ /// registered tool uses.
+ ///
public override AIFunction AsAIFunction(string name = "run_shell", string? description = null, bool requireApproval = true)
{
if (!requireApproval && !this._acknowledgeUnsafe)
diff --git a/dotnet/src/Microsoft.Agents.AI.Tools.Shell/ShellExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Tools.Shell/ShellExecutor.cs
index 4eb8cf3868b..957b7fd657b 100644
--- a/dotnet/src/Microsoft.Agents.AI.Tools.Shell/ShellExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Tools.Shell/ShellExecutor.cs
@@ -78,6 +78,13 @@ public abstract class ShellExecutor : IAsyncDisposable
/// explicit user approval before executing.
///
/// An wrapping .
+ ///
+ /// Security warning: auto-approval rules may match tool calls solely by name. Pay attention to
+ /// the tool names approved by auto-approval rules for other features. Setting
+ /// to a value that collides with a tool name that is approved by an auto-approval rule for another feature will
+ /// cause this shell tool to also be auto-approved, bypassing the human approval boundary. Choose a
+ /// unique name that no other registered tool uses.
+ ///
public abstract AIFunction AsAIFunction(string name = "run_shell", string? description = null, bool requireApproval = true);
///
diff --git a/dotnet/src/Microsoft.Agents.AI/Harness/FileAccess/FileAccessProvider.cs b/dotnet/src/Microsoft.Agents.AI/Harness/FileAccess/FileAccessProvider.cs
index d7b2f2c2612..95594333aee 100644
--- a/dotnet/src/Microsoft.Agents.AI/Harness/FileAccess/FileAccessProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Harness/FileAccess/FileAccessProvider.cs
@@ -174,6 +174,20 @@ public FileAccessProvider(AgentFileStore fileStore, FileAccessProviderOptions? o
/// The rule matches on the tool name, returning for read-only file access tools
/// and for all other tool calls so that subsequent rules continue to be evaluated.
///
+ ///
+ /// This rule approves calls to exactly the following tool names:
+ ///
+ /// - (file_access_read)
+ /// - (file_access_ls)
+ /// - (file_access_grep)
+ ///
+ ///
+ ///
+ /// Security note: because matching is by tool name only, any other registered tool that
+ /// shares one of these names — for example a configurable-name tool such as the Harness shell
+ /// tool (HarnessAgentOptions.ShellToolName) that was assigned the same name — will also be auto-approved, bypassing the
+ /// human approval boundary. Ensure no other tool collides with these reserved names.
+ ///
///
public static Func> ReadOnlyToolsAutoApprovalRule { get; } =
functionCall => new ValueTask(s_readOnlyToolNames.Contains(functionCall.Name));
@@ -193,6 +207,24 @@ public FileAccessProvider(AgentFileStore fileStore, FileAccessProviderOptions? o
/// The rule matches on the tool name, returning for any file access tool
/// and for all other tool calls so that subsequent rules continue to be evaluated.
///
+ ///
+ /// This rule approves calls to exactly the following tool names:
+ ///
+ /// - (file_access_write)
+ /// - (file_access_read)
+ /// - (file_access_delete)
+ /// - (file_access_ls)
+ /// - (file_access_grep)
+ /// - (file_access_replace)
+ /// - (file_access_replace_lines)
+ ///
+ ///
+ ///
+ /// Security note: because matching is by tool name only, any other registered tool that
+ /// shares one of these names — for example a configurable-name tool such as the Harness shell
+ /// tool (HarnessAgentOptions.ShellToolName) that was assigned the same name — will also be auto-approved, bypassing the
+ /// human approval boundary. Ensure no other tool collides with these reserved names.
+ ///
///
public static Func> AllToolsAutoApprovalRule { get; } =
functionCall => new ValueTask(s_allToolNames.Contains(functionCall.Name));
diff --git a/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgent.cs b/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgent.cs
index 74ac8501fd8..1143fae9c51 100644
--- a/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgent.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgent.cs
@@ -91,6 +91,10 @@ public ToolApprovalAgent(AIAgent innerAgent, ToolApprovalAgentOptions? options =
/// });
///
///
+ ///
+ /// Security note: this rule is name-agnostic and approves every tool call regardless
+ /// of the tool name () or arguments. Only use this rule in a fully trusted context.
+ ///
///
public static Func> AllToolsAutoApprovalRule { get; } =
_ => new ValueTask(true);
diff --git a/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgentOptions.cs b/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgentOptions.cs
index 974e7398a92..2db2b69b981 100644
--- a/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgentOptions.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Harness/ToolApproval/ToolApprovalAgentOptions.cs
@@ -40,6 +40,13 @@ public class ToolApprovalAgentOptions
/// prompting the user. Rules are evaluated in order; the first rule returning
/// causes the function call to be auto-approved.
///
+ ///
+ /// Security warning: auto-approval rules may match tool calls solely by name. A rule provided for
+ /// one feature (for example a provider's read-only rule) may auto-approve any registered tool
+ /// whose name matches, not just the tool the rule was designed for. When adding rules here, ensure
+ /// no unrelated tools you register collide with a name approved by any rule in this list,
+ /// otherwise that tool will be auto-approved without a human prompt, bypassing the approval boundary.
+ ///
///
public IEnumerable>>? AutoApprovalRules { get; set; }
}
diff --git a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs
index 32750f1b8d9..09922b52f3a 100644
--- a/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI/Skills/AgentSkillsProvider.cs
@@ -91,6 +91,19 @@ public sealed partial class AgentSkillsProvider : AIContextProvider, IDisposable
/// The rule matches on the tool name, returning for read-only skill tools
/// and for all other tool calls so that subsequent rules continue to be evaluated.
///
+ ///
+ /// This rule approves calls to exactly the following tool names:
+ ///
+ /// - (load_skill)
+ /// - (read_skill_resource)
+ ///
+ ///
+ ///
+ /// Security note: because matching is by tool name only, any other registered tool that
+ /// shares one of these names — for example a configurable-name tool such as the Harness shell
+ /// tool (HarnessAgentOptions.ShellToolName) that was assigned the same name — will also be auto-approved, bypassing the
+ /// human approval boundary. Ensure no other tool collides with these reserved names.
+ ///
///
public static Func> ReadOnlyToolsAutoApprovalRule { get; } =
functionCall => new ValueTask(s_readOnlyToolNames.Contains(functionCall.Name));
@@ -110,6 +123,20 @@ public sealed partial class AgentSkillsProvider : AIContextProvider, IDisposable
/// The rule matches on the tool name, returning for any skill tool
/// and for all other tool calls so that subsequent rules continue to be evaluated.
///
+ ///
+ /// This rule approves calls to exactly the following tool names:
+ ///
+ /// - (load_skill)
+ /// - (read_skill_resource)
+ /// - (run_skill_script)
+ ///
+ ///
+ ///
+ /// Security note: because matching is by tool name only, any other registered tool that
+ /// shares one of these names — for example a configurable-name tool such as the Harness shell
+ /// tool (HarnessAgentOptions.ShellToolName) that was assigned the same name — will also be auto-approved, bypassing the
+ /// human approval boundary. Ensure no other tool collides with these reserved names.
+ ///
///
public static Func> AllToolsAutoApprovalRule { get; } =
functionCall => new ValueTask(s_allToolNames.Contains(functionCall.Name));