fix: address PR #4180 review - security, typing, and test coverage
- Apply mcp_env_allowlist to plugin hooks: intersect HTTP allowedEnvVars with MCP allowlist, set command allowedEnvVars to full MCP allowlist - Scrub process.env in executeHookCommand when allowedEnvVars provided - Add PluginHooksState class with per-directory Map storage - Add PluginHooksConfig interface for typed boundary layer - Pass directory context through hook-config-handler - Add 16 tests across 4 files (40 assertions) covering allowlist filtering, env scrubbing, directory isolation, and edge cases - Remove unnecessary 'as' type assertions, use discriminated union narrowing instead
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
const { afterEach, beforeEach, describe, expect, mock, test } = require("bun:test")
|
||||
|
||||
const mockSetPluginHooksConfigs = mock(() => {})
|
||||
|
||||
mock.module("../hooks/claude-code-hooks/config", () => ({
|
||||
setPluginHooksConfigs: mockSetPluginHooksConfigs,
|
||||
}))
|
||||
|
||||
const { applyHookConfig } = await import("./hook-config-handler")
|
||||
|
||||
describe("applyHookConfig", () => {
|
||||
beforeEach(() => {
|
||||
mockSetPluginHooksConfigs.mockClear()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
mockSetPluginHooksConfigs.mockClear()
|
||||
})
|
||||
|
||||
test("#given ctx.directory #when applyHookConfig called #then setPluginHooksConfigs receives ctx.directory", () => {
|
||||
// given
|
||||
const testDirectory = "/test/dir"
|
||||
const pluginComponents = {
|
||||
commands: {},
|
||||
skills: {},
|
||||
agents: {},
|
||||
mcpServers: {},
|
||||
hooksConfigs: [
|
||||
{
|
||||
hooks: {
|
||||
Stop: [
|
||||
{
|
||||
matcher: "*",
|
||||
hooks: [{ type: "command", command: "echo test" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
plugins: [{ name: "test-plugin", version: "1.0.0" }],
|
||||
errors: [],
|
||||
}
|
||||
|
||||
// when
|
||||
applyHookConfig({
|
||||
pluginComponents,
|
||||
ctx: { directory: testDirectory },
|
||||
})
|
||||
|
||||
// then
|
||||
expect(mockSetPluginHooksConfigs).toHaveBeenCalledTimes(1)
|
||||
expect(mockSetPluginHooksConfigs).toHaveBeenCalledWith(
|
||||
testDirectory,
|
||||
pluginComponents.hooksConfigs,
|
||||
)
|
||||
})
|
||||
|
||||
test("#given empty hooksConfigs #when applyHookConfig called #then setPluginHooksConfigs still called with empty array", () => {
|
||||
// given
|
||||
const testDirectory = "/another/dir"
|
||||
const pluginComponents = {
|
||||
commands: {},
|
||||
skills: {},
|
||||
agents: {},
|
||||
mcpServers: {},
|
||||
hooksConfigs: [],
|
||||
plugins: [],
|
||||
errors: [],
|
||||
}
|
||||
|
||||
// when
|
||||
applyHookConfig({
|
||||
pluginComponents,
|
||||
ctx: { directory: testDirectory },
|
||||
})
|
||||
|
||||
// then
|
||||
expect(mockSetPluginHooksConfigs).toHaveBeenCalledTimes(1)
|
||||
expect(mockSetPluginHooksConfigs).toHaveBeenCalledWith(testDirectory, [])
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
||||
Reference in New Issue
Block a user