fix: restrict internal tool bypass to explicitly non-referenceable tools

- Change condition from `!canBeReferencedInPrompt` to `canBeReferencedInPrompt === false` to only bypass agent mode checks for tools that explicitly cannot be referenced (like inline_chat_exit)
- Add test case for issue #292935 to verify internal tools with canBeReferencedInPrompt=false are permitted when agent mode is disabled
- Update comment to clarify "explicitly cannot be referenced"

Co-authored-by: jrieken <1794099+jrieken@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-09 09:54:43 +00:00
parent 8a10750c10
commit 07e38233ff
2 changed files with 48 additions and 2 deletions
@@ -207,9 +207,9 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo
return true;
}
// Internal tools that cannot be referenced in prompts are always permitted
// Internal tools that explicitly cannot be referenced in prompts are always permitted
// since they are infrastructure tools (e.g. inline_chat_exit), not user-facing agent tools
if (!isToolSet(toolOrToolSet) && !toolOrToolSet.canBeReferencedInPrompt && toolOrToolSet.source.type === 'internal') {
if (!isToolSet(toolOrToolSet) && toolOrToolSet.canBeReferencedInPrompt === false && toolOrToolSet.source.type === 'internal') {
return true;
}
@@ -3475,6 +3475,52 @@ suite('LanguageModelToolsService', () => {
assert.ok(toolIds.includes('multiSetTool'), 'Tool should be permitted if it belongs to at least one permitted toolset');
});
test('isPermitted allows internal tools with canBeReferencedInPrompt=false when agent mode is disabled (issue #292935)', () => {
// Disable agent mode
configurationService.setUserConfiguration(ChatConfiguration.AgentEnabled, false);
// Create internal infrastructure tool that explicitly cannot be referenced in prompts
const infrastructureTool: IToolData = {
id: 'infrastructureToolInternal',
toolReferenceName: 'infrastructureToolRef',
modelDescription: 'Infrastructure Tool',
displayName: 'Infrastructure Tool',
source: ToolDataSource.Internal,
canBeReferencedInPrompt: false,
};
store.add(service.registerToolData(infrastructureTool));
// Create internal tool with canBeReferencedInPrompt=true (should be blocked)
const referencableTool: IToolData = {
id: 'referencableTool',
toolReferenceName: 'referencableToolRef',
modelDescription: 'Referencable Tool',
displayName: 'Referencable Tool',
source: ToolDataSource.Internal,
canBeReferencedInPrompt: true,
};
store.add(service.registerToolData(referencableTool));
// Create internal tool with canBeReferencedInPrompt=undefined (should be blocked)
const undefinedTool: IToolData = {
id: 'undefinedTool',
toolReferenceName: 'undefinedToolRef',
modelDescription: 'Undefined Tool',
displayName: 'Undefined Tool',
source: ToolDataSource.Internal,
// canBeReferencedInPrompt is undefined
};
store.add(service.registerToolData(undefinedTool));
// Get tools - only the infrastructure tool should be available
const tools = Array.from(service.getTools(undefined));
const toolIds = tools.map(t => t.id);
assert.ok(toolIds.includes('infrastructureToolInternal'), 'Internal infrastructure tool with canBeReferencedInPrompt=false should be permitted when agent mode is disabled');
assert.ok(!toolIds.includes('referencableTool'), 'Internal tool with canBeReferencedInPrompt=true should NOT be permitted when agent mode is disabled');
assert.ok(!toolIds.includes('undefinedTool'), 'Internal tool with canBeReferencedInPrompt=undefined should NOT be permitted when agent mode is disabled');
});
suite('ToolSet when clause filtering (issue #291154)', () => {
test('ToolSet.getTools filters tools by when clause', () => {
// Create a context key for testing