@hanhnd/agent-kit 1.0.6 → 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/README.md +16 -4
- package/dist/kit-server.js +17 -0
- package/dist/tools/security.d.ts +2 -3
- package/dist/tools/security.js +22 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
| `/ak:brainstorm [idea]` | Strategic architectural analysis |
|
|
12
12
|
| `/ak:plan [file or idea]` | Create an implementation blueprint |
|
|
13
13
|
| `/ak:code [file or task]` | Implement from a plan |
|
|
14
|
+
| `/ak:code-simplify` | Refactor modified code for readability |
|
|
15
|
+
| `/ak:research [topic]` | Research a topic |
|
|
14
16
|
| `/ak:review-pr [PR URL]` | Review a pull request |
|
|
15
17
|
| `/ak:review` | Review uncommitted local changes |
|
|
16
18
|
| `/ak:ticket [ID]` | Fetch a Jira ticket and plan from it |
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
|
|
28
30
|
```bash
|
|
29
31
|
claude plugin marketplace add https://github.com/hanh-nd/agent-kit
|
|
30
|
-
claude plugin install
|
|
32
|
+
claude plugin install ak
|
|
31
33
|
```
|
|
32
34
|
|
|
33
35
|
The plugin fetches from GitHub, registers the MCP server automatically, and makes all commands available immediately.
|
|
@@ -43,8 +45,8 @@ export BITBUCKET_API_TOKEN="your-atlassian-api-token"
|
|
|
43
45
|
export BITBUCKET_DEFAULT_WORKSPACE="your-default-workspace-slug"
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
To update: `claude plugin update
|
|
47
|
-
To uninstall: `claude plugin uninstall
|
|
48
|
+
To update: `claude plugin update ak`
|
|
49
|
+
To uninstall: `claude plugin uninstall ak`
|
|
48
50
|
|
|
49
51
|
---
|
|
50
52
|
|
|
@@ -65,7 +67,7 @@ npm run build
|
|
|
65
67
|
|
|
66
68
|
```bash
|
|
67
69
|
claude plugin marketplace add /absolute/path/to/agent-kit
|
|
68
|
-
claude plugin install
|
|
70
|
+
claude plugin install ak
|
|
69
71
|
```
|
|
70
72
|
|
|
71
73
|
This registers the MCP server automatically (pointing to your local build). Do **not** manually add a `kit-agents` entry to `settings.json` — the plugin handles that.
|
|
@@ -89,6 +91,16 @@ export BITBUCKET_DEFAULT_WORKSPACE="your-default-workspace-slug"
|
|
|
89
91
|
|
|
90
92
|
---
|
|
91
93
|
|
|
94
|
+
### Option 3: Install as Gemini Extension (Optional)
|
|
95
|
+
|
|
96
|
+
If you want to reuse the commands with [Gemini CLI](https://geminicli.com) (for `/ak:delegate` to Gemini), install it using:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
gemini extension install https://github.com/hanh-nd/agent-kit
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
92
104
|
## Development
|
|
93
105
|
|
|
94
106
|
```bash
|
package/dist/kit-server.js
CHANGED
|
@@ -21043,12 +21043,29 @@ import * as path2 from "path";
|
|
|
21043
21043
|
function sanitize(input) {
|
|
21044
21044
|
return String(input).replace(/[;&|`$<>\\]/g, "").trim().slice(0, 500);
|
|
21045
21045
|
}
|
|
21046
|
+
var FORBIDDEN_FILES = [
|
|
21047
|
+
".env",
|
|
21048
|
+
".bashrc",
|
|
21049
|
+
".zshrc",
|
|
21050
|
+
".profile",
|
|
21051
|
+
".bash_profile",
|
|
21052
|
+
".bash_history",
|
|
21053
|
+
".zsh_history",
|
|
21054
|
+
"config.mjs"
|
|
21055
|
+
// Some projects use this for sensitive config
|
|
21056
|
+
];
|
|
21046
21057
|
function validatePath(filePath, baseDir = process.cwd()) {
|
|
21047
21058
|
const resolved = path2.resolve(baseDir, filePath);
|
|
21048
21059
|
const root = path2.resolve(baseDir);
|
|
21049
21060
|
if (resolved !== root && !resolved.startsWith(root + path2.sep)) {
|
|
21050
21061
|
throw new Error(`Path traversal detected: ${filePath}`);
|
|
21051
21062
|
}
|
|
21063
|
+
const fileName = path2.basename(resolved);
|
|
21064
|
+
if (FORBIDDEN_FILES.some(
|
|
21065
|
+
(forbidden) => fileName === forbidden || fileName.startsWith(forbidden + ".")
|
|
21066
|
+
)) {
|
|
21067
|
+
throw new Error(`Access to sensitive file is FORBIDDEN: ${fileName}`);
|
|
21068
|
+
}
|
|
21052
21069
|
return resolved;
|
|
21053
21070
|
}
|
|
21054
21071
|
var GIT_TIMEOUT = parseInt(process.env.GEMINI_KIT_GIT_TIMEOUT || "30000", 10);
|
package/dist/tools/security.d.ts
CHANGED
|
@@ -14,9 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function sanitize(input: string): string;
|
|
16
16
|
/**
|
|
17
|
-
* Validate file path to prevent path traversal attacks
|
|
18
|
-
* Uses stricter path.sep check to prevent prefix matching flaws
|
|
19
|
-
* (e.g., /.geminit-kit/handoffs/app should not match /.geminit-kit/handoffs/app-secret)
|
|
17
|
+
* Validate file path to prevent path traversal attacks and access to forbidden files.
|
|
18
|
+
* Uses stricter path.sep check to prevent prefix matching flaws.
|
|
20
19
|
*/
|
|
21
20
|
export declare function validatePath(filePath: string, baseDir?: string): string;
|
|
22
21
|
/**
|
package/dist/tools/security.js
CHANGED
|
@@ -25,17 +25,35 @@ export function sanitize(input) {
|
|
|
25
25
|
.slice(0, 500); // Limit length
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
28
|
+
* Sensitive files that agents are FORBIDDEN from reading/writing.
|
|
29
|
+
* Includes environment variables, shell configs, and system profiles.
|
|
30
|
+
*/
|
|
31
|
+
const FORBIDDEN_FILES = [
|
|
32
|
+
'.env',
|
|
33
|
+
'.bashrc',
|
|
34
|
+
'.zshrc',
|
|
35
|
+
'.profile',
|
|
36
|
+
'.bash_profile',
|
|
37
|
+
'.bash_history',
|
|
38
|
+
'.zsh_history',
|
|
39
|
+
'config.mjs', // Some projects use this for sensitive config
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Validate file path to prevent path traversal attacks and access to forbidden files.
|
|
43
|
+
* Uses stricter path.sep check to prevent prefix matching flaws.
|
|
31
44
|
*/
|
|
32
45
|
export function validatePath(filePath, baseDir = process.cwd()) {
|
|
33
46
|
const resolved = path.resolve(baseDir, filePath);
|
|
34
47
|
const root = path.resolve(baseDir);
|
|
35
|
-
//
|
|
48
|
+
// 1. Path traversal check
|
|
36
49
|
if (resolved !== root && !resolved.startsWith(root + path.sep)) {
|
|
37
50
|
throw new Error(`Path traversal detected: ${filePath}`);
|
|
38
51
|
}
|
|
52
|
+
// 2. Forbidden files check (exact filename or suffix)
|
|
53
|
+
const fileName = path.basename(resolved);
|
|
54
|
+
if (FORBIDDEN_FILES.some((forbidden) => fileName === forbidden || fileName.startsWith(forbidden + '.'))) {
|
|
55
|
+
throw new Error(`Access to sensitive file is FORBIDDEN: ${fileName}`);
|
|
56
|
+
}
|
|
39
57
|
return resolved;
|
|
40
58
|
}
|
|
41
59
|
/**
|