@mnemonik/shared 7.142.0 → 7.143.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/dist/ast/grammars.d.ts +1 -1
- package/dist/ast/grammars.d.ts.map +1 -1
- package/dist/ast/grammars.js +10 -1
- package/dist/ast/grammars.js.map +1 -1
- package/dist/codeScanner.d.ts +3 -0
- package/dist/codeScanner.d.ts.map +1 -1
- package/dist/codeScanner.js +5 -0
- package/dist/codeScanner.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/sourceRedaction.d.ts.map +1 -1
- package/dist/sourceRedaction.js +364 -2
- package/dist/sourceRedaction.js.map +1 -1
- package/package.json +1 -1
- package/queries/sql.tags.scm +5 -0
- package/queries/swift.tags.scm +11 -0
- package/scripts/jsx-bare-ampersand.patch +61 -0
- package/scripts/vendor-grammars.ts +274 -8
- package/src/ast/grammars.ts +10 -1
- package/src/codeScanner.ts +6 -0
- package/src/index.ts +2 -0
- package/src/sourceRedaction.ts +391 -2
- package/wasm/javascript.wasm +0 -0
- package/wasm/lua.LICENSE +21 -0
- package/wasm/lua.tags.scm +36 -0
- package/wasm/lua.wasm +0 -0
- package/wasm/sql.LICENSE +21 -0
- package/wasm/sql.tags.scm +5 -0
- package/wasm/sql.wasm +0 -0
- package/wasm/swift.LICENSE +21 -0
- package/wasm/swift.tags.scm +11 -0
- package/wasm/swift.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
package/src/sourceRedaction.ts
CHANGED
|
@@ -27,7 +27,15 @@ export async function scrubSourceSecrets(text: string, filePath: string): Promis
|
|
|
27
27
|
? 'python'
|
|
28
28
|
: ['.sh', '.bash', '.zsh'].includes(extension)
|
|
29
29
|
? 'bash'
|
|
30
|
-
:
|
|
30
|
+
: extension === '.swift'
|
|
31
|
+
? 'swift'
|
|
32
|
+
: extension === '.sql'
|
|
33
|
+
? 'sql'
|
|
34
|
+
: extension === '.lua'
|
|
35
|
+
? 'lua'
|
|
36
|
+
: extension === '.rs'
|
|
37
|
+
? 'rust'
|
|
38
|
+
: null;
|
|
31
39
|
if (!text || !language || Buffer.byteLength(text, 'utf8') > MAX_AST_PARSE_BYTES) {
|
|
32
40
|
return scrubPayload(text);
|
|
33
41
|
}
|
|
@@ -41,10 +49,19 @@ export async function scrubSourceSecrets(text: string, filePath: string): Promis
|
|
|
41
49
|
tree = parser.parse(text);
|
|
42
50
|
if (!tree || tree.rootNode.hasError) return scrubPayload(text);
|
|
43
51
|
const root = tree.rootNode;
|
|
52
|
+
|
|
44
53
|
const redacted =
|
|
45
54
|
language === 'bash'
|
|
46
55
|
? redactShellNode(root, commandLineCredentialRanges(text))
|
|
47
|
-
:
|
|
56
|
+
: language === 'swift'
|
|
57
|
+
? redactSwiftNode(root)
|
|
58
|
+
: language === 'sql'
|
|
59
|
+
? redactSqlNode(root)
|
|
60
|
+
: language === 'lua'
|
|
61
|
+
? redactLuaNode(root)
|
|
62
|
+
: language === 'rust'
|
|
63
|
+
? redactRustNode(root)
|
|
64
|
+
: redactNode(root);
|
|
48
65
|
return text.slice(0, root.startIndex) + redacted + text.slice(root.endIndex);
|
|
49
66
|
} catch {
|
|
50
67
|
return scrubPayload(text);
|
|
@@ -54,6 +71,378 @@ export async function scrubSourceSecrets(text: string, filePath: string): Promis
|
|
|
54
71
|
}
|
|
55
72
|
}
|
|
56
73
|
|
|
74
|
+
/** Rust raw/byte prefixes belong to the delimiter, never to the credential payload. */
|
|
75
|
+
function redactRustNode(node: Node, sensitive = false, labeled = new Set<number>()): string {
|
|
76
|
+
sensitive ||= labeled.has(node.id);
|
|
77
|
+
const original = node.text;
|
|
78
|
+
const type = node.type;
|
|
79
|
+
if (type === 'line_comment') return '//' + scrubPayload(original.slice(2));
|
|
80
|
+
if (type === 'block_comment') return '/*' + scrubPayload(original.slice(2, -2)) + '*/';
|
|
81
|
+
if (sensitive && ['integer_literal', 'float_literal', 'char_literal'].includes(type))
|
|
82
|
+
return '"' + redactSecretValue(original) + '"';
|
|
83
|
+
if (type === 'string_literal' || type === 'raw_string_literal') {
|
|
84
|
+
const start = original.indexOf('"') + 1;
|
|
85
|
+
const end = original.lastIndexOf('"');
|
|
86
|
+
return (
|
|
87
|
+
original.slice(0, start) +
|
|
88
|
+
literalPayload(original.slice(start, end), sensitive) +
|
|
89
|
+
original.slice(end)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const label = (key: Node | null): boolean => {
|
|
93
|
+
if (!key) return false;
|
|
94
|
+
const name = (key.childForFieldName('field') ?? key).text;
|
|
95
|
+
return SECRET_LABEL_RE.test(
|
|
96
|
+
['string_literal', 'raw_string_literal'].includes(key.type)
|
|
97
|
+
? name.slice(name.indexOf('"') + 1, name.lastIndexOf('"'))
|
|
98
|
+
: name.replace(/^r#/, '')
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
const mark = (pattern: Node | null, value: Node | null): void => {
|
|
102
|
+
if (!pattern || !value) return;
|
|
103
|
+
if (['ref_pattern', 'mut_pattern', 'reference_pattern'].includes(pattern.type)) {
|
|
104
|
+
mark(pattern.firstNamedChild, value);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (label(pattern)) labeled.add(value.id);
|
|
108
|
+
else if (pattern.type === 'tuple_pattern' && value.type === 'tuple_expression')
|
|
109
|
+
pattern.namedChildren.forEach((part, index) =>
|
|
110
|
+
mark(part, value.namedChildren[index] ?? null)
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
if (type === 'let_declaration')
|
|
114
|
+
mark(node.childForFieldName('pattern'), node.childForFieldName('value'));
|
|
115
|
+
if (type === 'const_item' || type === 'static_item')
|
|
116
|
+
mark(node.childForFieldName('name'), node.childForFieldName('value'));
|
|
117
|
+
if (type === 'field_initializer')
|
|
118
|
+
mark(node.childForFieldName('field'), node.childForFieldName('value'));
|
|
119
|
+
if (type === 'assignment_expression')
|
|
120
|
+
mark(node.childForFieldName('left'), node.childForFieldName('right'));
|
|
121
|
+
// Attribute/macro arguments are token trees, but literal key/value boundaries remain explicit.
|
|
122
|
+
if (type === 'token_tree') {
|
|
123
|
+
const children = node.children.filter(
|
|
124
|
+
(child) => !['line_comment', 'block_comment'].includes(child.type)
|
|
125
|
+
);
|
|
126
|
+
let valueSensitive = sensitive;
|
|
127
|
+
let genericDepth = 0;
|
|
128
|
+
for (const [index, child] of children.entries()) {
|
|
129
|
+
const previous = children[index - 1];
|
|
130
|
+
// Token trees flatten type arguments too. Their commas and associated-type
|
|
131
|
+
// bindings are not macro value boundaries; const arguments are not values.
|
|
132
|
+
if (
|
|
133
|
+
child.text === '<' &&
|
|
134
|
+
(genericDepth > 0 || ['::', '=', ':', '('].includes(previous?.text ?? ''))
|
|
135
|
+
) {
|
|
136
|
+
genericDepth++;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (genericDepth > 0) {
|
|
140
|
+
if (child.text === '>' || child.text === '>>') genericDepth -= child.text.length;
|
|
141
|
+
genericDepth = Math.max(0, genericDepth);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const nextKey = children[index + 1];
|
|
145
|
+
const nextBinding =
|
|
146
|
+
nextKey &&
|
|
147
|
+
['identifier', 'string_literal', 'raw_string_literal'].includes(nextKey.type) &&
|
|
148
|
+
['=', ':'].includes(children[index + 2]?.text ?? '');
|
|
149
|
+
if (child.text === ';' || (child.text === ',' && nextBinding)) valueSensitive = sensitive;
|
|
150
|
+
else if (['=', ':'].includes(child.text) && label(previous ?? null)) valueSensitive = true;
|
|
151
|
+
else if (valueSensitive) {
|
|
152
|
+
const callArguments =
|
|
153
|
+
child.type === 'token_tree' &&
|
|
154
|
+
child.text.startsWith('(') &&
|
|
155
|
+
(previous?.type === 'identifier' ||
|
|
156
|
+
['>', ')', ']'].includes(previous?.text.at(-1) ?? ''));
|
|
157
|
+
const key = children[index + 1]?.text === ':';
|
|
158
|
+
if (!callArguments && !key) labeled.add(child.id);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
let result = '';
|
|
163
|
+
let offset = node.startIndex;
|
|
164
|
+
for (const child of node.namedChildren) {
|
|
165
|
+
result += original.slice(offset - node.startIndex, child.startIndex - node.startIndex);
|
|
166
|
+
// Carry a secret label through value wrappers, never into runtime call arguments/conditions.
|
|
167
|
+
const carry =
|
|
168
|
+
sensitive &&
|
|
169
|
+
([
|
|
170
|
+
'parenthesized_expression',
|
|
171
|
+
'unary_expression',
|
|
172
|
+
'binary_expression',
|
|
173
|
+
'field_expression',
|
|
174
|
+
'reference_expression',
|
|
175
|
+
'try_expression',
|
|
176
|
+
'await_expression',
|
|
177
|
+
'block',
|
|
178
|
+
'expression_statement',
|
|
179
|
+
'else_clause',
|
|
180
|
+
'tuple_expression',
|
|
181
|
+
'array_expression',
|
|
182
|
+
].includes(type) ||
|
|
183
|
+
(type === 'call_expression' && child.id === node.childForFieldName('function')?.id) ||
|
|
184
|
+
(type === 'match_expression' && child.id === node.childForFieldName('body')?.id) ||
|
|
185
|
+
type === 'match_block' ||
|
|
186
|
+
(type === 'match_arm' && child.id === node.childForFieldName('value')?.id) ||
|
|
187
|
+
(type === 'type_cast_expression' && child.id === node.childForFieldName('value')?.id) ||
|
|
188
|
+
(type === 'if_expression' && child.id !== node.childForFieldName('condition')?.id));
|
|
189
|
+
result += redactRustNode(child, carry, labeled);
|
|
190
|
+
offset = child.endIndex;
|
|
191
|
+
}
|
|
192
|
+
return result + original.slice(offset - node.startIndex);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Lua exposes payload spans for both quoted and level-matched long-bracket literals. */
|
|
196
|
+
function redactLuaNode(node: Node, sensitive = false, labeled = new Set<number>()): string {
|
|
197
|
+
sensitive ||= labeled.has(node.id);
|
|
198
|
+
const original = node.text;
|
|
199
|
+
if (node.type === 'string' || node.type === 'comment') {
|
|
200
|
+
const content = node.childForFieldName('content');
|
|
201
|
+
if (!content) return original;
|
|
202
|
+
const suffix = original.slice(content.endIndex - node.startIndex);
|
|
203
|
+
let payload =
|
|
204
|
+
node.type === 'comment'
|
|
205
|
+
? scrubPayload(content.text)
|
|
206
|
+
: literalPayload(content.text, sensitive);
|
|
207
|
+
if (payload !== content.text && suffix.startsWith(']')) {
|
|
208
|
+
// A placeholder must not introduce a closing long bracket, including at the boundary.
|
|
209
|
+
payload = payload.split(suffix).join('] ' + suffix.slice(1));
|
|
210
|
+
if ((payload + suffix).indexOf(suffix) < payload.length) payload += ' ';
|
|
211
|
+
}
|
|
212
|
+
return original.slice(0, content.startIndex - node.startIndex) + payload + suffix;
|
|
213
|
+
}
|
|
214
|
+
if (node.type === 'number' && sensitive) return "'" + redactSecretValue(original) + "'";
|
|
215
|
+
const label = (key: Node | null): boolean => {
|
|
216
|
+
if (key?.type === 'bracket_index_expression') {
|
|
217
|
+
const field = key.childForFieldName('field');
|
|
218
|
+
return field?.type === 'string' && secretLabel(field);
|
|
219
|
+
}
|
|
220
|
+
return secretLabel(key?.type === 'dot_index_expression' ? key.childForFieldName('field') : key);
|
|
221
|
+
};
|
|
222
|
+
if (node.type === 'assignment_statement') {
|
|
223
|
+
const names =
|
|
224
|
+
node.namedChildren.find((child) => child.type === 'variable_list')?.namedChildren ?? [];
|
|
225
|
+
const values =
|
|
226
|
+
node.namedChildren.find((child) => child.type === 'expression_list')?.namedChildren ?? [];
|
|
227
|
+
values.forEach((value, index) => {
|
|
228
|
+
if (label(names[index] ?? null)) labeled.add(value.id);
|
|
229
|
+
});
|
|
230
|
+
} else if (node.type === 'field' && label(node.childForFieldName('name'))) {
|
|
231
|
+
const value = node.childForFieldName('value');
|
|
232
|
+
if (value) labeled.add(value.id);
|
|
233
|
+
}
|
|
234
|
+
const carry =
|
|
235
|
+
sensitive &&
|
|
236
|
+
(node.type === 'parenthesized_expression' ||
|
|
237
|
+
node.type === 'unary_expression' ||
|
|
238
|
+
(node.type === 'binary_expression' &&
|
|
239
|
+
['..', 'and', 'or'].includes(node.childForFieldName('operator')?.text ?? '')));
|
|
240
|
+
let result = '';
|
|
241
|
+
let offset = node.startIndex;
|
|
242
|
+
for (const child of node.namedChildren) {
|
|
243
|
+
result += original.slice(offset - node.startIndex, child.startIndex - node.startIndex);
|
|
244
|
+
result += redactLuaNode(child, carry, labeled);
|
|
245
|
+
offset = child.endIndex;
|
|
246
|
+
}
|
|
247
|
+
return result + original.slice(offset - node.startIndex);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function sqlSecretLabel(node: Node | null): boolean {
|
|
251
|
+
if (!node) return false;
|
|
252
|
+
if (['field', 'object_reference', 'column'].includes(node.type))
|
|
253
|
+
return sqlSecretLabel(node.childForFieldName('name') ?? node.firstNamedChild);
|
|
254
|
+
// This dialect-neutral grammar sometimes calls PostgreSQL quoted identifiers literals.
|
|
255
|
+
if (node.type === 'identifier' || (node.type === 'literal' && node.text.startsWith('"')))
|
|
256
|
+
return SECRET_LABEL_RE.test(node.text.replace(/^"|"$/g, '').replaceAll('""', '"'));
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function redactSqlNode(node: Node, sensitive = false): string {
|
|
261
|
+
if (node.type === 'create_function') {
|
|
262
|
+
const language = node.namedChildren.find((child) => child.type === 'function_language');
|
|
263
|
+
const body = node.namedChildren.find((child) => child.type === 'function_body');
|
|
264
|
+
// Opaque/procedural bodies have no established inner syntax; the caller uses fallback.
|
|
265
|
+
if (
|
|
266
|
+
language?.namedChildren.find((child) => child.type === 'identifier')?.text.toLowerCase() !==
|
|
267
|
+
'sql' ||
|
|
268
|
+
body?.namedChildren.some((child) => child.type === 'literal')
|
|
269
|
+
)
|
|
270
|
+
throw new Error('Opaque SQL function body');
|
|
271
|
+
}
|
|
272
|
+
const original = node.text;
|
|
273
|
+
if (node.type === 'comment') return '--' + scrubPayload(original.slice(2));
|
|
274
|
+
if (node.type === 'marginalia') return '/*' + scrubPayload(original.slice(2, -2)) + '*/';
|
|
275
|
+
if (node.type === 'literal') {
|
|
276
|
+
if (original.startsWith('"')) return original; // PostgreSQL identifier, never a secret value.
|
|
277
|
+
const opening = /^(?:[eEnNbBxX]|[uU]&)?'|^\$[A-Za-z_0-9]*\$/.exec(original)?.[0];
|
|
278
|
+
if (opening) {
|
|
279
|
+
const closing = opening.startsWith('$') ? opening : "'";
|
|
280
|
+
if (!original.endsWith(closing)) throw new Error('Incomplete SQL literal');
|
|
281
|
+
const payload = original.slice(opening.length, -closing.length);
|
|
282
|
+
// Scrub the whole payload on a match: SQL doubled quotes must not leave a secret suffix.
|
|
283
|
+
const redacted = literalPayload(payload, sensitive);
|
|
284
|
+
return opening + (redacted === payload ? payload : redactSecretValue(payload)) + closing;
|
|
285
|
+
}
|
|
286
|
+
if (node.namedChildren.some((child) => child.type.startsWith('keyword_'))) return original;
|
|
287
|
+
if (/^[+\-\d.]/.test(original))
|
|
288
|
+
return sensitive ? "'" + redactSecretValue(original) + "'" : original;
|
|
289
|
+
// shortcut: unrecognized typed literals use fallback until their boundaries are established.
|
|
290
|
+
throw new Error('Unsupported SQL literal');
|
|
291
|
+
}
|
|
292
|
+
const left = node.childForFieldName('left');
|
|
293
|
+
const right = node.childForFieldName('right');
|
|
294
|
+
const labeled = ['assignment', 'binary_expression'].includes(node.type) && sqlSecretLabel(left);
|
|
295
|
+
const columnLabel =
|
|
296
|
+
node.type === 'column_definition' && sqlSecretLabel(node.childForFieldName('name'));
|
|
297
|
+
const argumentLabel =
|
|
298
|
+
node.type === 'function_argument' &&
|
|
299
|
+
sqlSecretLabel(node.namedChildren.find((child) => child.type === 'identifier') ?? null);
|
|
300
|
+
const aliasLabel = node.type === 'term' && sqlSecretLabel(node.childForFieldName('alias'));
|
|
301
|
+
const insert = node.type === 'list' && node.parent?.type === 'insert' ? node.parent : null;
|
|
302
|
+
const columns = insert?.namedChildren.find((child) => child.type === 'list');
|
|
303
|
+
const columnValues =
|
|
304
|
+
columns?.namedChildren.some((child) => child.type === 'column') && columns.id !== node.id
|
|
305
|
+
? columns.namedChildren.filter((child) => !['comment', 'marginalia'].includes(child.type))
|
|
306
|
+
: [];
|
|
307
|
+
|
|
308
|
+
let result = '';
|
|
309
|
+
let offset = node.startIndex;
|
|
310
|
+
let index = 0;
|
|
311
|
+
let previous: Node | null = null;
|
|
312
|
+
for (const child of node.namedChildren) {
|
|
313
|
+
result += original.slice(offset - node.startIndex, child.startIndex - node.startIndex);
|
|
314
|
+
const carry =
|
|
315
|
+
sensitive &&
|
|
316
|
+
((node.type === 'binary_expression' && node.childForFieldName('operator')?.text === '||') ||
|
|
317
|
+
(node.type === 'cast' &&
|
|
318
|
+
child.id ===
|
|
319
|
+
(
|
|
320
|
+
node.childForFieldName('parameter') ??
|
|
321
|
+
node.namedChildren.find((part) => !['comment', 'marginalia'].includes(part.type))
|
|
322
|
+
)?.id) ||
|
|
323
|
+
['list', 'array', 'parenthesized_expression'].includes(node.type) ||
|
|
324
|
+
(node.type === 'case' &&
|
|
325
|
+
(previous?.type === 'keyword_then' || previous?.type === 'keyword_else')));
|
|
326
|
+
result += redactSqlNode(
|
|
327
|
+
child,
|
|
328
|
+
carry ||
|
|
329
|
+
(labeled && child.id === right?.id) ||
|
|
330
|
+
(node.type === 'binary_expression' && sqlSecretLabel(right) && child.id === left?.id) ||
|
|
331
|
+
(columnLabel && previous?.type === 'keyword_default') ||
|
|
332
|
+
(argumentLabel && child.type === 'literal') ||
|
|
333
|
+
(aliasLabel && child.id === node.childForFieldName('value')?.id) ||
|
|
334
|
+
child.id === node.childForFieldName('password')?.id ||
|
|
335
|
+
sqlSecretLabel(columnValues[index] ?? null)
|
|
336
|
+
);
|
|
337
|
+
if (!['comment', 'marginalia'].includes(child.type)) {
|
|
338
|
+
previous = child;
|
|
339
|
+
index++;
|
|
340
|
+
}
|
|
341
|
+
offset = child.endIndex;
|
|
342
|
+
}
|
|
343
|
+
return result + original.slice(offset - node.startIndex);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function swiftSecretLabel(node: Node | null): boolean {
|
|
347
|
+
if (!node) return false;
|
|
348
|
+
if (node.type.endsWith('string_literal')) {
|
|
349
|
+
const opening = /^(#+)?("""|")/.exec(node.text);
|
|
350
|
+
return Boolean(
|
|
351
|
+
opening && SECRET_LABEL_RE.test(node.text.slice(opening[0].length, -opening[0].length))
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
if (['simple_identifier', 'type_identifier'].includes(node.type))
|
|
355
|
+
return SECRET_LABEL_RE.test(node.text.replace(/^`|`$/g, ''));
|
|
356
|
+
return swiftSecretLabel(
|
|
357
|
+
node.childForFieldName('suffix') ??
|
|
358
|
+
node.childForFieldName('bound_identifier') ??
|
|
359
|
+
node.childForFieldName('name') ??
|
|
360
|
+
node.firstNamedChild
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function redactSwiftNode(node: Node, sensitive = false): string {
|
|
365
|
+
const original = node.text;
|
|
366
|
+
if (node.type === 'comment' || node.type === 'multiline_comment') {
|
|
367
|
+
// Swift permits nested block comments; retain every delimiter from the parsed comment.
|
|
368
|
+
return original
|
|
369
|
+
.split(/(\/\*|\*\/)/)
|
|
370
|
+
.map((part) => (part === '/*' || part === '*/' ? part : scrubPayload(part)))
|
|
371
|
+
.join('');
|
|
372
|
+
}
|
|
373
|
+
if (
|
|
374
|
+
['line_string_literal', 'multi_line_string_literal', 'raw_string_literal'].includes(node.type)
|
|
375
|
+
) {
|
|
376
|
+
const opening = /^(#+)?("""|")/.exec(original);
|
|
377
|
+
if (!opening) throw new Error('Swift string delimiter unavailable');
|
|
378
|
+
const closing = opening[2] + (opening[1] ?? '');
|
|
379
|
+
if (!original.endsWith(closing)) throw new Error('Swift string is incomplete');
|
|
380
|
+
const payload = (text: string): string => {
|
|
381
|
+
if (opening[2] !== '"""') return literalPayload(text, sensitive);
|
|
382
|
+
// Keep required opening newlines/closing indentation; scrub multiline secrets together.
|
|
383
|
+
const leading = /^\s*/.exec(text)?.[0] ?? '';
|
|
384
|
+
const body = text.slice(leading.length);
|
|
385
|
+
const trailing = /\s*$/.exec(body)?.[0] ?? '';
|
|
386
|
+
return (
|
|
387
|
+
leading + literalPayload(body.slice(0, body.length - trailing.length), sensitive) + trailing
|
|
388
|
+
);
|
|
389
|
+
};
|
|
390
|
+
let result = opening[0];
|
|
391
|
+
let offset = node.startIndex + opening[0].length;
|
|
392
|
+
for (const child of node.children) {
|
|
393
|
+
if (!['\\(', ')', 'interpolated_expression', 'raw_str_interpolation'].includes(child.type))
|
|
394
|
+
continue;
|
|
395
|
+
result += payload(
|
|
396
|
+
original.slice(offset - node.startIndex, child.startIndex - node.startIndex)
|
|
397
|
+
);
|
|
398
|
+
result += redactSwiftNode(child);
|
|
399
|
+
offset = child.endIndex;
|
|
400
|
+
}
|
|
401
|
+
return result + payload(original.slice(offset - node.startIndex, -closing.length)) + closing;
|
|
402
|
+
}
|
|
403
|
+
if (sensitive && ['integer_literal', 'real_literal'].includes(node.type))
|
|
404
|
+
return '"' + redactSecretValue(original) + '"';
|
|
405
|
+
|
|
406
|
+
let labeled =
|
|
407
|
+
node.type === 'assignment'
|
|
408
|
+
? swiftSecretLabel(node.childForFieldName('target'))
|
|
409
|
+
: node.type === 'value_argument'
|
|
410
|
+
? swiftSecretLabel(node.childForFieldName('name'))
|
|
411
|
+
: false;
|
|
412
|
+
let result = '';
|
|
413
|
+
let offset = node.startIndex;
|
|
414
|
+
for (const [index, child] of node.children.entries()) {
|
|
415
|
+
const field = node.fieldNameForChild(index);
|
|
416
|
+
if (
|
|
417
|
+
(node.type === 'property_declaration' && field === 'name') ||
|
|
418
|
+
(node.type === 'dictionary_literal' && field === 'key') ||
|
|
419
|
+
child.type === 'parameter'
|
|
420
|
+
)
|
|
421
|
+
labeled = swiftSecretLabel(child);
|
|
422
|
+
const value =
|
|
423
|
+
(field === 'value' &&
|
|
424
|
+
['property_declaration', 'dictionary_literal', 'value_argument'].includes(node.type)) ||
|
|
425
|
+
(field === 'result' && node.type === 'assignment') ||
|
|
426
|
+
field === 'default_value';
|
|
427
|
+
const carry =
|
|
428
|
+
sensitive &&
|
|
429
|
+
([
|
|
430
|
+
'tuple_expression',
|
|
431
|
+
'additive_expression',
|
|
432
|
+
'nil_coalescing_expression',
|
|
433
|
+
'try_expression',
|
|
434
|
+
'await_expression',
|
|
435
|
+
].includes(node.type) ||
|
|
436
|
+
(node.type === 'as_expression' && field === 'expr') ||
|
|
437
|
+
(node.type === 'prefix_expression' && field === 'target') ||
|
|
438
|
+
(node.type === 'ternary_expression' && field !== 'condition'));
|
|
439
|
+
result += original.slice(offset - node.startIndex, child.startIndex - node.startIndex);
|
|
440
|
+
result += redactSwiftNode(child, carry || (labeled && value));
|
|
441
|
+
offset = child.endIndex;
|
|
442
|
+
}
|
|
443
|
+
return result + original.slice(offset - node.startIndex);
|
|
444
|
+
}
|
|
445
|
+
|
|
57
446
|
function redactShellNode(
|
|
58
447
|
root: Node,
|
|
59
448
|
ranges: ReturnType<typeof commandLineCredentialRanges>
|
package/wasm/javascript.wasm
CHANGED
|
Binary file
|
package/wasm/lua.LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Munif Tanjim
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
(function_declaration
|
|
2
|
+
name: [
|
|
3
|
+
(identifier) @name
|
|
4
|
+
(dot_index_expression
|
|
5
|
+
field: (identifier) @name)
|
|
6
|
+
]) @definition.function
|
|
7
|
+
|
|
8
|
+
(function_declaration
|
|
9
|
+
name: (method_index_expression
|
|
10
|
+
method: (identifier) @name)) @definition.method
|
|
11
|
+
|
|
12
|
+
(assignment_statement
|
|
13
|
+
(variable_list
|
|
14
|
+
.
|
|
15
|
+
name: [
|
|
16
|
+
(identifier) @name
|
|
17
|
+
(dot_index_expression
|
|
18
|
+
field: (identifier) @name)
|
|
19
|
+
])
|
|
20
|
+
(expression_list
|
|
21
|
+
.
|
|
22
|
+
value: (function_definition))) @definition.function
|
|
23
|
+
|
|
24
|
+
(table_constructor
|
|
25
|
+
(field
|
|
26
|
+
name: (identifier) @name
|
|
27
|
+
value: (function_definition))) @definition.function
|
|
28
|
+
|
|
29
|
+
(function_call
|
|
30
|
+
name: [
|
|
31
|
+
(identifier) @name
|
|
32
|
+
(dot_index_expression
|
|
33
|
+
field: (identifier) @name)
|
|
34
|
+
(method_index_expression
|
|
35
|
+
method: (identifier) @name)
|
|
36
|
+
]) @reference.call
|
package/wasm/lua.wasm
ADDED
|
Binary file
|
package/wasm/sql.LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Derek Stride
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
; Capture whole declarations and their qualified names; references are not declarations.
|
|
2
|
+
(create_table (object_reference) @name) @definition.table
|
|
3
|
+
(create_view (object_reference) @name) @definition.view
|
|
4
|
+
(create_materialized_view (object_reference) @name) @definition.view
|
|
5
|
+
(create_function (object_reference) @name) @definition.function
|
package/wasm/sql.wasm
ADDED
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 alex-pinkus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
; Upstream 0.7.3 tags capture the enclosing class as a method definition.
|
|
2
|
+
; Capture each declaration itself so chunks retain its exact line range.
|
|
3
|
+
(class_declaration name: (type_identifier) @name) @definition.class
|
|
4
|
+
(protocol_declaration name: (type_identifier) @name) @definition.interface
|
|
5
|
+
(source_file (function_declaration name: (simple_identifier) @name) @definition.function)
|
|
6
|
+
(class_body (function_declaration name: (simple_identifier) @name) @definition.method)
|
|
7
|
+
(enum_class_body (function_declaration name: (simple_identifier) @name) @definition.method)
|
|
8
|
+
(protocol_body (protocol_function_declaration name: (simple_identifier) @name) @definition.method)
|
|
9
|
+
(init_declaration "init" @name) @definition.method
|
|
10
|
+
(deinit_declaration "deinit" @name) @definition.method
|
|
11
|
+
(typealias_declaration name: (type_identifier) @name) @definition.type
|
package/wasm/swift.wasm
ADDED
|
Binary file
|
package/wasm/tsx.wasm
CHANGED
|
Binary file
|