@yu_robotics/remote-cli 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +13 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/security/HooksConfigurator.d.ts +32 -0
- package/dist/security/HooksConfigurator.d.ts.map +1 -0
- package/dist/security/HooksConfigurator.js +171 -0
- package/dist/security/HooksConfigurator.js.map +1 -0
- package/dist/security/index.d.ts +8 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +14 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security-guard.d.ts +46 -0
- package/dist/security/security-guard.d.ts.map +1 -0
- package/dist/security/security-guard.js +323 -0
- package/dist/security/security-guard.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oBAAoB;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA+I7B"}
|
package/dist/commands/start.js
CHANGED
|
@@ -9,6 +9,7 @@ const WebSocketClient_1 = require("../client/WebSocketClient");
|
|
|
9
9
|
const executor_1 = require("../executor");
|
|
10
10
|
const MessageHandler_1 = require("../client/MessageHandler");
|
|
11
11
|
const DirectoryGuard_1 = require("../security/DirectoryGuard");
|
|
12
|
+
const HooksConfigurator_1 = require("../security/HooksConfigurator");
|
|
12
13
|
const ora_1 = __importDefault(require("ora"));
|
|
13
14
|
/**
|
|
14
15
|
* Start the remote CLI service
|
|
@@ -53,6 +54,18 @@ async function startCommand(options) {
|
|
|
53
54
|
// Initialize components
|
|
54
55
|
spinner.text = 'Initializing components...';
|
|
55
56
|
const directoryGuard = new DirectoryGuard_1.DirectoryGuard(security.allowedDirectories);
|
|
57
|
+
// Configure Claude Code security hooks
|
|
58
|
+
spinner.text = 'Configuring security hooks...';
|
|
59
|
+
const hooksConfigurator = new HooksConfigurator_1.HooksConfigurator();
|
|
60
|
+
try {
|
|
61
|
+
await hooksConfigurator.configure();
|
|
62
|
+
console.log('🔒 Security hooks configured');
|
|
63
|
+
}
|
|
64
|
+
catch (hookError) {
|
|
65
|
+
// Non-fatal: warn but continue
|
|
66
|
+
console.warn('⚠️ Failed to configure security hooks:', hookError instanceof Error ? hookError.message : 'Unknown error');
|
|
67
|
+
console.warn(' File operations may not be restricted to working directory.');
|
|
68
|
+
}
|
|
56
69
|
// Get last working directory from config (if set) to initialize executor with correct path
|
|
57
70
|
// This ensures .claude-session file is stored in the working directory, not startup directory
|
|
58
71
|
const lastWorkingDirectory = config.get('lastWorkingDirectory');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HooksConfigurator - Manages Claude Code hooks configuration
|
|
3
|
+
*
|
|
4
|
+
* This module handles the configuration of Claude Code's PreToolUse hooks
|
|
5
|
+
* to enforce directory-based security restrictions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* HooksConfigurator manages Claude Code hooks configuration
|
|
9
|
+
* for security enforcement
|
|
10
|
+
*/
|
|
11
|
+
export declare class HooksConfigurator {
|
|
12
|
+
private claudeSettingsPath;
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Configure Claude Code hooks for security
|
|
16
|
+
* Adds the security guard hook to PreToolUse
|
|
17
|
+
*/
|
|
18
|
+
configure(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Remove security guard hooks from Claude settings
|
|
21
|
+
*/
|
|
22
|
+
unconfigure(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Check if security guard hooks are configured
|
|
25
|
+
*/
|
|
26
|
+
isConfigured(): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Get the path to the security guard script
|
|
29
|
+
*/
|
|
30
|
+
getSecurityGuardPath(): string;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=HooksConfigurator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HooksConfigurator.d.ts","sourceRoot":"","sources":["../../src/security/HooksConfigurator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+BH;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,kBAAkB,CAAS;;IAUnC;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAsDhC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAiClC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IA0BtC;;OAEG;IACH,oBAAoB,IAAI,MAAM;CAO/B"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HooksConfigurator - Manages Claude Code hooks configuration
|
|
4
|
+
*
|
|
5
|
+
* This module handles the configuration of Claude Code's PreToolUse hooks
|
|
6
|
+
* to enforce directory-based security restrictions.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.HooksConfigurator = void 0;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
/**
|
|
47
|
+
* File operation tools that need security validation
|
|
48
|
+
*/
|
|
49
|
+
const FILE_TOOLS = ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'NotebookEdit'];
|
|
50
|
+
/**
|
|
51
|
+
* HooksConfigurator manages Claude Code hooks configuration
|
|
52
|
+
* for security enforcement
|
|
53
|
+
*/
|
|
54
|
+
class HooksConfigurator {
|
|
55
|
+
claudeSettingsPath;
|
|
56
|
+
constructor() {
|
|
57
|
+
this.claudeSettingsPath = path.join(os.homedir(), '.claude', 'settings.json');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Configure Claude Code hooks for security
|
|
61
|
+
* Adds the security guard hook to PreToolUse
|
|
62
|
+
*/
|
|
63
|
+
async configure() {
|
|
64
|
+
const securityGuardPath = this.getSecurityGuardPath();
|
|
65
|
+
// Verify security guard script exists
|
|
66
|
+
if (!fs.existsSync(securityGuardPath)) {
|
|
67
|
+
throw new Error(`Security guard script not found at: ${securityGuardPath}`);
|
|
68
|
+
}
|
|
69
|
+
// Read existing settings or create empty object
|
|
70
|
+
let settings = {};
|
|
71
|
+
try {
|
|
72
|
+
if (fs.existsSync(this.claudeSettingsPath)) {
|
|
73
|
+
const content = fs.readFileSync(this.claudeSettingsPath, 'utf8');
|
|
74
|
+
settings = JSON.parse(content);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// If file doesn't exist or can't be parsed, start fresh
|
|
79
|
+
settings = {};
|
|
80
|
+
}
|
|
81
|
+
// Initialize hooks structure
|
|
82
|
+
settings.hooks = settings.hooks || {};
|
|
83
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
84
|
+
// Check if security guard hook is already configured
|
|
85
|
+
const hookCommand = `node "${securityGuardPath}"`;
|
|
86
|
+
const existingHook = settings.hooks.PreToolUse.find((hook) => {
|
|
87
|
+
const command = typeof hook === 'string' ? hook : hook.command;
|
|
88
|
+
return command.includes('security-guard');
|
|
89
|
+
});
|
|
90
|
+
// Add hook if not already present
|
|
91
|
+
if (!existingHook) {
|
|
92
|
+
const newHook = {
|
|
93
|
+
command: hookCommand,
|
|
94
|
+
tools: FILE_TOOLS
|
|
95
|
+
};
|
|
96
|
+
settings.hooks.PreToolUse.push(newHook);
|
|
97
|
+
}
|
|
98
|
+
// Ensure .claude directory exists
|
|
99
|
+
const claudeDir = path.dirname(this.claudeSettingsPath);
|
|
100
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
101
|
+
// Write settings
|
|
102
|
+
fs.writeFileSync(this.claudeSettingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
103
|
+
console.log('[HooksConfigurator] Claude Code hooks configured successfully');
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Remove security guard hooks from Claude settings
|
|
107
|
+
*/
|
|
108
|
+
async unconfigure() {
|
|
109
|
+
// Check if settings file exists
|
|
110
|
+
if (!fs.existsSync(this.claudeSettingsPath)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Read settings
|
|
114
|
+
let settings;
|
|
115
|
+
try {
|
|
116
|
+
const content = fs.readFileSync(this.claudeSettingsPath, 'utf8');
|
|
117
|
+
settings = JSON.parse(content);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Remove security guard hooks from PreToolUse
|
|
123
|
+
if (settings.hooks?.PreToolUse) {
|
|
124
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter((hook) => {
|
|
125
|
+
const command = typeof hook === 'string' ? hook : hook.command;
|
|
126
|
+
return !command.includes('security-guard');
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Write settings back
|
|
130
|
+
fs.writeFileSync(this.claudeSettingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
131
|
+
console.log('[HooksConfigurator] Claude Code hooks removed');
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if security guard hooks are configured
|
|
135
|
+
*/
|
|
136
|
+
async isConfigured() {
|
|
137
|
+
// Check if settings file exists
|
|
138
|
+
if (!fs.existsSync(this.claudeSettingsPath)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
// Read settings
|
|
142
|
+
let settings;
|
|
143
|
+
try {
|
|
144
|
+
const content = fs.readFileSync(this.claudeSettingsPath, 'utf8');
|
|
145
|
+
settings = JSON.parse(content);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
// Check for security guard in PreToolUse
|
|
151
|
+
if (!settings.hooks?.PreToolUse) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
return settings.hooks.PreToolUse.some((hook) => {
|
|
155
|
+
const command = typeof hook === 'string' ? hook : hook.command;
|
|
156
|
+
return command.includes('security-guard');
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get the path to the security guard script
|
|
161
|
+
*/
|
|
162
|
+
getSecurityGuardPath() {
|
|
163
|
+
// The security guard script is in the same directory as this module
|
|
164
|
+
// Try .ts first (for development), then .js (for production)
|
|
165
|
+
const tsPath = path.join(__dirname, 'security-guard.ts');
|
|
166
|
+
const jsPath = path.join(__dirname, 'security-guard.js');
|
|
167
|
+
return fs.existsSync(tsPath) ? tsPath : jsPath;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.HooksConfigurator = HooksConfigurator;
|
|
171
|
+
//# sourceMappingURL=HooksConfigurator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HooksConfigurator.js","sourceRoot":"","sources":["../../src/security/HooksConfigurator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security module exports
|
|
3
|
+
*/
|
|
4
|
+
export { DirectoryGuard } from './DirectoryGuard';
|
|
5
|
+
export { HooksConfigurator } from './HooksConfigurator';
|
|
6
|
+
export { validateToolUse, loadAllowedDirs } from './security-guard';
|
|
7
|
+
export type { ValidationResult, HookData } from './security-guard';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security module exports
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadAllowedDirs = exports.validateToolUse = exports.HooksConfigurator = exports.DirectoryGuard = void 0;
|
|
7
|
+
var DirectoryGuard_1 = require("./DirectoryGuard");
|
|
8
|
+
Object.defineProperty(exports, "DirectoryGuard", { enumerable: true, get: function () { return DirectoryGuard_1.DirectoryGuard; } });
|
|
9
|
+
var HooksConfigurator_1 = require("./HooksConfigurator");
|
|
10
|
+
Object.defineProperty(exports, "HooksConfigurator", { enumerable: true, get: function () { return HooksConfigurator_1.HooksConfigurator; } });
|
|
11
|
+
var security_guard_1 = require("./security-guard");
|
|
12
|
+
Object.defineProperty(exports, "validateToolUse", { enumerable: true, get: function () { return security_guard_1.validateToolUse; } });
|
|
13
|
+
Object.defineProperty(exports, "loadAllowedDirs", { enumerable: true, get: function () { return security_guard_1.loadAllowedDirs; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,yDAAwD;AAA/C,sHAAA,iBAAiB,OAAA;AAC1B,mDAAoE;AAA3D,iHAAA,eAAe,OAAA;AAAE,iHAAA,eAAe,OAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Guard for Claude Code PreToolUse Hooks
|
|
3
|
+
*
|
|
4
|
+
* This module validates tool usage against allowed directory restrictions.
|
|
5
|
+
* It can be used as:
|
|
6
|
+
* 1. A library function (validateToolUse) for testing and programmatic use
|
|
7
|
+
* 2. A standalone script called by Claude Code hooks
|
|
8
|
+
*
|
|
9
|
+
* Exit codes (when run as script):
|
|
10
|
+
* 0 = Allow execution
|
|
11
|
+
* 2 = Block execution (permission denied)
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Result of tool use validation
|
|
15
|
+
*/
|
|
16
|
+
export interface ValidationResult {
|
|
17
|
+
allowed: boolean;
|
|
18
|
+
reason: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Hook data passed from Claude Code
|
|
22
|
+
*/
|
|
23
|
+
export interface HookData {
|
|
24
|
+
tool_name: string;
|
|
25
|
+
tool_input: Record<string, any> | undefined;
|
|
26
|
+
cwd?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate tool use against allowed directories
|
|
30
|
+
*
|
|
31
|
+
* @param hookData - Data from Claude Code hook (tool_name, tool_input, etc.)
|
|
32
|
+
* @param allowedDirs - List of allowed directory paths
|
|
33
|
+
* @returns ValidationResult indicating if the operation is allowed
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateToolUse(hookData: HookData, allowedDirs: string[]): ValidationResult;
|
|
36
|
+
/**
|
|
37
|
+
* Load allowed directories from config file
|
|
38
|
+
* If lastWorkingDirectory is set, use it as the primary allowed directory
|
|
39
|
+
*/
|
|
40
|
+
export declare function loadAllowedDirs(configPath?: string): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Main function when run as a script
|
|
43
|
+
* Reads hook data from stdin and exits with appropriate code
|
|
44
|
+
*/
|
|
45
|
+
export declare function main(): Promise<void>;
|
|
46
|
+
//# sourceMappingURL=security-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-guard.d.ts","sourceRoot":"","sources":["../../src/security/security-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAsLD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,gBAAgB,CA+D3F;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB7D;AAED;;;GAGG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAiC1C"}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security Guard for Claude Code PreToolUse Hooks
|
|
4
|
+
*
|
|
5
|
+
* This module validates tool usage against allowed directory restrictions.
|
|
6
|
+
* It can be used as:
|
|
7
|
+
* 1. A library function (validateToolUse) for testing and programmatic use
|
|
8
|
+
* 2. A standalone script called by Claude Code hooks
|
|
9
|
+
*
|
|
10
|
+
* Exit codes (when run as script):
|
|
11
|
+
* 0 = Allow execution
|
|
12
|
+
* 2 = Block execution (permission denied)
|
|
13
|
+
*/
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
26
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
27
|
+
}) : function(o, v) {
|
|
28
|
+
o["default"] = v;
|
|
29
|
+
});
|
|
30
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
31
|
+
var ownKeys = function(o) {
|
|
32
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
33
|
+
var ar = [];
|
|
34
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
35
|
+
return ar;
|
|
36
|
+
};
|
|
37
|
+
return ownKeys(o);
|
|
38
|
+
};
|
|
39
|
+
return function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.validateToolUse = validateToolUse;
|
|
49
|
+
exports.loadAllowedDirs = loadAllowedDirs;
|
|
50
|
+
exports.main = main;
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
/**
|
|
54
|
+
* File operation tools that need path validation
|
|
55
|
+
*/
|
|
56
|
+
const FILE_TOOLS = ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'NotebookEdit'];
|
|
57
|
+
/**
|
|
58
|
+
* Dangerous commands that should always be blocked
|
|
59
|
+
*/
|
|
60
|
+
const DANGEROUS_COMMANDS = ['sudo'];
|
|
61
|
+
/**
|
|
62
|
+
* Patterns that indicate piping to a shell (dangerous)
|
|
63
|
+
*/
|
|
64
|
+
const PIPE_TO_SHELL_PATTERNS = [
|
|
65
|
+
/\|\s*bash\b/,
|
|
66
|
+
/\|\s*sh\b/,
|
|
67
|
+
/\|\s*zsh\b/,
|
|
68
|
+
/\|\s*source\b/,
|
|
69
|
+
/\$\(/, // Command substitution
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Resolve a path that may contain ~ to an absolute path
|
|
73
|
+
*/
|
|
74
|
+
function resolvePath(filePath, cwd) {
|
|
75
|
+
// Handle tilde expansion
|
|
76
|
+
if (filePath.startsWith('~')) {
|
|
77
|
+
const home = process.env.HOME || '';
|
|
78
|
+
filePath = path.join(home, filePath.slice(1));
|
|
79
|
+
}
|
|
80
|
+
// Handle relative paths
|
|
81
|
+
if (!path.isAbsolute(filePath)) {
|
|
82
|
+
const basePath = cwd || process.cwd();
|
|
83
|
+
filePath = path.resolve(basePath, filePath);
|
|
84
|
+
}
|
|
85
|
+
// Normalize to resolve .. and .
|
|
86
|
+
return path.normalize(filePath);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve an allowed directory path (may contain ~)
|
|
90
|
+
*/
|
|
91
|
+
function resolveAllowedDir(dirPath) {
|
|
92
|
+
if (dirPath.startsWith('~')) {
|
|
93
|
+
const home = process.env.HOME || '';
|
|
94
|
+
return path.normalize(path.join(home, dirPath.slice(1)));
|
|
95
|
+
}
|
|
96
|
+
return path.normalize(path.resolve(dirPath));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if a file path is within any of the allowed directories
|
|
100
|
+
*/
|
|
101
|
+
function isPathWithinAllowed(filePath, allowedDirs) {
|
|
102
|
+
const normalizedFilePath = path.normalize(filePath);
|
|
103
|
+
for (const allowedDir of allowedDirs) {
|
|
104
|
+
const normalizedAllowedDir = resolveAllowedDir(allowedDir);
|
|
105
|
+
// Check if file path starts with allowed directory
|
|
106
|
+
// Must either be exact match or have path separator after allowed dir
|
|
107
|
+
if (normalizedFilePath === normalizedAllowedDir) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
// Ensure we check with trailing separator to prevent prefix attacks
|
|
111
|
+
// e.g., /home/user/app should not match /home/user/app-malicious
|
|
112
|
+
const allowedWithSep = normalizedAllowedDir.endsWith(path.sep)
|
|
113
|
+
? normalizedAllowedDir
|
|
114
|
+
: normalizedAllowedDir + path.sep;
|
|
115
|
+
if (normalizedFilePath.startsWith(allowedWithSep)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Extract file path from tool input based on tool type
|
|
123
|
+
*/
|
|
124
|
+
function extractFilePath(toolName, toolInput) {
|
|
125
|
+
// Different tools use different parameter names for file paths
|
|
126
|
+
if (toolName === 'NotebookEdit') {
|
|
127
|
+
return toolInput.notebook_path || null;
|
|
128
|
+
}
|
|
129
|
+
if (toolName === 'Glob' || toolName === 'Grep') {
|
|
130
|
+
// Glob and Grep use 'path' parameter
|
|
131
|
+
return toolInput.path || toolInput.file_path || null;
|
|
132
|
+
}
|
|
133
|
+
// Read, Write, Edit use 'file_path'
|
|
134
|
+
return toolInput.file_path || null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Extract paths from a bash command
|
|
138
|
+
* Returns an array of paths found in the command
|
|
139
|
+
*/
|
|
140
|
+
function extractPathsFromCommand(command, cwd) {
|
|
141
|
+
const paths = [];
|
|
142
|
+
// Regex patterns to match paths
|
|
143
|
+
// Match absolute paths, tilde paths, and relative paths with common extensions
|
|
144
|
+
const pathPatterns = [
|
|
145
|
+
// Absolute paths starting with /
|
|
146
|
+
/(?:^|\s|=|"'`)(\/[^\s;|&><"'`]+)/g,
|
|
147
|
+
// Tilde paths
|
|
148
|
+
/(?:^|\s|=|"'`)(~\/[^\s;|&><"'`]*)/g,
|
|
149
|
+
// Relative paths starting with ./ or ../
|
|
150
|
+
/(?:^|\s|=|"'`)(\.\.[^\s;|&><"'`]*)/g,
|
|
151
|
+
/(?:^|\s|=|"'`)(\.[^\s;|&><"'`]+)/g,
|
|
152
|
+
];
|
|
153
|
+
for (const pattern of pathPatterns) {
|
|
154
|
+
let match;
|
|
155
|
+
while ((match = pattern.exec(command)) !== null) {
|
|
156
|
+
const potentialPath = match[1].trim();
|
|
157
|
+
// Filter out common non-path strings
|
|
158
|
+
if (potentialPath && !potentialPath.match(/^\.(js|ts|json|md|sh)$/)) {
|
|
159
|
+
paths.push(potentialPath);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return paths;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Validate a Bash command against security restrictions
|
|
167
|
+
*/
|
|
168
|
+
function validateBashCommand(command, cwd, allowedDirs) {
|
|
169
|
+
// Check for dangerous commands
|
|
170
|
+
for (const dangerous of DANGEROUS_COMMANDS) {
|
|
171
|
+
if (new RegExp(`\\b${dangerous}\\b`).test(command)) {
|
|
172
|
+
return {
|
|
173
|
+
allowed: false,
|
|
174
|
+
reason: `Command contains blocked keyword: ${dangerous}`
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Check for pipe to shell patterns
|
|
179
|
+
for (const pattern of PIPE_TO_SHELL_PATTERNS) {
|
|
180
|
+
if (pattern.test(command)) {
|
|
181
|
+
return {
|
|
182
|
+
allowed: false,
|
|
183
|
+
reason: 'Command contains dangerous pattern: pipe to shell'
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Extract and validate all paths in the command
|
|
188
|
+
const extractedPaths = extractPathsFromCommand(command, cwd);
|
|
189
|
+
for (const extractedPath of extractedPaths) {
|
|
190
|
+
const resolvedPath = resolvePath(extractedPath, cwd);
|
|
191
|
+
if (!isPathWithinAllowed(resolvedPath, allowedDirs)) {
|
|
192
|
+
return {
|
|
193
|
+
allowed: false,
|
|
194
|
+
reason: `Path "${extractedPath}" is outside allowed directories: ${allowedDirs.join(', ')}`
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
allowed: true,
|
|
200
|
+
reason: 'Command validated successfully'
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Validate tool use against allowed directories
|
|
205
|
+
*
|
|
206
|
+
* @param hookData - Data from Claude Code hook (tool_name, tool_input, etc.)
|
|
207
|
+
* @param allowedDirs - List of allowed directory paths
|
|
208
|
+
* @returns ValidationResult indicating if the operation is allowed
|
|
209
|
+
*/
|
|
210
|
+
function validateToolUse(hookData, allowedDirs) {
|
|
211
|
+
const { tool_name, tool_input, cwd } = hookData;
|
|
212
|
+
// If no restrictions configured, allow everything
|
|
213
|
+
if (!allowedDirs || allowedDirs.length === 0) {
|
|
214
|
+
return {
|
|
215
|
+
allowed: true,
|
|
216
|
+
reason: 'No directory restrictions configured'
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// Handle Bash tool specially
|
|
220
|
+
if (tool_name === 'Bash') {
|
|
221
|
+
if (!tool_input?.command) {
|
|
222
|
+
return {
|
|
223
|
+
allowed: true,
|
|
224
|
+
reason: 'No command in Bash tool input'
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return validateBashCommand(tool_input.command, cwd, allowedDirs);
|
|
228
|
+
}
|
|
229
|
+
// Non-file tools (other than Bash) are allowed by default
|
|
230
|
+
if (!FILE_TOOLS.includes(tool_name)) {
|
|
231
|
+
return {
|
|
232
|
+
allowed: true,
|
|
233
|
+
reason: 'Non-file tool'
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
// Handle missing or undefined tool_input
|
|
237
|
+
if (!tool_input) {
|
|
238
|
+
return {
|
|
239
|
+
allowed: true,
|
|
240
|
+
reason: 'No file path in tool input (undefined input)'
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
// Extract file path from tool input
|
|
244
|
+
const filePath = extractFilePath(tool_name, tool_input);
|
|
245
|
+
if (!filePath) {
|
|
246
|
+
return {
|
|
247
|
+
allowed: true,
|
|
248
|
+
reason: 'No file path in tool input'
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
// Resolve the file path to absolute
|
|
252
|
+
const absolutePath = resolvePath(filePath, cwd);
|
|
253
|
+
// Check if path is within allowed directories
|
|
254
|
+
if (isPathWithinAllowed(absolutePath, allowedDirs)) {
|
|
255
|
+
return {
|
|
256
|
+
allowed: true,
|
|
257
|
+
reason: `Path within allowed directory`
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
allowed: false,
|
|
262
|
+
reason: `Path "${filePath}" is outside allowed directories: ${allowedDirs.join(', ')}`
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Load allowed directories from config file
|
|
267
|
+
* If lastWorkingDirectory is set, use it as the primary allowed directory
|
|
268
|
+
*/
|
|
269
|
+
function loadAllowedDirs(configPath) {
|
|
270
|
+
const effectivePath = configPath ||
|
|
271
|
+
process.env.REMOTE_CLI_CONFIG ||
|
|
272
|
+
path.join(process.env.HOME || '', '.remote-cli', 'config.json');
|
|
273
|
+
try {
|
|
274
|
+
const config = JSON.parse(fs.readFileSync(effectivePath, 'utf8'));
|
|
275
|
+
// If lastWorkingDirectory is set, use it as the primary (and only) allowed directory
|
|
276
|
+
// This ensures security is tied to the current working directory
|
|
277
|
+
if (config.lastWorkingDirectory) {
|
|
278
|
+
return [config.lastWorkingDirectory];
|
|
279
|
+
}
|
|
280
|
+
// Fallback to allowedDirectories if no working directory is set
|
|
281
|
+
return config.security?.allowedDirectories || [];
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Main function when run as a script
|
|
289
|
+
* Reads hook data from stdin and exits with appropriate code
|
|
290
|
+
*/
|
|
291
|
+
async function main() {
|
|
292
|
+
let input = '';
|
|
293
|
+
// Read from stdin
|
|
294
|
+
process.stdin.setEncoding('utf8');
|
|
295
|
+
for await (const chunk of process.stdin) {
|
|
296
|
+
input += chunk;
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
const hookData = JSON.parse(input);
|
|
300
|
+
const allowedDirs = loadAllowedDirs();
|
|
301
|
+
// If no allowed directories are configured, allow everything (fallback)
|
|
302
|
+
if (allowedDirs.length === 0) {
|
|
303
|
+
console.error('[SecurityGuard] Warning: No working directory configured, allowing all operations');
|
|
304
|
+
process.exit(0);
|
|
305
|
+
}
|
|
306
|
+
const result = validateToolUse(hookData, allowedDirs);
|
|
307
|
+
if (!result.allowed) {
|
|
308
|
+
console.error(`[SecurityGuard] Blocked: ${result.reason}`);
|
|
309
|
+
process.exit(2);
|
|
310
|
+
}
|
|
311
|
+
process.exit(0);
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.error(`[SecurityGuard] Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
315
|
+
// Allow on error to avoid blocking legitimate operations
|
|
316
|
+
process.exit(0);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Run main if executed directly
|
|
320
|
+
if (require.main === module) {
|
|
321
|
+
main();
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=security-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-guard.js","sourceRoot":"","sources":["../../src/security/security-guard.ts"],"names":[],"mappings":"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"}
|