@grwnd/pi-governance 1.8.0 → 1.9.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/README.md +1 -0
- package/dist/extensions/index.cjs +43 -5
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.js +43 -5
- package/dist/extensions/index.js.map +1 -1
- package/dist/index.cjs +10 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/extensions/index.js
CHANGED
|
@@ -1533,15 +1533,15 @@ function sendJson(res, status, data) {
|
|
|
1533
1533
|
res.end(JSON.stringify(data));
|
|
1534
1534
|
}
|
|
1535
1535
|
function readBody(req) {
|
|
1536
|
-
return new Promise((
|
|
1536
|
+
return new Promise((resolve2, reject) => {
|
|
1537
1537
|
const chunks = [];
|
|
1538
1538
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
1539
|
-
req.on("end", () =>
|
|
1539
|
+
req.on("end", () => resolve2(Buffer.concat(chunks).toString("utf-8")));
|
|
1540
1540
|
req.on("error", reject);
|
|
1541
1541
|
});
|
|
1542
1542
|
}
|
|
1543
1543
|
function startWizardServer(options) {
|
|
1544
|
-
return new Promise((
|
|
1544
|
+
return new Promise((resolve2, reject) => {
|
|
1545
1545
|
let shutdownTimer;
|
|
1546
1546
|
const server = createServer((req, res) => {
|
|
1547
1547
|
setCorsHeaders(res);
|
|
@@ -1631,7 +1631,7 @@ function startWizardServer(options) {
|
|
|
1631
1631
|
shutdownTimer = setTimeout(() => {
|
|
1632
1632
|
closeServer();
|
|
1633
1633
|
}, AUTO_SHUTDOWN_MS);
|
|
1634
|
-
|
|
1634
|
+
resolve2({ port: addr.port, close: closeServer });
|
|
1635
1635
|
});
|
|
1636
1636
|
});
|
|
1637
1637
|
}
|
|
@@ -1681,6 +1681,7 @@ var init_wizard = __esm({
|
|
|
1681
1681
|
|
|
1682
1682
|
// src/extensions/index.ts
|
|
1683
1683
|
import { existsSync as existsSync2 } from "fs";
|
|
1684
|
+
import { resolve } from "path";
|
|
1684
1685
|
|
|
1685
1686
|
// src/lib/config/loader.ts
|
|
1686
1687
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -2154,7 +2155,16 @@ var DANGEROUS_PATTERNS = [
|
|
|
2154
2155
|
// Compiler/build (can execute arbitrary code)
|
|
2155
2156
|
/\bmake\s/,
|
|
2156
2157
|
/\bgcc\b/,
|
|
2157
|
-
/\bg
|
|
2158
|
+
/\bg\+\+/,
|
|
2159
|
+
// Governance config tampering — shell-based writes to governance files
|
|
2160
|
+
/(cat|echo|printf)\s.*>\s*.*governance(-rules)?\.yaml/,
|
|
2161
|
+
/\btee\s+.*governance(-rules)?\.yaml/,
|
|
2162
|
+
/sed\s+-i.*governance(-rules)?\.yaml/,
|
|
2163
|
+
/(cp|mv|rm)\s.*governance(-rules)?\.yaml/,
|
|
2164
|
+
/(cat|echo|printf)\s.*>\s*.*\.pi\/governance/,
|
|
2165
|
+
/\btee\s+.*\.pi\/governance/,
|
|
2166
|
+
/sed\s+-i.*\.pi\/governance/,
|
|
2167
|
+
/(cp|mv|rm)\s.*\.pi\/governance/
|
|
2158
2168
|
];
|
|
2159
2169
|
|
|
2160
2170
|
// src/lib/bash/classifier.ts
|
|
@@ -2949,7 +2959,9 @@ var piGovernance = (pi) => {
|
|
|
2949
2959
|
let configWatcher;
|
|
2950
2960
|
let dlpScanner;
|
|
2951
2961
|
let dlpMasker;
|
|
2962
|
+
let protectedPaths = /* @__PURE__ */ new Set();
|
|
2952
2963
|
const stats = {
|
|
2964
|
+
configTampered: 0,
|
|
2953
2965
|
allowed: 0,
|
|
2954
2966
|
denied: 0,
|
|
2955
2967
|
approvals: 0,
|
|
@@ -2963,6 +2975,15 @@ var piGovernance = (pi) => {
|
|
|
2963
2975
|
sessionId = ctx.sessionId;
|
|
2964
2976
|
const loaded = loadConfig();
|
|
2965
2977
|
config = loaded.config;
|
|
2978
|
+
const paths = /* @__PURE__ */ new Set();
|
|
2979
|
+
if (loaded.source !== "built-in") {
|
|
2980
|
+
paths.add(resolve(loaded.source));
|
|
2981
|
+
}
|
|
2982
|
+
const rulesFileCfg = config.policy?.yaml?.rules_file ?? "./governance-rules.yaml";
|
|
2983
|
+
paths.add(resolve(rulesFileCfg));
|
|
2984
|
+
paths.add(resolve(ctx.workingDirectory, ".pi/governance.yaml"));
|
|
2985
|
+
paths.add(resolve(ctx.workingDirectory, "governance-rules.yaml"));
|
|
2986
|
+
protectedPaths = paths;
|
|
2966
2987
|
const chain = createIdentityChain(config.auth);
|
|
2967
2988
|
identity = await chain.resolve();
|
|
2968
2989
|
const rulesFile = config.policy?.yaml?.rules_file ?? "./governance-rules.yaml";
|
|
@@ -3092,6 +3113,22 @@ var piGovernance = (pi) => {
|
|
|
3092
3113
|
tool: toolName,
|
|
3093
3114
|
input: params
|
|
3094
3115
|
};
|
|
3116
|
+
if (WRITE_TOOLS.has(toolName)) {
|
|
3117
|
+
const filePath = extractPath(toolName, input);
|
|
3118
|
+
if (filePath && protectedPaths.has(resolve(filePath))) {
|
|
3119
|
+
stats.configTampered++;
|
|
3120
|
+
await audit.log({
|
|
3121
|
+
...baseRecord,
|
|
3122
|
+
event: "config_tampered",
|
|
3123
|
+
decision: "denied",
|
|
3124
|
+
reason: `Config self-protection: write to governance file blocked (${filePath})`
|
|
3125
|
+
});
|
|
3126
|
+
return {
|
|
3127
|
+
block: true,
|
|
3128
|
+
reason: `Governance config files are protected and cannot be modified by agents`
|
|
3129
|
+
};
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3095
3132
|
if (executionMode === "dry_run") {
|
|
3096
3133
|
stats.dryRun++;
|
|
3097
3134
|
await audit.log({
|
|
@@ -3367,6 +3404,7 @@ var piGovernance = (pi) => {
|
|
|
3367
3404
|
` Approvals: ${stats.approvals}`,
|
|
3368
3405
|
` Dry-run blocks: ${stats.dryRun}`,
|
|
3369
3406
|
` Budget exceeded: ${stats.budgetExceeded}`,
|
|
3407
|
+
` Config tampered: ${stats.configTampered}`,
|
|
3370
3408
|
` DLP blocked: ${stats.dlpBlocked}`,
|
|
3371
3409
|
` DLP detected: ${stats.dlpDetected}`,
|
|
3372
3410
|
` DLP masked: ${stats.dlpMasked}`,
|