Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

43 lines · 1.3 KBRaw History
1/** Replaces registered secret values with `***` in log output. */
2export class Masker {
3 private values = new Set<string>();
4 private sorted: string[] = [];
5
6 add(value: string | undefined | null): void {
7 if (value === undefined || value === null) return;
8 const v = String(value);
9 if (v.trim() === "") return;
10 const before = this.values.size;
11 this.values.add(v);
12 this.values.add(v.trim());
13 // multi-line secrets: mask each line individually, since logs are line based
14 if (/\r?\n/.test(v)) {
15 for (const line of v.split(/\r?\n/)) {
16 const t = line.trim();
17 if (t.length >= 2) this.values.add(t);
18 }
19 }
20 if (this.values.size !== before) {
21 this.sorted = [...this.values].sort((a, b) => b.length - a.length);
22 }
23 }
24
25 has(value: string): boolean {
26 return this.values.has(value);
27 }
28
29 /** True when the text contains any masked value. */
30 containsSecret(text: string): boolean {
31 for (const v of this.sorted) if (text.includes(v)) return true;
32 return false;
33 }
34
35 mask(text: string): string {
36 if (this.sorted.length === 0 || text === "") return text;
37 let out = text;
38 for (const v of this.sorted) {
39 if (out.includes(v)) out = out.split(v).join("***");
40 }
41 return out;
42 }
43}