fix(browser-agent): enable "Allow all server tools" session policy (#22343)

This commit is contained in:
cynthialong0-0
2026-03-19 09:32:35 -07:00
committed by GitHub
parent 39d3b0e28c
commit 7de0616229
7 changed files with 297 additions and 6 deletions
+28
View File
@@ -630,6 +630,34 @@ name = "invalid-name"
).toBeUndefined();
});
it('should support mcpName in policy rules from TOML', async () => {
mockPolicyFile(
nodePath.join(MOCK_DEFAULT_DIR, 'mcp.toml'),
`
[[rule]]
toolName = "my-tool"
mcpName = "my-server"
decision = "allow"
priority = 150
`,
);
const config = await createPolicyEngineConfig(
{},
ApprovalMode.DEFAULT,
MOCK_DEFAULT_DIR,
);
const rule = config.rules?.find(
(r) =>
r.toolName === 'mcp_my-server_my-tool' &&
r.mcpName === 'my-server' &&
r.decision === PolicyDecision.ALLOW,
);
expect(rule).toBeDefined();
expect(rule?.priority).toBeCloseTo(1.15, 5);
});
it('should have default ASK_USER rule for discovered tools', async () => {
const config = await createPolicyEngineConfig({}, ApprovalMode.DEFAULT);
const discoveredRule = config.rules?.find(
+2
View File
@@ -576,6 +576,7 @@ export function createPolicyUpdater(
decision: PolicyDecision.ALLOW,
priority,
argsPattern: new RegExp(pattern),
mcpName: message.mcpName,
source: 'Dynamic (Confirmed)',
});
}
@@ -611,6 +612,7 @@ export function createPolicyUpdater(
decision: PolicyDecision.ALLOW,
priority,
argsPattern,
mcpName: message.mcpName,
source: 'Dynamic (Confirmed)',
});
}
@@ -30,6 +30,8 @@ vi.mock('../utils/shell-utils.js', () => ({
interface ParsedPolicy {
rule?: Array<{
commandPrefix?: string | string[];
mcpName?: string;
toolName?: string;
}>;
}
@@ -67,6 +69,7 @@ describe('createPolicyUpdater', () => {
type: MessageBusType.UPDATE_POLICY,
toolName: 'run_shell_command',
commandPrefix: ['echo', 'ls'],
mcpName: 'test-mcp',
persist: false,
});
@@ -76,6 +79,7 @@ describe('createPolicyUpdater', () => {
expect.objectContaining({
toolName: 'run_shell_command',
priority: ALWAYS_ALLOW_PRIORITY,
mcpName: 'test-mcp',
argsPattern: new RegExp(
escapeRegex('"command":"echo') + '(?:[\\s"]|\\\\")',
),
@@ -86,6 +90,7 @@ describe('createPolicyUpdater', () => {
expect.objectContaining({
toolName: 'run_shell_command',
priority: ALWAYS_ALLOW_PRIORITY,
mcpName: 'test-mcp',
argsPattern: new RegExp(
escapeRegex('"command":"ls') + '(?:[\\s"]|\\\\")',
),
@@ -93,6 +98,63 @@ describe('createPolicyUpdater', () => {
);
});
it('should pass mcpName to policyEngine.addRule for argsPattern updates', async () => {
createPolicyUpdater(policyEngine, messageBus, mockStorage);
await messageBus.publish({
type: MessageBusType.UPDATE_POLICY,
toolName: 'test_tool',
argsPattern: '"foo":"bar"',
mcpName: 'test-mcp',
persist: false,
});
expect(policyEngine.addRule).toHaveBeenCalledWith(
expect.objectContaining({
toolName: 'test_tool',
mcpName: 'test-mcp',
argsPattern: /"foo":"bar"/,
}),
);
});
it('should persist mcpName to TOML', async () => {
createPolicyUpdater(policyEngine, messageBus, mockStorage);
vi.mocked(fs.readFile).mockRejectedValue({ code: 'ENOENT' });
vi.mocked(fs.mkdir).mockResolvedValue(undefined);
const mockFileHandle = {
writeFile: vi.fn().mockResolvedValue(undefined),
close: vi.fn().mockResolvedValue(undefined),
};
vi.mocked(fs.open).mockResolvedValue(
mockFileHandle as unknown as fs.FileHandle,
);
vi.mocked(fs.rename).mockResolvedValue(undefined);
await messageBus.publish({
type: MessageBusType.UPDATE_POLICY,
toolName: 'mcp_test-mcp_tool',
mcpName: 'test-mcp',
commandPrefix: 'ls',
persist: true,
});
// Wait for the async listener to complete
await new Promise((resolve) => setTimeout(resolve, 0));
expect(fs.open).toHaveBeenCalled();
const [content] = mockFileHandle.writeFile.mock.calls[0] as [
string,
string,
];
const parsed = toml.parse(content) as unknown as ParsedPolicy;
expect(parsed.rule).toHaveLength(1);
expect(parsed.rule![0].mcpName).toBe('test-mcp');
expect(parsed.rule![0].toolName).toBe('tool'); // toolName should be stripped of MCP prefix
});
it('should add a single rule when commandPrefix is a string', async () => {
createPolicyUpdater(policyEngine, messageBus, mockStorage);