@arvoretech/pi-secret-firewall 0.1.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/README.md +68 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +152 -0
- package/dist/index.js.map +1 -0
- package/dist/redact.d.ts +10 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +45 -0
- package/dist/redact.js.map +1 -0
- package/dist/secrets.d.ts +8 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +86 -0
- package/dist/secrets.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @arvoretech/pi-secret-firewall
|
|
2
|
+
|
|
3
|
+
A secret firewall for the Pi/Kiro agent. It keeps secret **values** out of the
|
|
4
|
+
model context entirely, exposing them only as `$SECRET_*` shell environment
|
|
5
|
+
variables that the model can *reference by name* but never *read*.
|
|
6
|
+
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
On session start (and on demand) it discovers secrets from two sources:
|
|
10
|
+
|
|
11
|
+
1. **Real environment variables** whose name looks sensitive
|
|
12
|
+
(`*_TOKEN`, `*_SECRET`, `*_API_KEY`, `*_PASSWORD`, `DATABASE_URL`, ...) — exact
|
|
13
|
+
value match, zero false positives.
|
|
14
|
+
2. **`.env` / `.env.local` / `.env.development*`** files in the cwd.
|
|
15
|
+
|
|
16
|
+
Each secret value gets a stable placeholder: `MY_API_KEY=xptolksjf` →
|
|
17
|
+
`$SECRET_MY_API_KEY`.
|
|
18
|
+
|
|
19
|
+
Redaction happens on two channels:
|
|
20
|
+
|
|
21
|
+
- **`context` hook** — every message sent to the model (user text, assistant
|
|
22
|
+
text, thinking, and tool-call arguments) has secret values swapped for their
|
|
23
|
+
placeholder.
|
|
24
|
+
- **`tool_result` hook** — output from `bash`, `read`, `grep`, etc. is redacted,
|
|
25
|
+
so `cat .env` returns placeholders, not values.
|
|
26
|
+
|
|
27
|
+
A pattern fallback also catches well-known token shapes (AWS keys, JWTs,
|
|
28
|
+
`sk-...`, GitHub/Slack tokens, PEM private keys) that leak into output even when
|
|
29
|
+
they were never in an env var.
|
|
30
|
+
|
|
31
|
+
## Security model — the model never sees the value
|
|
32
|
+
|
|
33
|
+
This extension uses the **shell-env-only** strategy:
|
|
34
|
+
|
|
35
|
+
- The real value lives in `process.env` (which the `bash` tool inherits).
|
|
36
|
+
- The model references it as a shell variable: `curl -H "Authorization: Bearer $SECRET_MY_API_KEY"`.
|
|
37
|
+
- The shell resolves `$SECRET_MY_API_KEY` at execution time.
|
|
38
|
+
- The value never returns to the context — any echo of it in tool output is
|
|
39
|
+
redacted again.
|
|
40
|
+
|
|
41
|
+
The extension never re-hydrates placeholders itself. If the model writes the
|
|
42
|
+
literal *value* instead of the placeholder, that value is redacted on the way
|
|
43
|
+
back, but the model must use the `$SECRET_*` reference for a command to actually
|
|
44
|
+
use the secret.
|
|
45
|
+
|
|
46
|
+
### Limits / non-goals
|
|
47
|
+
|
|
48
|
+
- A determined model could still exfiltrate a secret by transforming it before
|
|
49
|
+
printing (e.g. base64). This raises the bar; it is not a sandbox.
|
|
50
|
+
- Values shorter than 8 chars or matching trivial values (`true`, `3000`, ...)
|
|
51
|
+
are not protected — they are not secrets and redacting them breaks the agent.
|
|
52
|
+
- Infra/session vars (`PATH`, `HOME`, `SSH_AUTH_SOCK`, `*_SESSION`, ...) are
|
|
53
|
+
explicitly never treated as secrets.
|
|
54
|
+
|
|
55
|
+
## Commands
|
|
56
|
+
|
|
57
|
+
- `/secret-firewall` — show status (protected secrets, redaction count, the
|
|
58
|
+
`$SECRET_*` names the model may reference).
|
|
59
|
+
- `/secret-firewall-toggle` — enable/disable redaction.
|
|
60
|
+
- `/secret-firewall-rescan` — re-scan env + `.env` files.
|
|
61
|
+
|
|
62
|
+
## Develop
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm build # tsc -> dist/
|
|
66
|
+
pnpm test # node --test against dist/
|
|
67
|
+
pnpm lint # tsc --noEmit
|
|
68
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAWpE,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QAoJxC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { discoverSecrets } from "./secrets.js";
|
|
2
|
+
import { createRedactor } from "./redact.js";
|
|
3
|
+
function shellVarName(placeholder) {
|
|
4
|
+
return placeholder.replace(/^\$/, "");
|
|
5
|
+
}
|
|
6
|
+
export default function (pi) {
|
|
7
|
+
let enabled = true;
|
|
8
|
+
let entries = [];
|
|
9
|
+
const redactor = createRedactor([]);
|
|
10
|
+
let exportedNames = [];
|
|
11
|
+
const stats = { redactedHits: 0, lastScan: 0 };
|
|
12
|
+
function exportToShell(list) {
|
|
13
|
+
for (const name of exportedNames) {
|
|
14
|
+
if (!list.some((e) => shellVarName(e.placeholder) === name)) {
|
|
15
|
+
delete process.env[name];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exportedNames = [];
|
|
19
|
+
for (const e of list) {
|
|
20
|
+
const varName = shellVarName(e.placeholder);
|
|
21
|
+
process.env[varName] = e.value;
|
|
22
|
+
exportedNames.push(varName);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function rescan(cwd) {
|
|
26
|
+
entries = discoverSecrets(cwd);
|
|
27
|
+
redactor.refresh(entries);
|
|
28
|
+
exportToShell(entries);
|
|
29
|
+
stats.lastScan = entries.length;
|
|
30
|
+
}
|
|
31
|
+
function redactBlocks(content) {
|
|
32
|
+
let changed = false;
|
|
33
|
+
const next = content.map((block) => {
|
|
34
|
+
if (block.type !== "text")
|
|
35
|
+
return block;
|
|
36
|
+
const { text, hits } = redactor.redactString(block.text);
|
|
37
|
+
if (hits > 0) {
|
|
38
|
+
changed = true;
|
|
39
|
+
stats.redactedHits += hits;
|
|
40
|
+
return { ...block, text };
|
|
41
|
+
}
|
|
42
|
+
return block;
|
|
43
|
+
});
|
|
44
|
+
return changed ? next : undefined;
|
|
45
|
+
}
|
|
46
|
+
function redactMessageContent(content) {
|
|
47
|
+
if (typeof content === "string") {
|
|
48
|
+
const { text, hits } = redactor.redactString(content);
|
|
49
|
+
if (hits > 0)
|
|
50
|
+
stats.redactedHits += hits;
|
|
51
|
+
return text;
|
|
52
|
+
}
|
|
53
|
+
if (Array.isArray(content)) {
|
|
54
|
+
return content.map((block) => {
|
|
55
|
+
if (block && typeof block === "object") {
|
|
56
|
+
const b = block;
|
|
57
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
58
|
+
const { text, hits } = redactor.redactString(b.text);
|
|
59
|
+
if (hits > 0)
|
|
60
|
+
stats.redactedHits += hits;
|
|
61
|
+
return { ...b, text };
|
|
62
|
+
}
|
|
63
|
+
if (b.type === "thinking" && typeof b.thinking === "string") {
|
|
64
|
+
const { text, hits } = redactor.redactString(b.thinking);
|
|
65
|
+
if (hits > 0)
|
|
66
|
+
stats.redactedHits += hits;
|
|
67
|
+
return { ...b, thinking: text };
|
|
68
|
+
}
|
|
69
|
+
if (b.type === "toolCall" && b.arguments && typeof b.arguments === "object") {
|
|
70
|
+
return { ...b, arguments: redactArguments(b.arguments) };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return block;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return content;
|
|
77
|
+
}
|
|
78
|
+
function redactArguments(args) {
|
|
79
|
+
const out = {};
|
|
80
|
+
for (const [k, v] of Object.entries(args)) {
|
|
81
|
+
if (typeof v === "string") {
|
|
82
|
+
const { text, hits } = redactor.redactString(v);
|
|
83
|
+
if (hits > 0)
|
|
84
|
+
stats.redactedHits += hits;
|
|
85
|
+
out[k] = text;
|
|
86
|
+
}
|
|
87
|
+
else if (Array.isArray(v)) {
|
|
88
|
+
out[k] = v.map((item) => typeof item === "string" ? redactor.redactString(item).text : item);
|
|
89
|
+
}
|
|
90
|
+
else if (v && typeof v === "object") {
|
|
91
|
+
out[k] = redactArguments(v);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
out[k] = v;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
100
|
+
rescan(ctx.cwd);
|
|
101
|
+
});
|
|
102
|
+
pi.on("context", async (event, _ctx) => {
|
|
103
|
+
if (!enabled || entries.length === 0)
|
|
104
|
+
return;
|
|
105
|
+
let changed = false;
|
|
106
|
+
const messages = event.messages.map((msg) => {
|
|
107
|
+
const m = msg;
|
|
108
|
+
if (!("content" in m))
|
|
109
|
+
return msg;
|
|
110
|
+
const before = m.content;
|
|
111
|
+
const after = redactMessageContent(before);
|
|
112
|
+
if (after !== before) {
|
|
113
|
+
changed = true;
|
|
114
|
+
return { ...m, content: after };
|
|
115
|
+
}
|
|
116
|
+
return msg;
|
|
117
|
+
});
|
|
118
|
+
if (changed)
|
|
119
|
+
return { messages };
|
|
120
|
+
});
|
|
121
|
+
pi.on("tool_result", async (event) => {
|
|
122
|
+
if (!enabled || entries.length === 0)
|
|
123
|
+
return;
|
|
124
|
+
const redacted = redactBlocks(event.content);
|
|
125
|
+
if (redacted)
|
|
126
|
+
return { content: redacted };
|
|
127
|
+
});
|
|
128
|
+
pi.registerCommand("secret-firewall", {
|
|
129
|
+
description: "Show secret-firewall status (protected secrets, redaction count)",
|
|
130
|
+
handler: async (_args, ctx) => {
|
|
131
|
+
rescan(ctx.cwd);
|
|
132
|
+
const names = entries.map((e) => e.placeholder).join(", ") || "(none)";
|
|
133
|
+
ctx.ui.notify(`secret-firewall [${enabled ? "on" : "off"}] | protecting ${entries.length} secret(s) | ` +
|
|
134
|
+
`redacted ${stats.redactedHits} value(s) so far\nReferenceable as shell env: ${names}`, "info");
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
pi.registerCommand("secret-firewall-toggle", {
|
|
138
|
+
description: "Enable or disable secret-firewall redaction",
|
|
139
|
+
handler: async (_args, ctx) => {
|
|
140
|
+
enabled = !enabled;
|
|
141
|
+
ctx.ui.notify(`secret-firewall ${enabled ? "enabled" : "disabled"}`, "info");
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
pi.registerCommand("secret-firewall-rescan", {
|
|
145
|
+
description: "Re-scan environment and .env files for secrets",
|
|
146
|
+
handler: async (_args, ctx) => {
|
|
147
|
+
rescan(ctx.cwd);
|
|
148
|
+
ctx.ui.notify(`secret-firewall re-scanned: ${entries.length} secret(s) protected`, "info");
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/redact.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SecretEntry } from "./secrets.js";
|
|
2
|
+
export interface Redactor {
|
|
3
|
+
redactString(text: string): {
|
|
4
|
+
text: string;
|
|
5
|
+
hits: number;
|
|
6
|
+
};
|
|
7
|
+
refresh(entries: SecretEntry[]): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function createRedactor(initial: SecretEntry[]): Redactor;
|
|
10
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,QAAQ;IACvB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;CACvC;AAwBD,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,CA8B/D"}
|
package/dist/redact.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const PATTERN_RULES = [
|
|
2
|
+
{ name: "AWS_ACCESS_KEY", re: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
3
|
+
{ name: "AWS_SECRET", re: /\b(?<![A-Za-z0-9/+])[A-Za-z0-9/+]{40}(?![A-Za-z0-9/+])\b/g },
|
|
4
|
+
{ name: "OPENAI_KEY", re: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
|
|
5
|
+
{ name: "GITHUB_TOKEN", re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/g },
|
|
6
|
+
{ name: "SLACK_TOKEN", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
|
|
7
|
+
{ name: "JWT", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
|
|
8
|
+
{
|
|
9
|
+
name: "PRIVATE_KEY",
|
|
10
|
+
re: /-----BEGIN[A-Z ]*PRIVATE KEY-----[\s\S]+?-----END[A-Z ]*PRIVATE KEY-----/g,
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
function escapeRe(s) {
|
|
14
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15
|
+
}
|
|
16
|
+
export function createRedactor(initial) {
|
|
17
|
+
let valueRules = [];
|
|
18
|
+
function refresh(entries) {
|
|
19
|
+
valueRules = entries
|
|
20
|
+
.filter((e) => e.value.length > 0)
|
|
21
|
+
.map((e) => ({ re: new RegExp(escapeRe(e.value), "g"), placeholder: e.placeholder }));
|
|
22
|
+
}
|
|
23
|
+
function redactString(text) {
|
|
24
|
+
if (!text)
|
|
25
|
+
return { text, hits: 0 };
|
|
26
|
+
let out = text;
|
|
27
|
+
let hits = 0;
|
|
28
|
+
for (const { re, placeholder } of valueRules) {
|
|
29
|
+
out = out.replace(re, () => {
|
|
30
|
+
hits++;
|
|
31
|
+
return placeholder;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
for (const { name, re } of PATTERN_RULES) {
|
|
35
|
+
out = out.replace(re, () => {
|
|
36
|
+
hits++;
|
|
37
|
+
return `$SECRET_${name}`;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return { text: out, hits };
|
|
41
|
+
}
|
|
42
|
+
refresh(initial);
|
|
43
|
+
return { redactString, refresh };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAYA,MAAM,aAAa,GAAkB;IACnC,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,uBAAuB,EAAE;IACvD,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,2DAA2D,EAAE;IACvF,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,4BAA4B,EAAE;IACxD,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,iCAAiC,EAAE;IAC/D,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,mCAAmC,EAAE;IAChE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,oEAAoE,EAAE;IACzF;QACE,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,2EAA2E;KAChF;CACF,CAAC;AAEF,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAsB;IACnD,IAAI,UAAU,GAA0C,EAAE,CAAC;IAE3D,SAAS,OAAO,CAAC,OAAsB;QACrC,UAAU,GAAG,OAAO;aACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;aACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,SAAS,YAAY,CAAC,IAAY;QAChC,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACpC,IAAI,GAAG,GAAG,IAAI,CAAC;QACf,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,UAAU,EAAE,CAAC;YAC7C,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE;gBACzB,IAAI,EAAE,CAAC;gBACP,OAAO,WAAW,CAAC;YACrB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,aAAa,EAAE,CAAC;YACzC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE;gBACzB,IAAI,EAAE,CAAC;gBACP,OAAO,WAAW,IAAI,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;CACtC;AA2DD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CA8B1D"}
|
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const SENSITIVE_NAME = /(SECRET|TOKEN|PASSWORD|PASSWD|PWD|API[_-]?KEY|APIKEY|ACCESS[_-]?KEY|PRIVATE[_-]?KEY|CLIENT[_-]?SECRET|AUTH|CREDENTIAL|DSN|DATABASE_URL|CONNECTION_STRING|SESSION|COOKIE|SIGNING|ENCRYPT|SALT|BEARER)/i;
|
|
4
|
+
const NEVER_SENSITIVE = /^(PATH|HOME|SHELL|PWD|OLDPWD|LANG|LC_|TERM|USER|LOGNAME|HOSTNAME|TMPDIR|EDITOR|PAGER|NODE_ENV|NODE_OPTIONS|npm_|PNPM_|COLORTERM|SHLVL|SSH_AUTH_SOCK|SSH_AGENT_PID|__MISE|MISE_|WARP_|XPC_|__CF|SECURITYSESSIONID|TERM_SESSION_ID|_$)/;
|
|
5
|
+
const SESSION_LIKE_NAME = /(SESSION|SOCK|UUID|_PID)$/i;
|
|
6
|
+
const MIN_VALUE_LENGTH = 8;
|
|
7
|
+
const TRIVIAL_VALUE = /^(true|false|null|undefined|none|localhost|0|1|3000|8080|development|production|staging|test)$/i;
|
|
8
|
+
const DOTENV_FILES = [".env", ".env.local", ".env.development", ".env.development.local"];
|
|
9
|
+
const DOTENV_LINE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/;
|
|
10
|
+
function unquote(raw) {
|
|
11
|
+
const v = raw.trim();
|
|
12
|
+
if ((v.startsWith('"') && v.endsWith('"')) ||
|
|
13
|
+
(v.startsWith("'") && v.endsWith("'"))) {
|
|
14
|
+
return v.slice(1, -1);
|
|
15
|
+
}
|
|
16
|
+
const hash = v.indexOf(" #");
|
|
17
|
+
return hash >= 0 ? v.slice(0, hash).trim() : v;
|
|
18
|
+
}
|
|
19
|
+
function isSensitiveValue(name, value) {
|
|
20
|
+
if (NEVER_SENSITIVE.test(name))
|
|
21
|
+
return false;
|
|
22
|
+
if (SESSION_LIKE_NAME.test(name))
|
|
23
|
+
return false;
|
|
24
|
+
if (!value || value.length < MIN_VALUE_LENGTH)
|
|
25
|
+
return false;
|
|
26
|
+
if (TRIVIAL_VALUE.test(value))
|
|
27
|
+
return false;
|
|
28
|
+
return SENSITIVE_NAME.test(name);
|
|
29
|
+
}
|
|
30
|
+
function toPlaceholder(name, taken) {
|
|
31
|
+
const base = `$SECRET_${name.replace(/[^A-Za-z0-9_]/g, "_").toUpperCase()}`;
|
|
32
|
+
if (!taken.has(base))
|
|
33
|
+
return base;
|
|
34
|
+
let i = 2;
|
|
35
|
+
while (taken.has(`${base}_${i}`))
|
|
36
|
+
i++;
|
|
37
|
+
return `${base}_${i}`;
|
|
38
|
+
}
|
|
39
|
+
function parseDotenv(path) {
|
|
40
|
+
const out = new Map();
|
|
41
|
+
try {
|
|
42
|
+
const text = readFileSync(path, "utf8");
|
|
43
|
+
for (const line of text.split(/\r?\n/)) {
|
|
44
|
+
if (!line.trim() || line.trim().startsWith("#"))
|
|
45
|
+
continue;
|
|
46
|
+
const m = DOTENV_LINE.exec(line);
|
|
47
|
+
if (!m)
|
|
48
|
+
continue;
|
|
49
|
+
out.set(m[1], unquote(m[2]));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
/* unreadable file, skip */
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
export function discoverSecrets(cwd) {
|
|
58
|
+
const byName = new Map();
|
|
59
|
+
for (const [name, value] of Object.entries(process.env)) {
|
|
60
|
+
if (typeof value === "string" && isSensitiveValue(name, value)) {
|
|
61
|
+
byName.set(name, { value, source: "env" });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
for (const file of DOTENV_FILES) {
|
|
65
|
+
const path = join(cwd, file);
|
|
66
|
+
if (!existsSync(path))
|
|
67
|
+
continue;
|
|
68
|
+
for (const [name, value] of parseDotenv(path)) {
|
|
69
|
+
if (isSensitiveValue(name, value) && !byName.has(name)) {
|
|
70
|
+
byName.set(name, { value, source: "dotenv" });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const taken = new Set();
|
|
75
|
+
const entries = [];
|
|
76
|
+
for (const [name, { value, source }] of byName) {
|
|
77
|
+
if (!value)
|
|
78
|
+
continue;
|
|
79
|
+
const placeholder = toPlaceholder(name, taken);
|
|
80
|
+
taken.add(placeholder);
|
|
81
|
+
entries.push({ name, placeholder, value, source });
|
|
82
|
+
}
|
|
83
|
+
entries.sort((a, b) => b.value.length - a.value.length);
|
|
84
|
+
return entries;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arvoretech/pi-secret-firewall",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Redacts secrets (env vars, .env files, token patterns) from the model context and tool outputs, exposing them only as $SECRET_* shell env vars the model can reference but never read",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"lint": "tsc --noEmit",
|
|
15
|
+
"test": "tsc && node --test --experimental-strip-types --disable-warning=ExperimentalWarning test/*.test.ts"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@earendil-works/pi-coding-agent": ">=0.74.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@earendil-works/pi-coding-agent": "^0.79.4",
|
|
22
|
+
"@earendil-works/pi-ai": "^0.79.4",
|
|
23
|
+
"@earendil-works/pi-tui": "^0.79.4",
|
|
24
|
+
"@types/node": "^20.10.0",
|
|
25
|
+
"typebox": "1.1.38",
|
|
26
|
+
"typescript": "^5.3.0"
|
|
27
|
+
},
|
|
28
|
+
"pi": {
|
|
29
|
+
"extensions": [
|
|
30
|
+
"./dist/index.js"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/arvoreeducacao/arvore-pi-extensions.git",
|
|
36
|
+
"directory": "packages/secret-firewall"
|
|
37
|
+
},
|
|
38
|
+
"author": "Arvore",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"keywords": [
|
|
41
|
+
"pi-package"
|
|
42
|
+
]
|
|
43
|
+
}
|