@manuelstolze/pi-permission-gate 0.2.0 → 0.2.1
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/application/ports/permission-approval-port.d.ts +15 -0
- package/dist/application/ports/permission-approval-port.js +2 -0
- package/dist/application/ports/permission-approval-port.js.map +1 -0
- package/dist/application/ports/permission-config-port.d.ts +14 -0
- package/dist/application/ports/permission-config-port.js +2 -0
- package/dist/application/ports/permission-config-port.js.map +1 -0
- package/dist/application/ports/session-approvals-port.d.ts +5 -0
- package/dist/application/ports/session-approvals-port.js +2 -0
- package/dist/application/ports/session-approvals-port.js.map +1 -0
- package/dist/application/use-cases/permission-gate.d.ts +27 -0
- package/dist/application/use-cases/permission-gate.js +58 -0
- package/dist/application/use-cases/permission-gate.js.map +1 -0
- package/dist/domain/patterns.d.ts +7 -0
- package/dist/domain/patterns.js +15 -0
- package/dist/domain/patterns.js.map +1 -0
- package/dist/domain/permission-rules.d.ts +17 -0
- package/dist/domain/permission-rules.js +41 -0
- package/dist/domain/permission-rules.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -107
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/config/file-permission-config-adapter.d.ts +9 -0
- package/dist/infrastructure/config/file-permission-config-adapter.js +94 -0
- package/dist/infrastructure/config/file-permission-config-adapter.js.map +1 -0
- package/dist/{dialog.js → interface/pi/dialog.js} +2 -2
- package/dist/interface/pi/dialog.js.map +1 -0
- package/dist/interface/pi/extension.d.ts +3 -0
- package/dist/interface/pi/extension.js +56 -0
- package/dist/interface/pi/extension.js.map +1 -0
- package/dist/interface/pi/permission-approval-adapter.d.ts +16 -0
- package/dist/interface/pi/permission-approval-adapter.js +47 -0
- package/dist/interface/pi/permission-approval-adapter.js.map +1 -0
- package/dist/interface/pi/session-approvals.d.ts +7 -0
- package/dist/interface/pi/session-approvals.js +13 -0
- package/dist/interface/pi/session-approvals.js.map +1 -0
- package/package.json +1 -1
- package/dist/config.d.ts +0 -21
- package/dist/config.js +0 -106
- package/dist/config.js.map +0 -1
- package/dist/dialog.js.map +0 -1
- package/dist/rules.d.ts +0 -6
- package/dist/rules.js +0 -16
- package/dist/rules.js.map +0 -1
- /package/dist/{dialog.d.ts → interface/pi/dialog.d.ts} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type PermissionApprovalResult = {
|
|
2
|
+
kind: "allow-once";
|
|
3
|
+
} | {
|
|
4
|
+
kind: "allow-session";
|
|
5
|
+
} | {
|
|
6
|
+
kind: "allow-forever";
|
|
7
|
+
} | {
|
|
8
|
+
kind: "deny";
|
|
9
|
+
instruction?: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "unavailable";
|
|
12
|
+
};
|
|
13
|
+
export interface PermissionApprovalPort {
|
|
14
|
+
request(command: string, description: string): Promise<PermissionApprovalResult>;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-approval-port.js","sourceRoot":"","sources":["../../../src/application/ports/permission-approval-port.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CommandPattern } from "../../domain/patterns.js";
|
|
2
|
+
export interface PermissionGateConfiguration {
|
|
3
|
+
applyBuiltinDefaults?: boolean;
|
|
4
|
+
dangerousPatterns?: CommandPattern[];
|
|
5
|
+
allowedPatterns?: CommandPattern[];
|
|
6
|
+
}
|
|
7
|
+
export interface PermissionConfigLoadResult {
|
|
8
|
+
configuration: PermissionGateConfiguration;
|
|
9
|
+
error?: Error;
|
|
10
|
+
}
|
|
11
|
+
export interface PermissionConfigPort {
|
|
12
|
+
load(): PermissionConfigLoadResult;
|
|
13
|
+
saveExactAllowRule(command: string): CommandPattern;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-config-port.js","sourceRoot":"","sources":["../../../src/application/ports/permission-config-port.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-approvals-port.js","sourceRoot":"","sources":["../../../src/application/ports/session-approvals-port.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PermissionApprovalPort } from "../ports/permission-approval-port.js";
|
|
2
|
+
import type { PermissionConfigPort } from "../ports/permission-config-port.js";
|
|
3
|
+
import type { SessionApprovalsPort } from "../ports/session-approvals-port.js";
|
|
4
|
+
export type PermissionGateOutcome = {
|
|
5
|
+
kind: "allow";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "allow-forever";
|
|
8
|
+
command: string;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "auto-deny";
|
|
11
|
+
pattern: string;
|
|
12
|
+
reason: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "approval-unavailable";
|
|
15
|
+
description: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "user-deny";
|
|
18
|
+
instruction?: string;
|
|
19
|
+
} | {
|
|
20
|
+
kind: "permanent-allow-failed";
|
|
21
|
+
error: Error;
|
|
22
|
+
};
|
|
23
|
+
export interface PermissionGate {
|
|
24
|
+
startSession(): Error | undefined;
|
|
25
|
+
handleCommand(command: string, approval: PermissionApprovalPort): Promise<PermissionGateOutcome>;
|
|
26
|
+
}
|
|
27
|
+
export declare function createPermissionGate(config: PermissionConfigPort, sessionApprovals: SessionApprovalsPort): PermissionGate;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BUILTIN_DANGEROUS_PATTERNS, evaluateCommand } from "../../domain/permission-rules.js";
|
|
2
|
+
export function createPermissionGate(config, sessionApprovals) {
|
|
3
|
+
let allowedPatterns = [];
|
|
4
|
+
let dangerousPatterns = [];
|
|
5
|
+
function startSession() {
|
|
6
|
+
sessionApprovals.clear();
|
|
7
|
+
const result = config.load();
|
|
8
|
+
const settings = result.error ? {} : result.configuration;
|
|
9
|
+
const applyBuiltinDefaults = settings.applyBuiltinDefaults !== false;
|
|
10
|
+
dangerousPatterns = applyBuiltinDefaults
|
|
11
|
+
? [...(settings.dangerousPatterns ?? []), ...BUILTIN_DANGEROUS_PATTERNS]
|
|
12
|
+
: (settings.dangerousPatterns ?? []);
|
|
13
|
+
allowedPatterns = settings.allowedPatterns ?? [];
|
|
14
|
+
return result.error;
|
|
15
|
+
}
|
|
16
|
+
async function handleCommand(command, approval) {
|
|
17
|
+
const evaluation = evaluateCommand(command, sessionApprovals.has(command), allowedPatterns, dangerousPatterns);
|
|
18
|
+
if (evaluation.kind === "auto-deny") {
|
|
19
|
+
return {
|
|
20
|
+
kind: "auto-deny",
|
|
21
|
+
pattern: evaluation.rule.pattern,
|
|
22
|
+
reason: evaluation.rule.reason,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (evaluation.kind === "allow")
|
|
26
|
+
return { kind: "allow" };
|
|
27
|
+
const description = evaluation.pattern.description ?? evaluation.pattern.pattern;
|
|
28
|
+
const result = await approval.request(command, description);
|
|
29
|
+
if (result.kind === "unavailable") {
|
|
30
|
+
return { kind: "approval-unavailable", description };
|
|
31
|
+
}
|
|
32
|
+
if (result.kind === "allow-once")
|
|
33
|
+
return { kind: "allow" };
|
|
34
|
+
if (result.kind === "allow-session") {
|
|
35
|
+
sessionApprovals.allow(command);
|
|
36
|
+
return { kind: "allow" };
|
|
37
|
+
}
|
|
38
|
+
if (result.kind === "allow-forever") {
|
|
39
|
+
try {
|
|
40
|
+
const rule = config.saveExactAllowRule(command);
|
|
41
|
+
if (!allowedPatterns.some((item) => item.pattern === rule.pattern && item.regex === true)) {
|
|
42
|
+
allowedPatterns.push(rule);
|
|
43
|
+
}
|
|
44
|
+
return { kind: "allow-forever", command };
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
kind: "permanent-allow-failed",
|
|
49
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const instruction = result.instruction?.trim();
|
|
54
|
+
return instruction ? { kind: "user-deny", instruction } : { kind: "user-deny" };
|
|
55
|
+
}
|
|
56
|
+
return { startSession, handleCommand };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=permission-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-gate.js","sourceRoot":"","sources":["../../../src/application/use-cases/permission-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface CommandPattern {
|
|
2
|
+
pattern: string;
|
|
3
|
+
regex?: boolean;
|
|
4
|
+
description?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function matchesCommandPattern(pattern: CommandPattern, command: string): boolean;
|
|
7
|
+
export declare function findCommandPattern(command: string, patterns: CommandPattern[]): CommandPattern | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function matchesCommandPattern(pattern, command) {
|
|
2
|
+
if (pattern.regex) {
|
|
3
|
+
try {
|
|
4
|
+
return new RegExp(pattern.pattern).test(command);
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return command.includes(pattern.pattern);
|
|
11
|
+
}
|
|
12
|
+
export function findCommandPattern(command, patterns) {
|
|
13
|
+
return patterns.find((pattern) => matchesCommandPattern(pattern, command));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/domain/patterns.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,qBAAqB,CAAC,OAAuB,EAAE,OAAe;IAC5E,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,QAA0B;IAE1B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CommandPattern } from "./patterns.js";
|
|
2
|
+
export interface AutoDenyRule {
|
|
3
|
+
pattern: string;
|
|
4
|
+
reason: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const AUTO_DENY_RULES: AutoDenyRule[];
|
|
7
|
+
export declare const BUILTIN_DANGEROUS_PATTERNS: CommandPattern[];
|
|
8
|
+
export type CommandEvaluation = {
|
|
9
|
+
kind: "auto-deny";
|
|
10
|
+
rule: AutoDenyRule;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "allow";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "requires-approval";
|
|
15
|
+
pattern: CommandPattern;
|
|
16
|
+
};
|
|
17
|
+
export declare function evaluateCommand(command: string, sessionAllowed: boolean, allowedPatterns: CommandPattern[], dangerousPatterns: CommandPattern[]): CommandEvaluation;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { findCommandPattern } from "./patterns.js";
|
|
2
|
+
export const AUTO_DENY_RULES = [
|
|
3
|
+
{ pattern: "az group delete", reason: "deletes an entire Azure resource group and all its resources" },
|
|
4
|
+
{ pattern: "az subscription cancel", reason: "cancels the entire Azure subscription" },
|
|
5
|
+
{ pattern: "az account management-group delete", reason: "deletes Azure management group hierarchy" },
|
|
6
|
+
{ pattern: "az ad user delete", reason: "deletes an Azure AD user" },
|
|
7
|
+
{ pattern: "az ad group delete", reason: "deletes an Azure AD security group" },
|
|
8
|
+
{ pattern: "az lock delete", reason: "removes an Azure resource lock (enables further destruction)" },
|
|
9
|
+
{ pattern: "az keyvault purge", reason: "permanently purges a Key Vault, bypassing soft-delete" },
|
|
10
|
+
{ pattern: "kubectl delete namespace", reason: "deletes a Kubernetes namespace and all resources inside" },
|
|
11
|
+
{ pattern: "kubectl delete --all", reason: "deletes all Kubernetes resources of a type" },
|
|
12
|
+
{ pattern: "kubectl drain", reason: "evicts all pods from a Kubernetes node" },
|
|
13
|
+
];
|
|
14
|
+
export const BUILTIN_DANGEROUS_PATTERNS = [
|
|
15
|
+
{ pattern: "rm -rf", description: "recursive force delete" },
|
|
16
|
+
{ pattern: "sudo", description: "superuser command" },
|
|
17
|
+
{ pattern: "dd of=", description: "disk write operation" },
|
|
18
|
+
{ pattern: "mkfs.", description: "filesystem format" },
|
|
19
|
+
{ pattern: "chmod -R 777", description: "insecure recursive permissions" },
|
|
20
|
+
{ pattern: "chown -R", description: "recursive ownership change" },
|
|
21
|
+
{ pattern: "doas", description: "privileged command execution" },
|
|
22
|
+
{ pattern: "pkexec", description: "privileged command execution" },
|
|
23
|
+
{ pattern: "shred", description: "secure file overwrite" },
|
|
24
|
+
{ pattern: "wipefs", description: "filesystem signature wipe" },
|
|
25
|
+
{ pattern: "blkdiscard", description: "block device discard" },
|
|
26
|
+
{ pattern: "fdisk", description: "disk partitioning" },
|
|
27
|
+
{ pattern: "parted", description: "disk partitioning" },
|
|
28
|
+
{ pattern: "docker run --privileged", description: "container with privileged mode" },
|
|
29
|
+
];
|
|
30
|
+
export function evaluateCommand(command, sessionAllowed, allowedPatterns, dangerousPatterns) {
|
|
31
|
+
const autoDenyRule = AUTO_DENY_RULES.find((rule) => command.includes(rule.pattern));
|
|
32
|
+
if (autoDenyRule)
|
|
33
|
+
return { kind: "auto-deny", rule: autoDenyRule };
|
|
34
|
+
if (sessionAllowed || findCommandPattern(command, allowedPatterns))
|
|
35
|
+
return { kind: "allow" };
|
|
36
|
+
const dangerousPattern = findCommandPattern(command, dangerousPatterns);
|
|
37
|
+
return dangerousPattern
|
|
38
|
+
? { kind: "requires-approval", pattern: dangerousPattern }
|
|
39
|
+
: { kind: "allow" };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=permission-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-rules.js","sourceRoot":"","sources":["../../src/domain/permission-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAuB,MAAM,eAAe,CAAC;AAOxE,MAAM,CAAC,MAAM,eAAe,GAAmB;IAC7C,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,8DAA8D,EAAE;IACtG,EAAE,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,uCAAuC,EAAE;IACtF,EAAE,OAAO,EAAE,oCAAoC,EAAE,MAAM,EAAE,0CAA0C,EAAE;IACrG,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,0BAA0B,EAAE;IACpE,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,oCAAoC,EAAE;IAC/E,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,8DAA8D,EAAE;IACrG,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,uDAAuD,EAAE;IACjG,EAAE,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,yDAAyD,EAAE;IAC1G,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,EAAE,4CAA4C,EAAE;IACzF,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,wCAAwC,EAAE;CAC/E,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IAC1D,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACrD,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;IAC1D,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACtD,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,gCAAgC,EAAE;IAC1E,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAClE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,8BAA8B,EAAE;IAChE,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;IAClE,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE;IAC1D,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE;IAC/D,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,sBAAsB,EAAE;IAC9D,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACtD,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACvD,EAAE,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,gCAAgC,EAAE;CACtF,CAAC;AAOF,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,cAAuB,EACvB,eAAiC,EACjC,iBAAmC;IAEnC,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpF,IAAI,YAAY;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAEnE,IAAI,cAAc,IAAI,kBAAkB,CAAC,OAAO,EAAE,eAAe,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAE7F,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACxE,OAAO,gBAAgB;QACrB,CAAC,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,EAAE;QAC1D,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACxB,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,111 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { createPermissionGate } from "./application/use-cases/permission-gate.js";
|
|
2
|
+
import { FilePermissionConfigAdapter } from "./infrastructure/config/file-permission-config-adapter.js";
|
|
3
|
+
import { registerPermissionGate } from "./interface/pi/extension.js";
|
|
4
|
+
import { InMemorySessionApprovals } from "./interface/pi/session-approvals.js";
|
|
5
5
|
const permissionGate = (pi) => {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
let dangerPatterns = [];
|
|
9
|
-
let configError;
|
|
10
|
-
function reportPermissionGate(active, label) {
|
|
11
|
-
if (process.env.HERDR_ENV !== "1")
|
|
12
|
-
return;
|
|
13
|
-
pi.events.emit("herdr:blocked", { active, label });
|
|
14
|
-
}
|
|
15
|
-
function loadConfig() {
|
|
16
|
-
sessionAllowedCommands.clear();
|
|
17
|
-
const result = readConfig();
|
|
18
|
-
configError = result.error;
|
|
19
|
-
const config = result.error ? {} : result.config;
|
|
20
|
-
const applyDefaults = config.applyBuiltinDefaults !== false;
|
|
21
|
-
const customPatterns = config.permissionGate?.patterns ?? [];
|
|
22
|
-
dangerPatterns = applyDefaults ? [...customPatterns, ...BUILTIN_PATTERNS] : customPatterns;
|
|
23
|
-
allowedPatterns = config.permissionGate?.allowedPatterns ?? [];
|
|
24
|
-
}
|
|
25
|
-
pi.on("session_start", (_event, ctx) => {
|
|
26
|
-
loadConfig();
|
|
27
|
-
if (configError) {
|
|
28
|
-
ctx.ui.notify(`Could not read guardrails.json. Using built-in dangerous-command patterns. ${configError.message}`, "warning");
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
pi.on("tool_call", async (event, ctx) => {
|
|
32
|
-
if (!isToolCallEventType("bash", event))
|
|
33
|
-
return;
|
|
34
|
-
const command = event.input.command;
|
|
35
|
-
// Auto-deny checks must run first. Config allow rules cannot override them.
|
|
36
|
-
const autoDeny = findAutoDenyMatch(command);
|
|
37
|
-
if (autoDeny) {
|
|
38
|
-
ctx.ui.notify(`Auto-blocked: ${autoDeny.pattern} — ${autoDeny.reason}`, "error");
|
|
39
|
-
return { block: true, reason: `Catastrophic command auto-blocked: ${autoDeny.reason}` };
|
|
40
|
-
}
|
|
41
|
-
if (sessionAllowedCommands.has(command))
|
|
42
|
-
return;
|
|
43
|
-
if (allowedPatterns.some((pattern) => testPattern(pattern, command)))
|
|
44
|
-
return;
|
|
45
|
-
const match = findPattern(command, dangerPatterns);
|
|
46
|
-
if (!match)
|
|
47
|
-
return;
|
|
48
|
-
const description = match.description ?? match.pattern;
|
|
49
|
-
if (!ctx.hasUI) {
|
|
50
|
-
return {
|
|
51
|
-
block: true,
|
|
52
|
-
reason: `Dangerous command blocked (no UI to confirm): ${description}`,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
reportPermissionGate(true, `Permission gate: ${description}`);
|
|
56
|
-
try {
|
|
57
|
-
let result = await ctx.ui.custom(createDialog(command, description));
|
|
58
|
-
// RPC and headless UI contexts can return undefined for custom dialogs.
|
|
59
|
-
if (result === undefined) {
|
|
60
|
-
const selection = await ctx.ui.select(`Dangerous command: ${description}`, [
|
|
61
|
-
"1 - Allow once",
|
|
62
|
-
"2 - Allow this session",
|
|
63
|
-
"3 - Allow forever",
|
|
64
|
-
"4 - Deny (tell pi what to do instead)",
|
|
65
|
-
]);
|
|
66
|
-
if (selection?.startsWith("1"))
|
|
67
|
-
result = "allow-once";
|
|
68
|
-
else if (selection?.startsWith("2"))
|
|
69
|
-
result = "allow-session";
|
|
70
|
-
else if (selection?.startsWith("3"))
|
|
71
|
-
result = "allow-forever";
|
|
72
|
-
else
|
|
73
|
-
result = "deny";
|
|
74
|
-
}
|
|
75
|
-
if (result === "allow-once")
|
|
76
|
-
return;
|
|
77
|
-
if (result === "allow-session") {
|
|
78
|
-
sessionAllowedCommands.add(command);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (result === "allow-forever") {
|
|
82
|
-
try {
|
|
83
|
-
const rule = writeExactAllowRule(command);
|
|
84
|
-
if (!allowedPatterns.some((item) => item.pattern === rule.pattern && item.regex === true)) {
|
|
85
|
-
allowedPatterns.push(rule);
|
|
86
|
-
}
|
|
87
|
-
ctx.ui.notify(`Added an exact command to the global allowlist: ${command.slice(0, 60)}${command.length > 60 ? "…" : ""}`, "info");
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
92
|
-
ctx.ui.notify(`Could not save the allow rule. Command remains blocked. ${message}`, "error");
|
|
93
|
-
return { block: true, reason: "Could not save the permanent allow rule" };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const instruction = await ctx.ui.input("Tell pi what to do instead:", "");
|
|
97
|
-
if (instruction?.trim()) {
|
|
98
|
-
pi.sendUserMessage(`The command \`${command}\` was blocked. Please do the following instead: ${instruction.trim()}`, { deliverAs: "steer" });
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
ctx.ui.notify("Command blocked.", "error");
|
|
102
|
-
}
|
|
103
|
-
return { block: true, reason: "User denied dangerous command" };
|
|
104
|
-
}
|
|
105
|
-
finally {
|
|
106
|
-
reportPermissionGate(false);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
6
|
+
const gate = createPermissionGate(new FilePermissionConfigAdapter(), new InMemorySessionApprovals());
|
|
7
|
+
registerPermissionGate(pi, gate);
|
|
109
8
|
};
|
|
110
9
|
export default permissionGate;
|
|
111
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,2DAA2D,CAAC;AACxG,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAE/E,MAAM,cAAc,GAAqB,CAAC,EAAE,EAAE,EAAE;IAC9C,MAAM,IAAI,GAAG,oBAAoB,CAC/B,IAAI,2BAA2B,EAAE,EACjC,IAAI,wBAAwB,EAAE,CAC/B,CAAC;IACF,sBAAsB,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PermissionConfigLoadResult, PermissionConfigPort } from "../../application/ports/permission-config-port.js";
|
|
2
|
+
import type { CommandPattern } from "../../domain/patterns.js";
|
|
3
|
+
export declare function getConfigPath(): string;
|
|
4
|
+
export declare class FilePermissionConfigAdapter implements PermissionConfigPort {
|
|
5
|
+
private readonly path;
|
|
6
|
+
constructor(path?: string);
|
|
7
|
+
load(): PermissionConfigLoadResult;
|
|
8
|
+
saveExactAllowRule(command: string): CommandPattern;
|
|
9
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export function getConfigPath() {
|
|
5
|
+
return join(homedir(), ".pi", "agent", "extensions", "guardrails.json");
|
|
6
|
+
}
|
|
7
|
+
export class FilePermissionConfigAdapter {
|
|
8
|
+
path;
|
|
9
|
+
constructor(path = getConfigPath()) {
|
|
10
|
+
this.path = path;
|
|
11
|
+
}
|
|
12
|
+
load() {
|
|
13
|
+
const result = readStoredConfig(this.path);
|
|
14
|
+
if (result.error)
|
|
15
|
+
return { configuration: {}, error: result.error };
|
|
16
|
+
return {
|
|
17
|
+
configuration: {
|
|
18
|
+
applyBuiltinDefaults: result.config.applyBuiltinDefaults,
|
|
19
|
+
dangerousPatterns: result.config.permissionGate?.patterns,
|
|
20
|
+
allowedPatterns: result.config.permissionGate?.allowedPatterns,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
saveExactAllowRule(command) {
|
|
25
|
+
const result = readStoredConfig(this.path);
|
|
26
|
+
if (result.error) {
|
|
27
|
+
throw new Error(`Cannot update invalid guardrails config: ${result.error.message}`);
|
|
28
|
+
}
|
|
29
|
+
const config = result.config;
|
|
30
|
+
const permissionGate = config.permissionGate ?? {};
|
|
31
|
+
const allowedPatterns = permissionGate.allowedPatterns ?? [];
|
|
32
|
+
const rule = { pattern: `^${escapeRegex(command)}$`, regex: true };
|
|
33
|
+
if (!allowedPatterns.some((item) => item.pattern === rule.pattern && item.regex === true)) {
|
|
34
|
+
allowedPatterns.push(rule);
|
|
35
|
+
}
|
|
36
|
+
config.permissionGate = { ...permissionGate, allowedPatterns };
|
|
37
|
+
mkdirSync(dirname(this.path), { recursive: true });
|
|
38
|
+
writeFileSync(this.path, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
|
|
39
|
+
return rule;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function readStoredConfig(path) {
|
|
43
|
+
let content;
|
|
44
|
+
try {
|
|
45
|
+
content = readFileSync(path, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
49
|
+
return { config: {} };
|
|
50
|
+
return { config: {}, error: asError(error) };
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(content);
|
|
54
|
+
if (!isGuardrailsConfig(parsed))
|
|
55
|
+
throw new Error("guardrails.json has an invalid structure");
|
|
56
|
+
return { config: parsed };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return { config: {}, error: asError(error) };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function escapeRegex(value) {
|
|
63
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
64
|
+
}
|
|
65
|
+
function isGuardrailsConfig(value) {
|
|
66
|
+
if (!isRecord(value))
|
|
67
|
+
return false;
|
|
68
|
+
if (value.applyBuiltinDefaults !== undefined && typeof value.applyBuiltinDefaults !== "boolean")
|
|
69
|
+
return false;
|
|
70
|
+
if (value.permissionGate === undefined)
|
|
71
|
+
return true;
|
|
72
|
+
if (!isRecord(value.permissionGate))
|
|
73
|
+
return false;
|
|
74
|
+
return isPatternList(value.permissionGate.patterns) && isPatternList(value.permissionGate.allowedPatterns);
|
|
75
|
+
}
|
|
76
|
+
function isPatternList(value) {
|
|
77
|
+
return value === undefined || (Array.isArray(value) && value.every(isPatternConfig));
|
|
78
|
+
}
|
|
79
|
+
function isPatternConfig(value) {
|
|
80
|
+
return (isRecord(value) &&
|
|
81
|
+
typeof value.pattern === "string" &&
|
|
82
|
+
(value.regex === undefined || typeof value.regex === "boolean") &&
|
|
83
|
+
(value.description === undefined || typeof value.description === "string"));
|
|
84
|
+
}
|
|
85
|
+
function isRecord(value) {
|
|
86
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
87
|
+
}
|
|
88
|
+
function isNodeError(error) {
|
|
89
|
+
return error instanceof Error && "code" in error;
|
|
90
|
+
}
|
|
91
|
+
function asError(error) {
|
|
92
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=file-permission-config-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-permission-config-adapter.js","sourceRoot":"","sources":["../../../src/infrastructure/config/file-permission-config-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DynamicBorder
|
|
2
|
-
import { Container, Key, Spacer, Text, matchesKey, wrapTextWithAnsi
|
|
1
|
+
import { DynamicBorder } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { Container, Key, Spacer, Text, matchesKey, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
3
3
|
const OPTIONS = [
|
|
4
4
|
{ label: "Allow once", result: "allow-once" },
|
|
5
5
|
{ label: "Allow this session", result: "allow-session" },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../../src/interface/pi/dialog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isToolCallEventType } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { PiPermissionApprovalAdapter } from "./permission-approval-adapter.js";
|
|
3
|
+
export function registerPermissionGate(pi, gate) {
|
|
4
|
+
function reportPermissionGate(active, label) {
|
|
5
|
+
if (process.env.HERDR_ENV !== "1")
|
|
6
|
+
return;
|
|
7
|
+
pi.events.emit("herdr:blocked", { active, label });
|
|
8
|
+
}
|
|
9
|
+
pi.on("session_start", (_event, context) => {
|
|
10
|
+
const configError = gate.startSession();
|
|
11
|
+
if (configError) {
|
|
12
|
+
context.ui.notify(`Could not read guardrails.json. Using built-in dangerous-command patterns. ${configError.message}`, "warning");
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
pi.on("tool_call", async (event, context) => {
|
|
16
|
+
if (!isToolCallEventType("bash", event))
|
|
17
|
+
return;
|
|
18
|
+
const command = event.input.command;
|
|
19
|
+
const approval = new PiPermissionApprovalAdapter({
|
|
20
|
+
hasUI: context.hasUI,
|
|
21
|
+
custom: (dialog) => context.ui.custom(dialog),
|
|
22
|
+
select: (title, choices) => context.ui.select(title, choices),
|
|
23
|
+
input: (prompt, defaultValue) => context.ui.input(prompt, defaultValue),
|
|
24
|
+
}, (description) => reportPermissionGate(true, `Permission gate: ${description}`), () => reportPermissionGate(false));
|
|
25
|
+
const outcome = await gate.handleCommand(command, approval);
|
|
26
|
+
switch (outcome.kind) {
|
|
27
|
+
case "allow":
|
|
28
|
+
return;
|
|
29
|
+
case "allow-forever":
|
|
30
|
+
context.ui.notify(`Added an exact command to the global allowlist: ${outcome.command.slice(0, 60)}${outcome.command.length > 60 ? "…" : ""}`, "info");
|
|
31
|
+
return;
|
|
32
|
+
case "auto-deny":
|
|
33
|
+
context.ui.notify(`Auto-blocked: ${outcome.pattern} — ${outcome.reason}`, "error");
|
|
34
|
+
return { block: true, reason: `Catastrophic command auto-blocked: ${outcome.reason}` };
|
|
35
|
+
case "approval-unavailable":
|
|
36
|
+
return {
|
|
37
|
+
block: true,
|
|
38
|
+
reason: `Dangerous command blocked (no UI to confirm): ${outcome.description}`,
|
|
39
|
+
};
|
|
40
|
+
case "user-deny":
|
|
41
|
+
if (outcome.instruction) {
|
|
42
|
+
pi.sendUserMessage(`The command \`${command}\` was blocked. Please do the following instead: ${outcome.instruction}`, { deliverAs: "steer" });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
context.ui.notify("Command blocked.", "error");
|
|
46
|
+
}
|
|
47
|
+
return { block: true, reason: "User denied dangerous command" };
|
|
48
|
+
case "permanent-allow-failed": {
|
|
49
|
+
const message = outcome.error.message;
|
|
50
|
+
context.ui.notify(`Could not save the allow rule. Command remains blocked. ${message}`, "error");
|
|
51
|
+
return { block: true, reason: "Could not save the permanent allow rule" };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../src/interface/pi/extension.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PermissionApprovalPort, PermissionApprovalResult } from "../../application/ports/permission-approval-port.js";
|
|
2
|
+
import { createDialog, type ConfirmResult } from "./dialog.js";
|
|
3
|
+
interface PiApprovalContext {
|
|
4
|
+
hasUI: boolean;
|
|
5
|
+
custom(dialog: ReturnType<typeof createDialog>): Promise<ConfirmResult | undefined>;
|
|
6
|
+
select(title: string, choices: string[]): Promise<string | undefined>;
|
|
7
|
+
input(prompt: string, defaultValue?: string): Promise<string | undefined>;
|
|
8
|
+
}
|
|
9
|
+
export declare class PiPermissionApprovalAdapter implements PermissionApprovalPort {
|
|
10
|
+
private readonly context;
|
|
11
|
+
private readonly reportActive;
|
|
12
|
+
private readonly reportInactive;
|
|
13
|
+
constructor(context: PiApprovalContext, reportActive: (description: string) => void, reportInactive: () => void);
|
|
14
|
+
request(command: string, description: string): Promise<PermissionApprovalResult>;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createDialog } from "./dialog.js";
|
|
2
|
+
export class PiPermissionApprovalAdapter {
|
|
3
|
+
context;
|
|
4
|
+
reportActive;
|
|
5
|
+
reportInactive;
|
|
6
|
+
constructor(context, reportActive, reportInactive) {
|
|
7
|
+
this.context = context;
|
|
8
|
+
this.reportActive = reportActive;
|
|
9
|
+
this.reportInactive = reportInactive;
|
|
10
|
+
}
|
|
11
|
+
async request(command, description) {
|
|
12
|
+
if (!this.context.hasUI)
|
|
13
|
+
return { kind: "unavailable" };
|
|
14
|
+
this.reportActive(description);
|
|
15
|
+
try {
|
|
16
|
+
let result = await this.context.custom(createDialog(command, description));
|
|
17
|
+
// RPC and headless UI contexts can return undefined for custom dialogs.
|
|
18
|
+
if (result === undefined) {
|
|
19
|
+
const selection = await this.context.select(`Dangerous command: ${description}`, [
|
|
20
|
+
"1 - Allow once",
|
|
21
|
+
"2 - Allow this session",
|
|
22
|
+
"3 - Allow forever",
|
|
23
|
+
"4 - Deny (tell pi what to do instead)",
|
|
24
|
+
]);
|
|
25
|
+
if (selection?.startsWith("1"))
|
|
26
|
+
result = "allow-once";
|
|
27
|
+
else if (selection?.startsWith("2"))
|
|
28
|
+
result = "allow-session";
|
|
29
|
+
else if (selection?.startsWith("3"))
|
|
30
|
+
result = "allow-forever";
|
|
31
|
+
else
|
|
32
|
+
result = "deny";
|
|
33
|
+
}
|
|
34
|
+
if (result === "allow-once")
|
|
35
|
+
return { kind: "allow-once" };
|
|
36
|
+
if (result === "allow-session")
|
|
37
|
+
return { kind: "allow-session" };
|
|
38
|
+
if (result === "allow-forever")
|
|
39
|
+
return { kind: "allow-forever" };
|
|
40
|
+
return { kind: "deny", instruction: await this.context.input("Tell pi what to do instead:", "") };
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
this.reportInactive();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=permission-approval-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-approval-adapter.js","sourceRoot":"","sources":["../../../src/interface/pi/permission-approval-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAsB,MAAM,aAAa,CAAC;AAS/D,MAAM,OAAO,2BAA2B;IAEnB,OAAO;IACP,YAAY;IACZ,cAAc;IAHjC,YACmB,OAA0B,EAC1B,YAA2C,EAC3C,cAA0B;uBAF1B,OAAO;4BACP,YAAY;8BACZ,cAAc;IAC9B,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,WAAmB;QAChD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAExD,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;YAE3E,wEAAwE;YACxE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,WAAW,EAAE,EAAE;oBAC/E,gBAAgB;oBAChB,wBAAwB;oBACxB,mBAAmB;oBACnB,uCAAuC;iBACxC,CAAC,CAAC;gBACH,IAAI,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC;oBAAE,MAAM,GAAG,YAAY,CAAC;qBACjD,IAAI,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC;oBAAE,MAAM,GAAG,eAAe,CAAC;qBACzD,IAAI,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC;oBAAE,MAAM,GAAG,eAAe,CAAC;;oBACzD,MAAM,GAAG,MAAM,CAAC;YACvB,CAAC;YAED,IAAI,MAAM,KAAK,YAAY;gBAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;YAC3D,IAAI,MAAM,KAAK,eAAe;gBAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;YACjE,IAAI,MAAM,KAAK,eAAe;gBAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;YAEjE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAE,CAAC,EAAE,CAAC;QACpG,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SessionApprovalsPort } from "../../application/ports/session-approvals-port.js";
|
|
2
|
+
export declare class InMemorySessionApprovals implements SessionApprovalsPort {
|
|
3
|
+
private readonly commands;
|
|
4
|
+
clear(): void;
|
|
5
|
+
has(command: string): boolean;
|
|
6
|
+
allow(command: string): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class InMemorySessionApprovals {
|
|
2
|
+
commands = new Set();
|
|
3
|
+
clear() {
|
|
4
|
+
this.commands.clear();
|
|
5
|
+
}
|
|
6
|
+
has(command) {
|
|
7
|
+
return this.commands.has(command);
|
|
8
|
+
}
|
|
9
|
+
allow(command) {
|
|
10
|
+
this.commands.add(command);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=session-approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-approvals.js","sourceRoot":"","sources":["../../../src/interface/pi/session-approvals.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,wBAAwB;IAClB,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAE9C,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,GAAG,CAAC,OAAe;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,OAAe;QACnB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;CACF"}
|
package/package.json
CHANGED
package/dist/config.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export interface PatternConfig {
|
|
2
|
-
pattern: string;
|
|
3
|
-
regex?: boolean;
|
|
4
|
-
description?: string;
|
|
5
|
-
}
|
|
6
|
-
export interface GuardrailsConfig {
|
|
7
|
-
applyBuiltinDefaults?: boolean;
|
|
8
|
-
permissionGate?: {
|
|
9
|
-
patterns?: PatternConfig[];
|
|
10
|
-
allowedPatterns?: PatternConfig[];
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export declare const BUILTIN_PATTERNS: PatternConfig[];
|
|
14
|
-
export declare function getConfigPath(): string;
|
|
15
|
-
export declare function readConfig(path?: string): {
|
|
16
|
-
config: GuardrailsConfig;
|
|
17
|
-
error?: Error;
|
|
18
|
-
};
|
|
19
|
-
export declare function writeExactAllowRule(command: string, path?: string): PatternConfig;
|
|
20
|
-
export declare function testPattern(pattern: PatternConfig, command: string): boolean;
|
|
21
|
-
export declare function findPattern(command: string, patterns: PatternConfig[]): PatternConfig | undefined;
|
package/dist/config.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
export const BUILTIN_PATTERNS = [
|
|
5
|
-
{ pattern: "rm -rf", description: "recursive force delete" },
|
|
6
|
-
{ pattern: "sudo", description: "superuser command" },
|
|
7
|
-
{ pattern: "dd of=", description: "disk write operation" },
|
|
8
|
-
{ pattern: "mkfs.", description: "filesystem format" },
|
|
9
|
-
{ pattern: "chmod -R 777", description: "insecure recursive permissions" },
|
|
10
|
-
{ pattern: "chown -R", description: "recursive ownership change" },
|
|
11
|
-
{ pattern: "doas", description: "privileged command execution" },
|
|
12
|
-
{ pattern: "pkexec", description: "privileged command execution" },
|
|
13
|
-
{ pattern: "shred", description: "secure file overwrite" },
|
|
14
|
-
{ pattern: "wipefs", description: "filesystem signature wipe" },
|
|
15
|
-
{ pattern: "blkdiscard", description: "block device discard" },
|
|
16
|
-
{ pattern: "fdisk", description: "disk partitioning" },
|
|
17
|
-
{ pattern: "parted", description: "disk partitioning" },
|
|
18
|
-
{ pattern: "docker run --privileged", description: "container with privileged mode" },
|
|
19
|
-
];
|
|
20
|
-
export function getConfigPath() {
|
|
21
|
-
return join(homedir(), ".pi", "agent", "extensions", "guardrails.json");
|
|
22
|
-
}
|
|
23
|
-
export function readConfig(path = getConfigPath()) {
|
|
24
|
-
let content;
|
|
25
|
-
try {
|
|
26
|
-
content = readFileSync(path, "utf-8");
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
if (isNodeError(error) && error.code === "ENOENT")
|
|
30
|
-
return { config: {} };
|
|
31
|
-
return { config: {}, error: asError(error) };
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const parsed = JSON.parse(content);
|
|
35
|
-
if (!isGuardrailsConfig(parsed))
|
|
36
|
-
throw new Error("guardrails.json has an invalid structure");
|
|
37
|
-
return { config: parsed };
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
return { config: {}, error: asError(error) };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export function writeExactAllowRule(command, path = getConfigPath()) {
|
|
44
|
-
const { config, error } = readConfig(path);
|
|
45
|
-
if (error)
|
|
46
|
-
throw new Error(`Cannot update invalid guardrails config: ${error.message}`);
|
|
47
|
-
const permissionGate = config.permissionGate ?? {};
|
|
48
|
-
const allowedPatterns = permissionGate.allowedPatterns ?? [];
|
|
49
|
-
const rule = { pattern: `^${escapeRegex(command)}$`, regex: true };
|
|
50
|
-
if (!allowedPatterns.some((item) => item.pattern === rule.pattern && item.regex === true)) {
|
|
51
|
-
allowedPatterns.push(rule);
|
|
52
|
-
}
|
|
53
|
-
config.permissionGate = { ...permissionGate, allowedPatterns };
|
|
54
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
55
|
-
writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
|
|
56
|
-
return rule;
|
|
57
|
-
}
|
|
58
|
-
export function testPattern(pattern, command) {
|
|
59
|
-
if (pattern.regex) {
|
|
60
|
-
try {
|
|
61
|
-
return new RegExp(pattern.pattern).test(command);
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return command.includes(pattern.pattern);
|
|
68
|
-
}
|
|
69
|
-
export function findPattern(command, patterns) {
|
|
70
|
-
return patterns.find((pattern) => testPattern(pattern, command));
|
|
71
|
-
}
|
|
72
|
-
function escapeRegex(value) {
|
|
73
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
74
|
-
}
|
|
75
|
-
function isGuardrailsConfig(value) {
|
|
76
|
-
if (!isRecord(value))
|
|
77
|
-
return false;
|
|
78
|
-
if (value.applyBuiltinDefaults !== undefined && typeof value.applyBuiltinDefaults !== "boolean")
|
|
79
|
-
return false;
|
|
80
|
-
if (value.permissionGate === undefined)
|
|
81
|
-
return true;
|
|
82
|
-
if (!isRecord(value.permissionGate))
|
|
83
|
-
return false;
|
|
84
|
-
return isPatternList(value.permissionGate.patterns) && isPatternList(value.permissionGate.allowedPatterns);
|
|
85
|
-
}
|
|
86
|
-
function isPatternList(value) {
|
|
87
|
-
if (value === undefined)
|
|
88
|
-
return true;
|
|
89
|
-
return Array.isArray(value) && value.every(isPatternConfig);
|
|
90
|
-
}
|
|
91
|
-
function isPatternConfig(value) {
|
|
92
|
-
return (isRecord(value) &&
|
|
93
|
-
typeof value.pattern === "string" &&
|
|
94
|
-
(value.regex === undefined || typeof value.regex === "boolean") &&
|
|
95
|
-
(value.description === undefined || typeof value.description === "string"));
|
|
96
|
-
}
|
|
97
|
-
function isRecord(value) {
|
|
98
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
99
|
-
}
|
|
100
|
-
function isNodeError(error) {
|
|
101
|
-
return error instanceof Error && "code" in error;
|
|
102
|
-
}
|
|
103
|
-
function asError(error) {
|
|
104
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
105
|
-
}
|
|
106
|
-
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgB1C,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;IAC5D,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACrD,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;IAC1D,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACtD,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,gCAAgC,EAAE;IAC1E,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,4BAA4B,EAAE;IAClE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,8BAA8B,EAAE;IAChE,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;IAClE,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE;IAC1D,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE;IAC/D,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,sBAAsB,EAAE;IAC9D,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACtD,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACvD,EAAE,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,gCAAgC,EAAE;CACtF,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,aAAa,EAAE;IAC/C,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACzE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC7F,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,IAAI,GAAG,aAAa,EAAE;IACzE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAExF,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;IACnD,MAAM,eAAe,GAAG,cAAc,CAAC,eAAe,IAAI,EAAE,CAAC;IAC7D,MAAM,IAAI,GAAkB,EAAE,OAAO,EAAE,IAAI,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAClF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1F,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,eAAe,EAAE,CAAC;IAC/D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAsB,EAAE,OAAe;IACjE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,QAAyB;IACpE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,KAAK,CAAC,oBAAoB,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,oBAAoB,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC9G,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,OAAO,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;AAC7G,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,CACL,QAAQ,CAAC,KAAK,CAAC;QACf,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC;QAC/D,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAC3E,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC"}
|
package/dist/dialog.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","sourceRoot":"","sources":["../src/dialog.ts"],"names":[],"mappings":"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"}
|
package/dist/rules.d.ts
DELETED
package/dist/rules.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export const AUTO_DENY_PATTERNS = [
|
|
2
|
-
{ pattern: "az group delete", reason: "deletes an entire Azure resource group and all its resources" },
|
|
3
|
-
{ pattern: "az subscription cancel", reason: "cancels the entire Azure subscription" },
|
|
4
|
-
{ pattern: "az account management-group delete", reason: "deletes Azure management group hierarchy" },
|
|
5
|
-
{ pattern: "az ad user delete", reason: "deletes an Azure AD user" },
|
|
6
|
-
{ pattern: "az ad group delete", reason: "deletes an Azure AD security group" },
|
|
7
|
-
{ pattern: "az lock delete", reason: "removes an Azure resource lock (enables further destruction)" },
|
|
8
|
-
{ pattern: "az keyvault purge", reason: "permanently purges a Key Vault, bypassing soft-delete" },
|
|
9
|
-
{ pattern: "kubectl delete namespace", reason: "deletes a Kubernetes namespace and all resources inside" },
|
|
10
|
-
{ pattern: "kubectl delete --all", reason: "deletes all Kubernetes resources of a type" },
|
|
11
|
-
{ pattern: "kubectl drain", reason: "evicts all pods from a Kubernetes node" },
|
|
12
|
-
];
|
|
13
|
-
export function findAutoDenyMatch(command) {
|
|
14
|
-
return AUTO_DENY_PATTERNS.find((rule) => command.includes(rule.pattern));
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=rules.js.map
|
package/dist/rules.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,kBAAkB,GAAmB;IAChD,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,8DAA8D,EAAE;IACtG,EAAE,OAAO,EAAE,wBAAwB,EAAE,MAAM,EAAE,uCAAuC,EAAE;IACtF,EAAE,OAAO,EAAE,oCAAoC,EAAE,MAAM,EAAE,0CAA0C,EAAE;IACrG,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,0BAA0B,EAAE;IACpE,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,oCAAoC,EAAE;IAC/E,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,8DAA8D,EAAE;IACrG,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,uDAAuD,EAAE;IACjG,EAAE,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,yDAAyD,EAAE;IAC1G,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,EAAE,4CAA4C,EAAE;IACzF,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,wCAAwC,EAAE;CAC/E,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3E,CAAC"}
|
|
File without changes
|