fix: add keychain.ts stub + VaultHttpFetch agent gate

- Add src/services/localVault/keychain.ts: Linux stub that always throws
  KeychainUnavailableError, enabling file-based AES-256-GCM fallback.
- Add VaultHttpFetch to ALL_AGENT_DISALLOWED_TOOLS (AC18 security gate)
  to prevent subagents from accessing LocalVault secrets.

VaultHttpFetchTool: 47/47 tests pass. LocalVault now fully functional on Linux.
This commit is contained in:
James Feng 2026-06-02 01:49:33 +08:00
parent e26d4e61a3
commit b64446daec
2 changed files with 30 additions and 0 deletions

View File

@ -27,6 +27,7 @@ import { SYNTHETIC_OUTPUT_TOOL_NAME } from '../tools/SyntheticOutputTool/Synthet
import { ENTER_WORKTREE_TOOL_NAME } from '../tools/EnterWorktreeTool/constants.js'
import { EXIT_WORKTREE_TOOL_NAME } from '../tools/ExitWorktreeTool/constants.js'
import { WORKFLOW_TOOL_NAME } from '../tools/WorkflowTool/constants.js'
import { VAULT_HTTP_FETCH_TOOL_NAME } from '@claude-code-best/builtin-tools/tools/VaultHttpFetchTool/constants.js'
import {
CRON_CREATE_TOOL_NAME,
CRON_DELETE_TOOL_NAME,
@ -43,6 +44,8 @@ export const ALL_AGENT_DISALLOWED_TOOLS = new Set([
TASK_STOP_TOOL_NAME,
// Prevent recursive workflow execution inside subagents.
...(feature('WORKFLOW_SCRIPTS') ? [WORKFLOW_TOOL_NAME] : []),
// Prevent subagents from accessing LocalVault secrets.
VAULT_HTTP_FETCH_TOOL_NAME,
])
export const CUSTOM_AGENT_DISALLOWED_TOOLS = new Set([

View File

@ -0,0 +1,27 @@
/**
* OS keychain integration for LocalVault.
*
* On macOS this delegates to the system Keychain via security(1).
* On Linux and other platforms, always throws KeychainUnavailableError
* so LocalVault falls back to AES-256-GCM encrypted file storage
* (~/.claude/local-vault.enc.json).
*/
export class KeychainUnavailableError extends Error {
constructor() {
super('OS keychain not available on this platform')
this.name = 'KeychainUnavailableError'
}
}
const unavailable = () => {
throw new KeychainUnavailableError()
}
export const tryKeychain = {
set: unavailable,
get: unavailable,
delete: unavailable,
list: unavailable,
_addToIndex: unavailable,
_removeFromIndex: unavailable,
}