fix(hooks): enable image-read blocking by default for third-party profiles

Match WebSearch hook pattern:
- ENABLED by default for settings/cliproxy profiles
- DISABLED for native Claude accounts (account/default)
- User can override via config: hooks.block_image_read.enabled: false

This ensures CCS CLI users get context protection out-of-the-box
while native Claude subscription users are unaffected.
This commit is contained in:
kaitranntt committed 2026-02-02 19:00:46 -05:00
1 parent 38eb74043c
commit 9f3edc5daf
2 files changed
+47 -17

No files matched your search

+33 -13
View File
@@ -7,6 +7,11 @@
* *
* This is a PreToolUse hook that runs BEFORE the tool is executed. * This is a PreToolUse hook that runs BEFORE the tool is executed.
* *
* Behavior (matches WebSearch pattern):
* - ENABLED by default for third-party profiles (settings, cliproxy)
* - DISABLED for native Claude accounts (account, default profiles)
* - User can override via config: hooks.block_image_read.enabled: false
*
* Usage: * Usage:
* Configured in ~/.claude/settings.json: * Configured in ~/.claude/settings.json:
* { * {
@@ -22,10 +27,11 @@
* } * }
* } * }
* *
* Environment Variables: * Environment Variables (set by CCS):
* CCS_BLOCK_IMAGE_READ=1 - Enable blocking (required) * CCS_BLOCK_IMAGE_READ=1 - Enable blocking (default for third-party)
* CCS_BLOCK_IMAGE_READ=0 - Disable blocking (allow all reads) * CCS_BLOCK_IMAGE_READ=0 - Disable blocking
* CCS_DEBUG=1 - Enable debug output * CCS_PROFILE_TYPE - Profile type (account, default, settings, cliproxy)
* CCS_DEBUG=1 - Enable debug output
* *
* Exit codes: * Exit codes:
* 0 - Allow tool (pass-through) * 0 - Allow tool (pass-through)
@@ -53,11 +59,28 @@ process.stdin.on('error', () => {
}); });
/** /**
* Check if blocking is enabled via environment variable * Check if hook should skip (for native Claude accounts).
* Matches WebSearch hook pattern.
*/ */
function isBlockingEnabled() { function shouldSkipHook() {
// Must be explicitly enabled // Account/default profiles use native Claude - don't block
return process.env.CCS_BLOCK_IMAGE_READ === '1'; const profileType = process.env.CCS_PROFILE_TYPE;
if (profileType === 'account' || profileType === 'default') {
if (process.env.CCS_DEBUG) {
console.error(`[CCS Hook] Skipping image block for profile type: ${profileType}`);
}
return true;
}
// Explicit disable via config
if (process.env.CCS_BLOCK_IMAGE_READ === '0') {
if (process.env.CCS_DEBUG) {
console.error('[CCS Hook] Image read blocking disabled by config');
}
return true;
}
return false;
} }
/** /**
@@ -65,11 +88,8 @@ function isBlockingEnabled() {
*/ */
function processHook() { function processHook() {
try { try {
// Skip if blocking not enabled // Skip for native accounts or explicit disable
if (!isBlockingEnabled()) { if (shouldSkipHook()) {
if (process.env.CCS_DEBUG) {
console.error('[CCS Hook] Image read blocking disabled (CCS_BLOCK_IMAGE_READ != 1)');
}
process.exit(0); process.exit(0);
} }
+14 -4
View File
@@ -4,6 +4,9 @@
* Provides environment variables for image read blocking hook configuration. * Provides environment variables for image read blocking hook configuration.
* Prevents context overflow when skills generate images and agent tries to read them. * Prevents context overflow when skills generate images and agent tries to read them.
* *
* Enabled by default for third-party profiles (settings, cliproxy).
* Disabled for native Claude accounts where context is managed server-side.
*
* @module utils/hooks/image-read-block-hook-env * @module utils/hooks/image-read-block-hook-env
*/ */
@@ -13,13 +16,13 @@ import { loadOrCreateUnifiedConfig } from '../../config/unified-config-loader';
* Configuration for image read blocking. * Configuration for image read blocking.
*/ */
export interface ImageReadBlockConfig { export interface ImageReadBlockConfig {
/** Whether blocking is enabled */ /** Whether blocking is enabled (default: true) */
enabled: boolean; enabled: boolean;
} }
/** /**
* Get image read block configuration from unified config. * Get image read block configuration from unified config.
* Defaults to disabled (opt-in feature). * Defaults to ENABLED (opt-out feature) - matches WebSearch pattern.
*/ */
export function getImageReadBlockConfig(): ImageReadBlockConfig { export function getImageReadBlockConfig(): ImageReadBlockConfig {
const config = loadOrCreateUnifiedConfig(); const config = loadOrCreateUnifiedConfig();
@@ -28,14 +31,18 @@ export function getImageReadBlockConfig(): ImageReadBlockConfig {
config as unknown as { hooks?: { block_image_read?: { enabled?: boolean } } } config as unknown as { hooks?: { block_image_read?: { enabled?: boolean } } }
).hooks; ).hooks;
return { return {
// Default to false - must be explicitly enabled // Default to TRUE - enabled by default, user can opt-out
enabled: hooksConfig?.block_image_read?.enabled ?? false, enabled: hooksConfig?.block_image_read?.enabled ?? true,
}; };
} }
/** /**
* Get environment variables for image read block hook configuration. * Get environment variables for image read block hook configuration.
* *
* Like WebSearch, this respects CCS_PROFILE_TYPE:
* - 'account' or 'default' profiles: Skip blocking (native Claude)
* - 'settings' or 'cliproxy' profiles: Apply blocking
*
* @returns Record of environment variables to set before spawning Claude * @returns Record of environment variables to set before spawning Claude
*/ */
export function getImageReadBlockHookEnv(): Record<string, string> { export function getImageReadBlockHookEnv(): Record<string, string> {
@@ -44,6 +51,9 @@ export function getImageReadBlockHookEnv(): Record<string, string> {
if (config.enabled) { if (config.enabled) {
env.CCS_BLOCK_IMAGE_READ = '1'; env.CCS_BLOCK_IMAGE_READ = '1';
} else {
// Explicit disable signal
env.CCS_BLOCK_IMAGE_READ = '0';
} }
return env; return env;