@hynaweb/kavlr 0.0.0-stage → 1.0.0
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/bin/cli.js +106 -0
- package/package.json +15 -4
- package/README.md +0 -3
package/bin/cli.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const axios = require('axios');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const readline = require('readline');
|
|
8
|
+
|
|
9
|
+
const API_URL = 'https://yasllkvdrgnqtjesdyfz.supabase.co/functions/v1/intercept';
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0];
|
|
12
|
+
|
|
13
|
+
if (command === 'init') {
|
|
14
|
+
console.log('\x1b[36m%s\x1b[0m', '🛡️ Initializing KAVLR...');
|
|
15
|
+
const shell = process.env.SHELL || '';
|
|
16
|
+
const rcFile = shell.includes('zsh') ? '.zshrc' : '.bashrc';
|
|
17
|
+
const rcPath = path.join(os.homedir(), rcFile);
|
|
18
|
+
|
|
19
|
+
const rl = readline.createInterface({
|
|
20
|
+
input: process.stdin,
|
|
21
|
+
output: process.stdout
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
rl.question('\n\x1b[33mPlease enter your KAVLR API Key: \x1b[0m', (apiKey) => {
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
console.log('\x1b[31m%s\x1b[0m', '❌ API Key is required. Setup aborted.');
|
|
27
|
+
rl.close();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const configStr = `\n# KAVLR Agent Leash\nexport KAVLR_API_KEY="${apiKey}"\nalias rm="kavlr hook rm"\nalias cat="kavlr hook cat"\nalias cp="kavlr hook cp"\nalias mv="kavlr hook mv"\n`;
|
|
32
|
+
|
|
33
|
+
if (fs.existsSync(rcPath)) {
|
|
34
|
+
const content = fs.readFileSync(rcPath, 'utf8');
|
|
35
|
+
if (content.includes('KAVLR Agent Leash') === false) {
|
|
36
|
+
fs.appendFileSync(rcPath, configStr);
|
|
37
|
+
console.log('\n\x1b[32m%s\x1b[0m', '✅ API Key and Hook installed in ~/' + rcFile);
|
|
38
|
+
console.log('\x1b[36m%s\x1b[0m', '👉 Run: source ~/' + rcFile + ' to activate.');
|
|
39
|
+
} else {
|
|
40
|
+
console.log('\n\x1b[32m%s\x1b[0m', '✅ KAVLR is already configured. (If you need to change your key, edit ~/' + rcFile + ')');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
rl.close();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (command === 'hook') {
|
|
50
|
+
const originalCmd = args[1];
|
|
51
|
+
const originalArgs = args.slice(2).join(' ');
|
|
52
|
+
const payload = originalCmd + ' ' + originalArgs;
|
|
53
|
+
|
|
54
|
+
analyzeCommand(payload, true, originalCmd, originalArgs, true);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (command === 'run') {
|
|
59
|
+
const payload = args.slice(1).join(' ');
|
|
60
|
+
analyzeCommand(payload, false, null, null, false);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function analyzeCommand(payload, executeAfter, cmd, cmdArgs, isHook) {
|
|
65
|
+
const API_KEY = process.env.KAVLR_API_KEY;
|
|
66
|
+
|
|
67
|
+
if (API_KEY === undefined) {
|
|
68
|
+
console.error('\x1b[31m%s\x1b[0m', '❌ KAVLR_API_KEY is missing. Run "kavlr init" or export it manually.');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (isHook === false) {
|
|
73
|
+
console.log('\n\x1b[36m%s\x1b[0m', '🔍 KAVLR analyzing: "' + payload + '"...');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const response = await axios.post(API_URL, {
|
|
78
|
+
agent_id: isHook ? 'shell-hook' : 'cli-user',
|
|
79
|
+
action_type: cmd || 'run',
|
|
80
|
+
payload: payload
|
|
81
|
+
}, {
|
|
82
|
+
headers: { 'Authorization': 'Bearer ' + API_KEY }
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (isHook === false) {
|
|
86
|
+
console.log('\x1b[32m%s\x1b[0m', '✅ [ALLOWED] Action permitted.');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (executeAfter) {
|
|
90
|
+
try {
|
|
91
|
+
execSync(cmd + ' ' + cmdArgs, { stdio: 'inherit' });
|
|
92
|
+
} catch (err) {
|
|
93
|
+
process.exit(err.status || 1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error.response && error.response.status === 403) {
|
|
99
|
+
console.error('\x1b[41m\x1b[37m%s\x1b[0m', ' 🛑 [BLOCKED] THREAT DETECTED ');
|
|
100
|
+
console.error('\x1b[31m%s\x1b[0m', 'Reason: ' + error.response.data.message);
|
|
101
|
+
} else {
|
|
102
|
+
console.error('\x1b[31m%s\x1b[0m', '❌ KAVLR API Error. Blocking command for safety.');
|
|
103
|
+
}
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hynaweb/kavlr",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The Agent Leash. Runtime security for AI coding agents.",
|
|
5
|
+
"main": "bin/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"kavlr": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"axios": "^1.6.0"
|
|
14
|
+
},
|
|
15
|
+
"author": "Harun (HYNAWEB)",
|
|
16
|
+
"license": "MIT"
|
|
17
|
+
}
|
package/README.md
DELETED