@optimuslabs/pii-scrub-staging 0.1.0 → 0.1.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 +8 -3
- package/dist/index.d.ts +9 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +131 -39
- package/dist/index.js.map +1 -1
- package/dist/org-setting.d.ts +14 -0
- package/dist/org-setting.d.ts.map +1 -0
- package/dist/org-setting.js +28 -0
- package/dist/org-setting.js.map +1 -0
- package/dist/rules.d.ts +12 -5
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +12 -5
- package/dist/rules.js.map +1 -1
- package/package.json +1 -1
- package/rules.json +127 -20
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# @optimuslabs/pii-scrub
|
|
2
2
|
|
|
3
|
-
Redacts secrets
|
|
4
|
-
|
|
3
|
+
Redacts secrets from what an Optimus endpoint sends, before the request leaves the machine. Personal
|
|
4
|
+
data (emails, home directories) is not redacted: the backend reads it for owners, tenants and path
|
|
5
|
+
matching. Used by `@optimuslabs/runtime`
|
|
5
6
|
(tool calls), `@optimuslabs/harness-map` (config file inventory) and `@optimuslabs/discovery`
|
|
6
7
|
(which sends the version). Design: `docs/pii-scrubbing/DESIGN.md`.
|
|
7
8
|
|
|
@@ -10,7 +11,7 @@ import { SCRUBBER_VERSION, scrub, scrubText, scrubValue } from "@optimuslabs/pii
|
|
|
10
11
|
|
|
11
12
|
scrubValue({ env: { BRAVE_API_KEY: "BSA..." } }); // { env: { BRAVE_API_KEY: "[OL_REDACTED:CREDENTIAL_ENV_VAR]" } }
|
|
12
13
|
scrubText("key sk-ant-api03-...", { fingerprintKey }); // "key sk-ant-api03-[OL_REDACTED:ANTHROPIC_KEY:<24 hex>]"
|
|
13
|
-
|
|
14
|
+
scrubValue({ command: "npx", env: { LOG_LEVEL: "debug" } }); // unchanged: only secrets are redacted
|
|
14
15
|
scrub(payload).hits; // { ANTHROPIC_KEY: 1, ... }; placeholders already there are not hits
|
|
15
16
|
```
|
|
16
17
|
|
|
@@ -18,5 +19,9 @@ The rules are in `rules.json`, which the backend reads too; every pattern works
|
|
|
18
19
|
JavaScript and Python regex engines. Only vendor-format secrets are fingerprinted (HMAC-SHA256
|
|
19
20
|
under the org key, 96 bits), and only when the caller passes the key.
|
|
20
21
|
|
|
22
|
+
An organization can switch scrubbing off (OPT-942). The senders store the backend's `scrub_pii` in
|
|
23
|
+
`~/.optimuslabs/management/org/config.json`, and every function here returns its input unchanged
|
|
24
|
+
while that file says `"scrub_pii": false`. No file, or no field, means scrub.
|
|
25
|
+
|
|
21
26
|
The staging build publishes as `@optimuslabs/pii-scrub-staging`, the production build as
|
|
22
27
|
`@optimuslabs/pii-scrub`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Redact secrets
|
|
2
|
+
* Redact secrets from what an endpoint sends to Optimus. Personal data (emails, home directories)
|
|
3
|
+
* is not redacted: the backend reads it for identity, owners and path matching.
|
|
3
4
|
*
|
|
4
5
|
* Runs on the endpoint, just before a request is built, so the value never leaves the machine.
|
|
5
6
|
* A value is replaced with a typed placeholder rather than dropped, so the backend still knows a
|
|
@@ -7,9 +8,7 @@
|
|
|
7
8
|
*
|
|
8
9
|
* sk-ant-api03-[OL_REDACTED:ANTHROPIC_KEY:<fp>] a vendor key keeps its published prefix
|
|
9
10
|
* [OL_REDACTED:CREDENTIAL_ENV_VAR] a value under a credential-named key
|
|
10
|
-
* [OL_REDACTED:
|
|
11
|
-
* [OL_REDACTED:EMAIL]@gmail.com an email inside content keeps its domain
|
|
12
|
-
* /Users/[OL_REDACTED:USERNAME]/src a home directory keeps its path
|
|
11
|
+
* [OL_REDACTED:POTENTIAL_TOKEN] a 40+ character token in an MCP server's env
|
|
13
12
|
*
|
|
14
13
|
* `<fp>` is a 96-bit fingerprint (24 hex characters, HMAC-SHA256 under the org's key), on
|
|
15
14
|
* vendor-format secrets only, so the same key is recognisable across configs and machines
|
|
@@ -21,16 +20,11 @@
|
|
|
21
20
|
* is and is not a hit, so scrubbing twice changes nothing and counts nothing.
|
|
22
21
|
*/
|
|
23
22
|
export { SECRET_FORMATS } from "./rules.js";
|
|
23
|
+
export { scrubbingSwitchedOff } from "./org-setting.js";
|
|
24
24
|
/** This scrubber's version (the package's), which every sender includes with what it scrubbed. */
|
|
25
25
|
export declare const SCRUBBER_VERSION: string;
|
|
26
26
|
export declare const PLACEHOLDER_PREFIX = "[OL_REDACTED:";
|
|
27
27
|
export interface ScrubOptions {
|
|
28
|
-
/**
|
|
29
|
-
* Also redact personal data: the name part of emails and the username in home directories. On
|
|
30
|
-
* for tool-call content; off for config files, where account emails are identity (agent owners,
|
|
31
|
-
* tenant approval, the personal-email finding) and stay readable.
|
|
32
|
-
*/
|
|
33
|
-
personalData?: boolean;
|
|
34
28
|
/** The org's fingerprint key, hex. Absent until the endpoint has received it: no fingerprints. */
|
|
35
29
|
fingerprintKey?: string;
|
|
36
30
|
}
|
|
@@ -44,11 +38,15 @@ export declare function placeholder(type: string, fingerprint?: string): string;
|
|
|
44
38
|
/**
|
|
45
39
|
* A deep copy of `value` with every string scrubbed and every value under a credential-named key
|
|
46
40
|
* redacted, and how many of each type were redacted. Non-string leaves are returned as they are.
|
|
41
|
+
* When the organization has switched scrubbing off, `value` itself, with no hits.
|
|
47
42
|
*/
|
|
48
43
|
export declare function scrub<T>(value: T, options?: ScrubOptions): ScrubResult<T>;
|
|
49
44
|
/** `scrub(value).value`. */
|
|
50
45
|
export declare function scrubValue<T>(value: T, options?: ScrubOptions): T;
|
|
51
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* A copy of `text` with every secret redacted;
|
|
48
|
+
* `text` itself when the organization has switched scrubbing off.
|
|
49
|
+
*/
|
|
52
50
|
export declare function scrubText(text: string, options?: ScrubOptions): string;
|
|
53
51
|
/**
|
|
54
52
|
* A copy of `record` with each of `fields` that is a string scrubbed as text, the rest untouched:
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAyBH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,kGAAkG;AAClG,eAAO,MAAM,gBAAgB,EAAE,MAA2F,CAAC;AAE3H,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,SAAS,CAAC;CACjB;AAcD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;AA4MD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAE,YAAiB,GAAG,WAAW,CAAC,CAAC,CAAC,CAI7E;AAED,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAE,YAAiB,GAAG,CAAC,CAErE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAG1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,GAAE,YAAiB,GACzB,CAAC,CAOH;AAED,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO3D"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Redact secrets
|
|
2
|
+
* Redact secrets from what an endpoint sends to Optimus. Personal data (emails, home directories)
|
|
3
|
+
* is not redacted: the backend reads it for identity, owners and path matching.
|
|
3
4
|
*
|
|
4
5
|
* Runs on the endpoint, just before a request is built, so the value never leaves the machine.
|
|
5
6
|
* A value is replaced with a typed placeholder rather than dropped, so the backend still knows a
|
|
@@ -7,9 +8,7 @@
|
|
|
7
8
|
*
|
|
8
9
|
* sk-ant-api03-[OL_REDACTED:ANTHROPIC_KEY:<fp>] a vendor key keeps its published prefix
|
|
9
10
|
* [OL_REDACTED:CREDENTIAL_ENV_VAR] a value under a credential-named key
|
|
10
|
-
* [OL_REDACTED:
|
|
11
|
-
* [OL_REDACTED:EMAIL]@gmail.com an email inside content keeps its domain
|
|
12
|
-
* /Users/[OL_REDACTED:USERNAME]/src a home directory keeps its path
|
|
11
|
+
* [OL_REDACTED:POTENTIAL_TOKEN] a 40+ character token in an MCP server's env
|
|
13
12
|
*
|
|
14
13
|
* `<fp>` is a 96-bit fingerprint (24 hex characters, HMAC-SHA256 under the org's key), on
|
|
15
14
|
* vendor-format secrets only, so the same key is recognisable across configs and machines
|
|
@@ -22,13 +21,18 @@
|
|
|
22
21
|
*/
|
|
23
22
|
import { createHmac } from "node:crypto";
|
|
24
23
|
import { createRequire } from "node:module";
|
|
25
|
-
import { CONTAINS_REFERENCE, CREDENTIAL_ASSIGNMENT, CREDENTIAL_FLAG, CREDENTIAL_KEY,
|
|
24
|
+
import { CODE_VALUE, CONTAINER_KEEP, CONTAINS_REFERENCE, CREDENTIAL_ASSIGNMENT, CREDENTIAL_CONTAINER, CREDENTIAL_FLAG, CREDENTIAL_KEY, ENV_REFERENCE, GENERIC_TOKEN, JSON_SCHEMA_TYPES, MCP_SERVER_KEYS, MCP_VALUE_BLOCKS, MIN_CREDENTIAL_LENGTH, NOT_A_SECRET_UNDER_WEAK_KEY, PLACEHOLDER_VALUE, SECRET_FORMATS, WEAK_CREDENTIAL_KEY, } from "./rules.js";
|
|
25
|
+
import { scrubbingSwitchedOff } from "./org-setting.js";
|
|
26
26
|
export { SECRET_FORMATS } from "./rules.js";
|
|
27
|
+
export { scrubbingSwitchedOff } from "./org-setting.js";
|
|
27
28
|
/** This scrubber's version (the package's), which every sender includes with what it scrubbed. */
|
|
28
29
|
export const SCRUBBER_VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
29
30
|
export const PLACEHOLDER_PREFIX = "[OL_REDACTED:";
|
|
30
|
-
/**
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* How deep a payload may nest before the scrubber stops descending (and redacts the rest). MCP tool
|
|
33
|
+
* input schemas in agent configs nest past 32 (measured on prod data), so the limit sits well above.
|
|
34
|
+
*/
|
|
35
|
+
const MAX_DEPTH = 128;
|
|
32
36
|
const FINGERPRINT_HEX_LENGTH = 24;
|
|
33
37
|
export function placeholder(type, fingerprint) {
|
|
34
38
|
return fingerprint ? `${PLACEHOLDER_PREFIX}${type}:${fingerprint}]` : `${PLACEHOLDER_PREFIX}${type}]`;
|
|
@@ -49,37 +53,60 @@ function isCredentialValue(value) {
|
|
|
49
53
|
return (trimmed.length >= MIN_CREDENTIAL_LENGTH &&
|
|
50
54
|
!/\s/.test(trimmed) &&
|
|
51
55
|
!ENV_REFERENCE.test(trimmed) &&
|
|
56
|
+
!PLACEHOLDER_VALUE.test(trimmed) &&
|
|
52
57
|
// A placeholder, or the front of one that a text rule cut at its closing `]`.
|
|
53
58
|
!trimmed.includes(PLACEHOLDER_PREFIX));
|
|
54
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Whether `name` names a credential, for its `value`. A bare `_key` name (`DEPLOY_SSH_KEY`, but
|
|
62
|
+
* also `issue_key`, `session_key`) counts only when the value is not an identifier of something else.
|
|
63
|
+
*/
|
|
64
|
+
function isCredentialName(name, value) {
|
|
65
|
+
if (CREDENTIAL_KEY.test(name))
|
|
66
|
+
return true;
|
|
67
|
+
return WEAK_CREDENTIAL_KEY.test(name) && !NOT_A_SECRET_UNDER_WEAK_KEY.test(value.trim());
|
|
68
|
+
}
|
|
69
|
+
/** A reference to a secret stored elsewhere, or a documentation placeholder where one goes. */
|
|
70
|
+
function isReferenceOrPlaceholder(secret) {
|
|
71
|
+
return CONTAINS_REFERENCE.test(secret) || ENV_REFERENCE.test(secret) || PLACEHOLDER_VALUE.test(secret);
|
|
72
|
+
}
|
|
55
73
|
function redactFormats(text, pass) {
|
|
56
74
|
let out = text;
|
|
57
75
|
for (const format of SECRET_FORMATS) {
|
|
58
76
|
out = out.replace(format.pattern, (match, prefix) => {
|
|
77
|
+
// Over a placeholder already written (`https://[OL_REDACTED:URL_CREDENTIALS]@host`): left as
|
|
78
|
+
// it is, so scrubbing twice changes nothing and counts nothing.
|
|
79
|
+
if (match.includes(PLACEHOLDER_PREFIX))
|
|
80
|
+
return match;
|
|
81
|
+
const kept = typeof prefix === "string" ? prefix : "";
|
|
82
|
+
if (format.skipPlaceholders && isReferenceOrPlaceholder(match.slice(kept.length)))
|
|
83
|
+
return match;
|
|
59
84
|
const fingerprint = format.fingerprint ? fingerprintOf(pass, match) : undefined;
|
|
60
|
-
return `${
|
|
85
|
+
return `${kept}${redacted(pass, format.type, fingerprint)}`;
|
|
61
86
|
});
|
|
62
87
|
}
|
|
63
88
|
return out;
|
|
64
89
|
}
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
/** Whether `offset` falls inside a placeholder already written, such as `[OL_REDACTED:GITHUB_TOKEN:<fp>]`. */
|
|
91
|
+
function insidePlaceholder(text, offset) {
|
|
92
|
+
const open = text.lastIndexOf(PLACEHOLDER_PREFIX, offset);
|
|
93
|
+
return open !== -1 && text.indexOf("]", open) >= offset;
|
|
67
94
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
95
|
+
function redactAssignments(text, pass) {
|
|
96
|
+
return text.replace(CREDENTIAL_ASSIGNMENT, (match, name, value, offset) =>
|
|
97
|
+
// `credential = client.beta(` and `credential: data.credential` are code, not a secret; the
|
|
98
|
+
// `TOKEN:<fp>` of a fingerprinted placeholder is the placeholder, not an assignment.
|
|
99
|
+
isCredentialValue(value) && !CODE_VALUE.test(value) && !insidePlaceholder(text, offset)
|
|
100
|
+
? `${name}${redacted(pass, "CREDENTIAL_ENV_VAR")}`
|
|
101
|
+
: match);
|
|
74
102
|
}
|
|
75
103
|
function scrubString(text, pass) {
|
|
76
104
|
if (!text)
|
|
77
105
|
return text;
|
|
78
|
-
|
|
79
|
-
return pass.options.personalData ? redactPersonalData(out, pass) : out;
|
|
106
|
+
return redactAssignments(redactFormats(text, pass), pass);
|
|
80
107
|
}
|
|
81
108
|
function scrubLeaf(value, pass, key) {
|
|
82
|
-
if (key !== undefined &&
|
|
109
|
+
if (key !== undefined && isCredentialName(key, value) && isCredentialValue(value)) {
|
|
83
110
|
// A recognised format keeps its prefix, type and fingerprint; anything else is just a credential.
|
|
84
111
|
const formatted = redactFormats(value, pass);
|
|
85
112
|
return formatted !== value ? formatted : redacted(pass, "CREDENTIAL_ENV_VAR");
|
|
@@ -89,60 +116,115 @@ function scrubLeaf(value, pass, key) {
|
|
|
89
116
|
function isPlainObject(value) {
|
|
90
117
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
91
118
|
}
|
|
119
|
+
/** A JSON Schema node (an MCP tool's input schema): `{"type": "array", ...}` describes data, holds none. */
|
|
120
|
+
function isSchemaNode(value) {
|
|
121
|
+
if (!isPlainObject(value))
|
|
122
|
+
return false;
|
|
123
|
+
return typeof value.type === "string" && JSON_SCHEMA_TYPES.has(value.type);
|
|
124
|
+
}
|
|
92
125
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* and fingerprint; a credential-named one is a credential; anything else is typed by the block
|
|
96
|
-
* (`ENV_VALUE`, `HEADER_VALUE`), which the backend does not read as a secret. A reference to a
|
|
97
|
-
* secret stored elsewhere (`${TOKEN}`, `Bearer ${TOKEN}`) stays readable.
|
|
126
|
+
* An MCP server definition: a server key holding a string or list (`command`, `url`, `args`). A
|
|
127
|
+
* schema's `properties` map with a `type` or `url` property holds objects there, and is not one.
|
|
98
128
|
*/
|
|
99
|
-
function
|
|
100
|
-
if (
|
|
101
|
-
return
|
|
102
|
-
|
|
129
|
+
function isServerDefinition(obj) {
|
|
130
|
+
if (isSchemaNode(obj))
|
|
131
|
+
return false;
|
|
132
|
+
return Object.entries(obj).some(([k, v]) => MCP_SERVER_KEYS.has(k) && (typeof v === "string" || Array.isArray(v)));
|
|
133
|
+
}
|
|
134
|
+
/** Whether a value can be redacted whole: not empty, not a reference, not already a placeholder. */
|
|
135
|
+
function isRedactable(value) {
|
|
136
|
+
return Boolean(value.trim()) && !CONTAINS_REFERENCE.test(value) && !ENV_REFERENCE.test(value.trim()) && !value.includes(PLACEHOLDER_PREFIX);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The backend's generic token (`HardcodedSecretRule`'s "Potential token/secret"): 40 or more
|
|
140
|
+
* letters, digits, `_` and `-`. In a URL only the query is searched, as the backend does: a host
|
|
141
|
+
* or path is not a token.
|
|
142
|
+
*/
|
|
143
|
+
function redactGenericTokens(value, pass) {
|
|
144
|
+
const replace = (text) => text.replace(GENERIC_TOKEN, (token) => (token.length >= 40 ? redacted(pass, "POTENTIAL_TOKEN") : token));
|
|
145
|
+
if (!value.includes("://"))
|
|
146
|
+
return replace(value);
|
|
147
|
+
const query = value.indexOf("?");
|
|
148
|
+
return query === -1 ? value : value.slice(0, query + 1) + replace(value.slice(query + 1));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* A value in an MCP server's env or headers block, redacted only when it is a secret: a known
|
|
152
|
+
* format keeps its prefix, type and fingerprint; a credential-named one is a credential; a 40+
|
|
153
|
+
* character token is a potential token, as the backend reads one. Anything else (`LOG_LEVEL=debug`)
|
|
154
|
+
* stays readable, as before scrubbing. A reference to a secret stored elsewhere (`${TOKEN}`,
|
|
155
|
+
* `Bearer ${TOKEN}`) stays readable.
|
|
156
|
+
*/
|
|
157
|
+
function redactBlockValue(value, name, pass) {
|
|
158
|
+
if (!isRedactable(value))
|
|
103
159
|
return value;
|
|
104
160
|
const formatted = redactFormats(value, pass);
|
|
105
161
|
if (formatted !== value)
|
|
106
162
|
return formatted;
|
|
107
|
-
|
|
163
|
+
if (isCredentialName(name, value) && isCredentialValue(value))
|
|
164
|
+
return redacted(pass, "CREDENTIAL_ENV_VAR");
|
|
165
|
+
return redactGenericTokens(redactAssignments(value, pass), pass);
|
|
108
166
|
}
|
|
109
|
-
function walkValueBlock(block,
|
|
167
|
+
function walkValueBlock(block, pass, depth) {
|
|
110
168
|
const out = {};
|
|
111
169
|
for (const [name, v] of Object.entries(block)) {
|
|
112
|
-
out[name] = typeof v === "string" ? redactBlockValue(v, name,
|
|
170
|
+
out[name] = typeof v === "string" ? redactBlockValue(v, name, pass) : walk(v, pass, name, depth + 1);
|
|
113
171
|
}
|
|
114
172
|
return out;
|
|
115
173
|
}
|
|
174
|
+
/** A value in a credential container: a credential whatever its shape (a known format keeps its type). */
|
|
175
|
+
function redactContainerValue(value, pass) {
|
|
176
|
+
if (!isRedactable(value))
|
|
177
|
+
return value;
|
|
178
|
+
const formatted = redactFormats(value, pass);
|
|
179
|
+
return formatted !== value ? formatted : redacted(pass, "CREDENTIAL_ENV_VAR");
|
|
180
|
+
}
|
|
116
181
|
/** `["--api-key", "BSA..."]`: the argument after a credential flag is the credential. */
|
|
117
182
|
function walkArgs(args, pass, depth) {
|
|
118
183
|
return args.map((arg, i) => {
|
|
119
184
|
const flag = typeof args[i - 1] === "string" ? CREDENTIAL_FLAG.exec(args[i - 1]) : null;
|
|
120
|
-
if (flag &&
|
|
185
|
+
if (flag && typeof arg === "string" && isCredentialName(flag[1], arg) && isCredentialValue(arg)) {
|
|
121
186
|
const formatted = redactFormats(arg, pass);
|
|
122
187
|
return formatted !== arg ? formatted : redacted(pass, "CREDENTIAL_ENV_VAR");
|
|
123
188
|
}
|
|
124
189
|
return walk(arg, pass, "args", depth + 1);
|
|
125
190
|
});
|
|
126
191
|
}
|
|
127
|
-
/**
|
|
192
|
+
/**
|
|
193
|
+
* A credential container (`copilotTokens: {"https://github.com:ada": "gho_..."}`): every string
|
|
194
|
+
* value is a credential whatever its key, so a token with no known format is still redacted.
|
|
195
|
+
* Fields ending in `id` stay readable.
|
|
196
|
+
*/
|
|
197
|
+
function walkCredentialContainer(container, pass, depth) {
|
|
198
|
+
const out = {};
|
|
199
|
+
for (const [name, v] of Object.entries(container)) {
|
|
200
|
+
const isCredential = typeof v === "string" && !CONTAINER_KEEP.test(name);
|
|
201
|
+
out[name] = isCredential ? redactContainerValue(v, pass) : walk(v, pass, name, depth + 1);
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
205
|
+
/** One child of an object: MCP value blocks, credential containers and `args` get their structural rule. */
|
|
128
206
|
function walkChild(key, value, inServer, pass, depth) {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
207
|
+
const isBlock = inServer && MCP_VALUE_BLOCKS.has(key);
|
|
208
|
+
const isData = isPlainObject(value) && !isSchemaNode(value);
|
|
209
|
+
if (isBlock && isData)
|
|
210
|
+
return walkValueBlock(value, pass, depth);
|
|
211
|
+
if (CREDENTIAL_CONTAINER.test(key) && isData)
|
|
212
|
+
return walkCredentialContainer(value, pass, depth);
|
|
132
213
|
if (key === "args" && Array.isArray(value))
|
|
133
214
|
return walkArgs(value, pass, depth);
|
|
134
215
|
return walk(value, pass, key, depth + 1);
|
|
135
216
|
}
|
|
136
217
|
function walkObject(obj, pass, depth) {
|
|
137
|
-
const inServer =
|
|
218
|
+
const inServer = isServerDefinition(obj);
|
|
138
219
|
const out = {};
|
|
139
220
|
for (const [k, v] of Object.entries(obj))
|
|
140
221
|
out[k] = walkChild(k, v, inServer, pass, depth);
|
|
141
222
|
return out;
|
|
142
223
|
}
|
|
143
224
|
function walk(value, pass, key, depth) {
|
|
225
|
+
// The TOO_DEEP placeholder a first pass left at this depth stays as it is.
|
|
144
226
|
if (depth > MAX_DEPTH)
|
|
145
|
-
return redacted(pass, "TOO_DEEP");
|
|
227
|
+
return value === placeholder("TOO_DEEP") ? value : redacted(pass, "TOO_DEEP");
|
|
146
228
|
if (Array.isArray(value))
|
|
147
229
|
return value.map((item) => walk(item, pass, key, depth + 1));
|
|
148
230
|
if (isPlainObject(value))
|
|
@@ -152,8 +234,11 @@ function walk(value, pass, key, depth) {
|
|
|
152
234
|
/**
|
|
153
235
|
* A deep copy of `value` with every string scrubbed and every value under a credential-named key
|
|
154
236
|
* redacted, and how many of each type were redacted. Non-string leaves are returned as they are.
|
|
237
|
+
* When the organization has switched scrubbing off, `value` itself, with no hits.
|
|
155
238
|
*/
|
|
156
239
|
export function scrub(value, options = {}) {
|
|
240
|
+
if (scrubbingSwitchedOff())
|
|
241
|
+
return { value, hits: {} };
|
|
157
242
|
const pass = { options, hits: {} };
|
|
158
243
|
return { value: walk(value, pass, undefined, 0), hits: pass.hits };
|
|
159
244
|
}
|
|
@@ -161,8 +246,13 @@ export function scrub(value, options = {}) {
|
|
|
161
246
|
export function scrubValue(value, options = {}) {
|
|
162
247
|
return scrub(value, options).value;
|
|
163
248
|
}
|
|
164
|
-
/**
|
|
249
|
+
/**
|
|
250
|
+
* A copy of `text` with every secret redacted;
|
|
251
|
+
* `text` itself when the organization has switched scrubbing off.
|
|
252
|
+
*/
|
|
165
253
|
export function scrubText(text, options = {}) {
|
|
254
|
+
if (scrubbingSwitchedOff())
|
|
255
|
+
return text;
|
|
166
256
|
return scrubString(text, { options, hits: {} });
|
|
167
257
|
}
|
|
168
258
|
/**
|
|
@@ -171,6 +261,8 @@ export function scrubText(text, options = {}) {
|
|
|
171
261
|
*/
|
|
172
262
|
export function scrubFields(record, fields, options = {}) {
|
|
173
263
|
const out = { ...record };
|
|
264
|
+
if (scrubbingSwitchedOff())
|
|
265
|
+
return out;
|
|
174
266
|
for (const field of fields) {
|
|
175
267
|
if (typeof out[field] === "string")
|
|
176
268
|
out[field] = scrubText(out[field], options);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the organization has switched scrubbing off (OPT-942).
|
|
3
|
+
*
|
|
4
|
+
* The backend sends `scrub_pii` with the prompt policy on startup and inventory responses, and
|
|
5
|
+
* the senders store it in the org config file beside `collect_prompts`. Only an explicit `false`
|
|
6
|
+
* turns scrubbing off: no file yet, an unreadable one or no field means scrub, so an endpoint
|
|
7
|
+
* that has not heard from its organization yet scrubs.
|
|
8
|
+
*
|
|
9
|
+
* Read on every call rather than once per process, so a change reaches a sender as soon as the
|
|
10
|
+
* file is rewritten. The file is a few hundred bytes.
|
|
11
|
+
*/
|
|
12
|
+
export declare function orgConfigPath(): string;
|
|
13
|
+
export declare function scrubbingSwitchedOff(): boolean;
|
|
14
|
+
//# sourceMappingURL=org-setting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-setting.d.ts","sourceRoot":"","sources":["../src/org-setting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAQ9C"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the organization has switched scrubbing off (OPT-942).
|
|
3
|
+
*
|
|
4
|
+
* The backend sends `scrub_pii` with the prompt policy on startup and inventory responses, and
|
|
5
|
+
* the senders store it in the org config file beside `collect_prompts`. Only an explicit `false`
|
|
6
|
+
* turns scrubbing off: no file yet, an unreadable one or no field means scrub, so an endpoint
|
|
7
|
+
* that has not heard from its organization yet scrubs.
|
|
8
|
+
*
|
|
9
|
+
* Read on every call rather than once per process, so a change reaches a sender as soon as the
|
|
10
|
+
* file is rewritten. The file is a few hundred bytes.
|
|
11
|
+
*/
|
|
12
|
+
import { readFileSync } from "node:fs";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
export function orgConfigPath() {
|
|
16
|
+
return join(homedir(), ".optimuslabs", "management", "org", "config.json");
|
|
17
|
+
}
|
|
18
|
+
export function scrubbingSwitchedOff() {
|
|
19
|
+
try {
|
|
20
|
+
const config = JSON.parse(readFileSync(orgConfigPath(), "utf8"));
|
|
21
|
+
return Boolean(config) && typeof config === "object" && config.scrub_pii === false;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// No file yet, or not JSON: scrub.
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=org-setting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-setting.js","sourceRoot":"","sources":["../src/org-setting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,CAAY,CAAC;QAC5E,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAK,MAAkC,CAAC,SAAS,KAAK,KAAK,CAAC;IAClH,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/rules.d.ts
CHANGED
|
@@ -13,20 +13,27 @@
|
|
|
13
13
|
export interface SecretFormat {
|
|
14
14
|
type: string;
|
|
15
15
|
fingerprint: boolean;
|
|
16
|
+
skipPlaceholders: boolean;
|
|
16
17
|
/** Global, for `replace`. */
|
|
17
18
|
pattern: RegExp;
|
|
18
19
|
}
|
|
19
20
|
export declare const SECRET_FORMATS: readonly SecretFormat[];
|
|
20
21
|
export declare const CREDENTIAL_KEY: RegExp;
|
|
22
|
+
export declare const WEAK_CREDENTIAL_KEY: RegExp;
|
|
23
|
+
export declare const NOT_A_SECRET_UNDER_WEAK_KEY: RegExp;
|
|
24
|
+
export declare const CREDENTIAL_CONTAINER: RegExp;
|
|
25
|
+
export declare const CONTAINER_KEEP: RegExp;
|
|
21
26
|
export declare const CREDENTIAL_ASSIGNMENT: RegExp;
|
|
27
|
+
export declare const CODE_VALUE: RegExp;
|
|
22
28
|
export declare const ENV_REFERENCE: RegExp;
|
|
23
29
|
export declare const CONTAINS_REFERENCE: RegExp;
|
|
30
|
+
export declare const PLACEHOLDER_VALUE: RegExp;
|
|
24
31
|
export declare const CREDENTIAL_FLAG: RegExp;
|
|
25
|
-
/**
|
|
26
|
-
export declare const MCP_VALUE_BLOCKS:
|
|
32
|
+
/** The blocks of an MCP server definition whose values are checked for secrets (`env`, `headers`). */
|
|
33
|
+
export declare const MCP_VALUE_BLOCKS: ReadonlySet<string>;
|
|
34
|
+
/** The backend's generic token shape; a match of 40 or more characters is a potential token. */
|
|
35
|
+
export declare const GENERIC_TOKEN: RegExp;
|
|
27
36
|
export declare const MCP_SERVER_KEYS: ReadonlySet<string>;
|
|
28
|
-
export declare const
|
|
29
|
-
export declare const RESERVED_EMAIL_DOMAIN: RegExp;
|
|
30
|
-
export declare const HOME_DIRECTORY: RegExp;
|
|
37
|
+
export declare const JSON_SCHEMA_TYPES: ReadonlySet<string>;
|
|
31
38
|
export declare const MIN_CREDENTIAL_LENGTH: number;
|
|
32
39
|
//# sourceMappingURL=rules.d.ts.map
|
package/dist/rules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkCH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAWD,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAK/C,CAAC;AACJ,eAAO,MAAM,cAAc,QAAuC,CAAC;AACnE,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,2BAA2B,QAA6D,CAAC;AACtG,eAAO,MAAM,oBAAoB,QAA6C,CAAC;AAC/E,eAAO,MAAM,cAAc,QAAsD,CAAC;AAClF,eAAO,MAAM,qBAAqB,QAA6C,CAAC;AAChF,eAAO,MAAM,UAAU,QAAmC,CAAC;AAC3D,eAAO,MAAM,aAAa,QAAsC,CAAC;AACjE,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,iBAAiB,QAA0C,CAAC;AACzE,eAAO,MAAM,eAAe,QAAwC,CAAC;AACrE,sGAAsG;AACtG,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAA0C,CAAC;AAC5F,gGAAgG;AAChG,eAAO,MAAM,aAAa,QAAqC,CAAC;AAChE,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAA+C,CAAC;AAChG,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAA0C,CAAC;AAC7F,eAAO,MAAM,qBAAqB,QAA8B,CAAC"}
|
package/dist/rules.js
CHANGED
|
@@ -21,18 +21,25 @@ function compile(spec, global) {
|
|
|
21
21
|
export const SECRET_FORMATS = RULES.formats.map((f) => ({
|
|
22
22
|
type: f.type,
|
|
23
23
|
fingerprint: f.fingerprint,
|
|
24
|
+
skipPlaceholders: Boolean(f.skip_placeholders),
|
|
24
25
|
pattern: compile(f, true),
|
|
25
26
|
}));
|
|
26
27
|
export const CREDENTIAL_KEY = compile(RULES.credential_key, false);
|
|
28
|
+
export const WEAK_CREDENTIAL_KEY = compile(RULES.weak_credential_key, false);
|
|
29
|
+
export const NOT_A_SECRET_UNDER_WEAK_KEY = new RegExp(RULES.weak_credential_key.not_a_secret_pattern);
|
|
30
|
+
export const CREDENTIAL_CONTAINER = compile(RULES.credential_container, false);
|
|
31
|
+
export const CONTAINER_KEEP = new RegExp(RULES.credential_container.keep_pattern);
|
|
27
32
|
export const CREDENTIAL_ASSIGNMENT = compile(RULES.credential_assignment, true);
|
|
33
|
+
export const CODE_VALUE = compile(RULES.code_value, false);
|
|
28
34
|
export const ENV_REFERENCE = compile(RULES.env_reference, false);
|
|
29
35
|
export const CONTAINS_REFERENCE = compile(RULES.contains_reference, false);
|
|
36
|
+
export const PLACEHOLDER_VALUE = compile(RULES.placeholder_value, false);
|
|
30
37
|
export const CREDENTIAL_FLAG = compile(RULES.credential_flag, false);
|
|
31
|
-
/**
|
|
32
|
-
export const MCP_VALUE_BLOCKS = RULES.mcp_value_blocks.blocks;
|
|
38
|
+
/** The blocks of an MCP server definition whose values are checked for secrets (`env`, `headers`). */
|
|
39
|
+
export const MCP_VALUE_BLOCKS = new Set(RULES.mcp_value_blocks.blocks);
|
|
40
|
+
/** The backend's generic token shape; a match of 40 or more characters is a potential token. */
|
|
41
|
+
export const GENERIC_TOKEN = compile(RULES.generic_token, true);
|
|
33
42
|
export const MCP_SERVER_KEYS = new Set(RULES.mcp_value_blocks.server_keys);
|
|
34
|
-
export const
|
|
35
|
-
export const RESERVED_EMAIL_DOMAIN = compile(RULES.reserved_email_domain, false);
|
|
36
|
-
export const HOME_DIRECTORY = compile(RULES.home_directory, true);
|
|
43
|
+
export const JSON_SCHEMA_TYPES = new Set(RULES.json_schema_types.types);
|
|
37
44
|
export const MIN_CREDENTIAL_LENGTH = RULES.min_credential_length;
|
|
38
45
|
//# sourceMappingURL=rules.js.map
|
package/dist/rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAwC5C,gGAAgG;AAChG,0EAA0E;AAC1E,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,eAAe,CAAc,CAAC;AAE3E,kGAAkG;AAClG,SAAS,OAAO,CAAC,IAAiB,EAAE,MAAe;IACjD,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAA4B,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/E,IAAI,EAAE,CAAC,CAAC,IAAI;IACZ,WAAW,EAAE,CAAC,CAAC,WAAW;IAC1B,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC;CAC1B,CAAC,CAAC,CAAC;AACJ,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;AACnE,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;AACtG,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;AAChF,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;AACzE,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;AACrE,sGAAsG;AACtG,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAC5F,gGAAgG;AAChG,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AAChE,MAAM,CAAC,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAC7F,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC"}
|
package/package.json
CHANGED
package/rules.json
CHANGED
|
@@ -14,7 +14,15 @@
|
|
|
14
14
|
"type": "URL_CREDENTIALS",
|
|
15
15
|
"pattern": "\\b([a-z][a-z0-9+.-]{0,31}:\\/\\/[^\\s:@/\"'`]{1,256}:)[^\\s@/\"'`]{1,256}(?=@)",
|
|
16
16
|
"ignore_case": true,
|
|
17
|
-
"fingerprint": false
|
|
17
|
+
"fingerprint": false,
|
|
18
|
+
"skip_placeholders": true
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"type": "URL_CREDENTIALS",
|
|
22
|
+
"pattern": "\\b([a-z][a-z0-9+.-]{0,31}:\\/\\/)[^\\s:@/\"'`]{16,255}(?=@)",
|
|
23
|
+
"ignore_case": true,
|
|
24
|
+
"fingerprint": false,
|
|
25
|
+
"skip_placeholders": true
|
|
18
26
|
},
|
|
19
27
|
{
|
|
20
28
|
"type": "ANTHROPIC_KEY",
|
|
@@ -86,6 +94,11 @@
|
|
|
86
94
|
"pattern": "\\b(pplx-)[A-Za-z0-9]{32,}",
|
|
87
95
|
"fingerprint": true
|
|
88
96
|
},
|
|
97
|
+
{
|
|
98
|
+
"type": "BRAVE_KEY",
|
|
99
|
+
"pattern": "\\b(BSA)[A-Za-z0-9_-]{20,}",
|
|
100
|
+
"fingerprint": true
|
|
101
|
+
},
|
|
89
102
|
{
|
|
90
103
|
"type": "JWT",
|
|
91
104
|
"pattern": "\\beyJ[A-Za-z0-9_-]{8,}\\.eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}",
|
|
@@ -95,22 +108,39 @@
|
|
|
95
108
|
"type": "BEARER_TOKEN",
|
|
96
109
|
"pattern": "\\b(Bearer\\s+)[A-Za-z0-9._~+/=-]{16,}",
|
|
97
110
|
"ignore_case": true,
|
|
98
|
-
"fingerprint": false
|
|
111
|
+
"fingerprint": false,
|
|
112
|
+
"skip_placeholders": true
|
|
99
113
|
},
|
|
100
114
|
{
|
|
101
115
|
"type": "BASIC_AUTH",
|
|
102
|
-
"pattern": "\\b(Basic\\s+)[A-Za-z0-9+/=]{
|
|
116
|
+
"pattern": "\\b(Basic\\s+)(?=[A-Za-z0-9+/=]{0,512}(?:[0-9+/=]|[a-z][A-Z]))(?:[A-Za-z0-9+/]{4}){2,128}(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)(?![A-Za-z0-9+/=])",
|
|
103
117
|
"fingerprint": false
|
|
104
118
|
}
|
|
105
119
|
],
|
|
106
120
|
"credential_key": {
|
|
107
|
-
"pattern": "(?:
|
|
121
|
+
"pattern": "(?:api[_-]?key|apikey|secret|token|password|passwd|credential|private[_-]?key|(?:secret|signing|encryption)[_-]?key|access[_-]?key|authorization|token[_-]?cache(?:v\\d+)?)$",
|
|
108
122
|
"ignore_case": true
|
|
109
123
|
},
|
|
124
|
+
"weak_credential_key": {
|
|
125
|
+
"description": "A name ending in `_key` (DEPLOY_SSH_KEY, LICENSE_KEY) is a credential only when its value is not an identifier of something else: an issue key (INCIDENT-31138) or a session key of three or more colon-separated lowercase parts (agent:main:slack). Secret, signing and encryption keys are always credentials (credential_key).",
|
|
126
|
+
"pattern": "[_.-]key$",
|
|
127
|
+
"ignore_case": true,
|
|
128
|
+
"not_a_secret_pattern": "^[a-z0-9_-]+(?::[a-z0-9_+.-]+){2,}$|^[A-Z][A-Z0-9]{1,15}-[0-9]{1,9}$"
|
|
129
|
+
},
|
|
130
|
+
"credential_container": {
|
|
131
|
+
"description": "An object whose every string value is a credential, whatever its own key (Copilot's copilotTokens maps host:user to a token). Fields ending in id stay (Codex tokens.account_id).",
|
|
132
|
+
"pattern": "(?:tokens|secrets|credentials|api[_-]?keys)$",
|
|
133
|
+
"ignore_case": true,
|
|
134
|
+
"keep_pattern": "(?:^|[_-])id$|[a-z]Id$"
|
|
135
|
+
},
|
|
110
136
|
"credential_assignment": {
|
|
111
137
|
"pattern": "((?:api[_-]?key|apikey|secret|token|password|passwd|credential|private[_-]?key|access[_-]?key)[\"']?\\s*[:=]\\s*[\"']?)([^\\s\"'`,;&)}\\]]{8,})",
|
|
112
138
|
"ignore_case": true
|
|
113
139
|
},
|
|
140
|
+
"code_value": {
|
|
141
|
+
"description": "A value after a credential name in text that is code, not a secret: a call or block opener (`os.environ.get(`, `T.type_alias{`), a template (`{client_private_key}`, `<paste_key_here>`), or a variable named for a credential (`data.credential`, `walletKey`, `this.env.VAPID_PRIVATE_KEY`). A secret that merely contains `(` or `{` is still one.",
|
|
142
|
+
"pattern": "^[A-Za-z_$][\\w$.]*[({]$|^\\{[\\w.]{1,128}$|^<[^<>]{1,64}>$|^(?=[\\w$.]{0,256}(?:\\.|[a-z][A-Z]))(?=[\\w$.]{0,256}(?:[Kk]ey|KEY|[Ss]ecret|SECRET|[Tt]oken|TOKEN|[Pp]assw|PASSW|[Cc]redential|CREDENTIAL|\\.env\\.|\\.environ\\b))[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*$"
|
|
143
|
+
},
|
|
114
144
|
"env_reference": {
|
|
115
145
|
"pattern": "^(?:\\$|\\{\\{|process\\.env\\.)|^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$"
|
|
116
146
|
},
|
|
@@ -118,18 +148,22 @@
|
|
|
118
148
|
"description": "A reference to a secret stored elsewhere anywhere in a value (`Bearer ${TOKEN}`): the value stays readable.",
|
|
119
149
|
"pattern": "\\$\\{[^}]{1,128}\\}|\\$env:|process\\.env\\."
|
|
120
150
|
},
|
|
151
|
+
"placeholder_value": {
|
|
152
|
+
"description": "A documentation placeholder where a secret goes (`<your_key>`, `YOUR_API_TOKEN`, `my_secret`): not a secret, so not redacted and never a finding.",
|
|
153
|
+
"pattern": "^<[^<>]{1,64}>$|(?:^|[_.-])(?:YOUR|your|MY|my)[_-]|_(?:TOKEN|KEY|SECRET|PASSWORD)$"
|
|
154
|
+
},
|
|
121
155
|
"credential_flag": {
|
|
122
156
|
"description": "A command-line flag whose next argument is a credential (`--api-key`, `--token`); group 1 is the name, tested against credential_key.",
|
|
123
157
|
"pattern": "^-{1,2}([A-Za-z0-9_.-]{1,64})$"
|
|
124
158
|
},
|
|
125
159
|
"mcp_value_blocks": {
|
|
126
|
-
"description": "Blocks inside an MCP server definition whose
|
|
127
|
-
"blocks":
|
|
128
|
-
"env"
|
|
129
|
-
"environment"
|
|
130
|
-
"headers"
|
|
131
|
-
"http_headers"
|
|
132
|
-
|
|
160
|
+
"description": "Blocks inside an MCP server definition whose values are checked for secrets: a known format, a value under a credential-named key, or a generic token (generic_token) is redacted; any other value stays. A server definition is an object with one of server_keys. A server key counts only when its value is a string or a list, so a JSON Schema `properties` map with a `type` or `url` property is not a server.",
|
|
161
|
+
"blocks": [
|
|
162
|
+
"env",
|
|
163
|
+
"environment",
|
|
164
|
+
"headers",
|
|
165
|
+
"http_headers"
|
|
166
|
+
],
|
|
133
167
|
"server_keys": [
|
|
134
168
|
"command",
|
|
135
169
|
"args",
|
|
@@ -140,15 +174,88 @@
|
|
|
140
174
|
"type"
|
|
141
175
|
]
|
|
142
176
|
},
|
|
143
|
-
"
|
|
144
|
-
"
|
|
177
|
+
"generic_token": {
|
|
178
|
+
"description": "The backend's generic token (HardcodedSecretRule.GENERIC_TOKEN_PATTERN): in an MCP env or headers value, a match of 40 or more characters is redacted as POTENTIAL_TOKEN, which the backend reads as a potential token/secret. In a URL only the query is searched.",
|
|
179
|
+
"pattern": "\\b[a-zA-Z0-9][a-zA-Z0-9_-]{31,}\\b"
|
|
145
180
|
},
|
|
146
|
-
"
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
181
|
+
"json_schema_types": {
|
|
182
|
+
"description": "An object whose `type` is one of these is a JSON Schema node (an MCP tool's input schema), not data: never a credential container or an MCP value block.",
|
|
183
|
+
"types": [
|
|
184
|
+
"object",
|
|
185
|
+
"array",
|
|
186
|
+
"string",
|
|
187
|
+
"number",
|
|
188
|
+
"integer",
|
|
189
|
+
"boolean",
|
|
190
|
+
"null"
|
|
191
|
+
]
|
|
152
192
|
},
|
|
153
|
-
"min_credential_length": 8
|
|
193
|
+
"min_credential_length": 8,
|
|
194
|
+
"admin_summary": {
|
|
195
|
+
"description": "What admins are told is redacted (org settings, Data redaction; OPT-953): one item per kind, naming the rule groups it describes; \"list\": \"formats\" adds the format types as a list. \"items\" are the names or kinds the other items remove. The backend sends these items; a backend test fails when a rule group that redacts has no item here.",
|
|
196
|
+
"lines": [
|
|
197
|
+
{
|
|
198
|
+
"title": "API keys and tokens",
|
|
199
|
+
"rules": [
|
|
200
|
+
"formats"
|
|
201
|
+
],
|
|
202
|
+
"list": "formats",
|
|
203
|
+
"text": "Known vendor formats, replaced by [OL_REDACTED:<format>]. The vendor's prefix stays."
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"title": "Credentials by name",
|
|
207
|
+
"rules": [
|
|
208
|
+
"credential_key",
|
|
209
|
+
"weak_credential_key",
|
|
210
|
+
"credential_assignment",
|
|
211
|
+
"credential_flag"
|
|
212
|
+
],
|
|
213
|
+
"text": "Values named like a credential (api_key, token, secret, password), in any format.",
|
|
214
|
+
"items": [
|
|
215
|
+
"api_key",
|
|
216
|
+
"apikey",
|
|
217
|
+
"secret",
|
|
218
|
+
"token",
|
|
219
|
+
"password",
|
|
220
|
+
"passwd",
|
|
221
|
+
"credential",
|
|
222
|
+
"private_key",
|
|
223
|
+
"secret_key",
|
|
224
|
+
"signing_key",
|
|
225
|
+
"encryption_key",
|
|
226
|
+
"access_key",
|
|
227
|
+
"authorization",
|
|
228
|
+
"token_cache",
|
|
229
|
+
"*_key"
|
|
230
|
+
]
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"title": "Token maps",
|
|
234
|
+
"rules": [
|
|
235
|
+
"credential_container"
|
|
236
|
+
],
|
|
237
|
+
"text": "Every value in a map of tokens, such as Copilot's copilotTokens.",
|
|
238
|
+
"items": [
|
|
239
|
+
"*tokens",
|
|
240
|
+
"*secrets",
|
|
241
|
+
"*credentials",
|
|
242
|
+
"*api_keys"
|
|
243
|
+
]
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"title": "MCP server env and headers",
|
|
247
|
+
"rules": [
|
|
248
|
+
"mcp_value_blocks",
|
|
249
|
+
"generic_token"
|
|
250
|
+
],
|
|
251
|
+
"text": "Secrets in an MCP server's env and headers: known formats, credential names and long tokens. Other values stay.",
|
|
252
|
+
"items": [
|
|
253
|
+
"env",
|
|
254
|
+
"environment",
|
|
255
|
+
"headers",
|
|
256
|
+
"http_headers"
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
}
|
|
154
261
|
}
|