@link-foundation/sensitive-data-sanitizer 0.19.3 → 0.21.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/CHANGELOG.md +12 -0
- package/README.md +22 -2
- package/bin/sensitive-data-sanitizer.js +50 -28
- package/docs/API.md +355 -16
- package/docs/COVERAGE.md +19 -9
- package/docs/RULES.md +218 -0
- package/examples/second-pass-placeholders.mjs +28 -0
- package/package.json +12 -3
- package/src/allow-list.js +93 -0
- package/src/confidence.js +24 -9
- package/src/context.js +287 -40
- package/src/credential-spans.js +180 -0
- package/src/credentials-entry.d.ts +23 -0
- package/src/credentials-entry.js +62 -0
- package/src/credentials.js +51 -0
- package/src/crypto-addresses.js +74 -0
- package/src/detection.js +87 -41
- package/src/document-person-cues.js +1 -1
- package/src/encoded.js +137 -51
- package/src/encrypt.js +95 -0
- package/src/engines.js +33 -10
- package/src/entities.js +4 -3
- package/src/exempt.js +72 -0
- package/src/fake-memory.js +32 -0
- package/src/fake.js +33 -29
- package/src/features.js +29 -0
- package/src/files.js +57 -12
- package/src/gitleaks.js +82 -27
- package/src/html-tags.js +8 -0
- package/src/identifier-detector.js +36 -0
- package/src/identity-types.js +63 -0
- package/src/identity.js +3 -47
- package/src/index.d.ts +157 -3
- package/src/index.js +13 -0
- package/src/known.js +33 -15
- package/src/national-checks.js +209 -0
- package/src/national.js +310 -92
- package/src/pattern-detector.js +219 -0
- package/src/personal-context.js +3 -2
- package/src/personal-evidence.js +233 -0
- package/src/personal-features.js +39 -0
- package/src/personal.js +66 -10
- package/src/placeholder-types.js +154 -4
- package/src/placeholders.js +127 -45
- package/src/projection.js +78 -26
- package/src/proper-names.js +48 -5
- package/src/prose-words.js +120 -0
- package/src/record-worker.js +1 -0
- package/src/rule-catalog.js +426 -0
- package/src/rules.js +8 -0
- package/src/sanitizer.js +133 -23
- package/src/sarif.js +127 -0
- package/src/stream-worker.js +1 -0
- package/src/strict-attributes.js +48 -4
- package/src/strict.js +1 -1
- package/src/structured.js +2 -0
- package/src/token-checksum.js +49 -0
- package/src/transforms.js +146 -33
- package/src/vendor/betterleaks/LICENSE +21 -0
- package/src/vendor/betterleaks/provenance.json +11 -0
- package/src/vendor/betterleaks/rules-0.json +463 -0
- package/src/vendor/betterleaks/rules-1.json +454 -0
- package/src/vendor/betterleaks/rules-2.json +461 -0
- package/src/vendor/betterleaks/rules-3.json +455 -0
- package/src/vendor/betterleaks/rules-4.json +483 -0
- package/src/vendor/betterleaks/rules-5.json +35 -0
- package/src/vendor/entities/aws.json +1 -1
- package/src/vendor/entities/azure.json +6 -2
- package/src/vendor/entities/google.json +2 -1
- package/src/vocabulary.js +27 -1
- package/src/worker-options.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.21.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d1d7a22: Resolve the sanitizer requests of issues 130–141. Placeholder mode accepts `transformation.existing: 'keep'` for a second pass over sanitized text, types whole JSON values (`Sensitive-1`, `Age-1`), and keeps pronouns, cue words and sentence-initial greetings and verbs readable beside `Person-n`; compact organization and location spans become one typed token. `reservedPlaceholderTypes()` and `isPlaceholderToken()` expose the namespace. `strict` covers more nationality, religion, health, sexuality, conviction and trade-union wording, and `vocabulary.personalAttributes` adds caller stems. A credentials-only entry (`@link-foundation/sensitive-data-sanitizer/credentials`) starts about three times faster, and both entries support `require`. Credential context stays readable and masks stay stable; configuration settings are kept and an `exempt(finding, text)` hook can keep findings by policy. New detections cover CI credential markers, XML attributes, hash rockets, markup values and plural credential flags. Wrapped base64 and hex keep their layout; candidates are bounded per 64 KiB window; `knownSecrets` also match their hex and base64 spellings. Environment secret discovery selects `PGPASSWORD`-style names and cookies, skips more configuration names, and accepts `minLength`.
|
|
8
|
+
|
|
9
|
+
## 0.20.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- befe673: Match the strongest features of competing secret and PII tools. Add national, tax, bank and device identifiers from Presidio, OpenRedaction, DataFog and Google; 203 vendored Betterleaks rules; offline CRC32 checks for GitHub and npm tokens (`tokenChecksum`, `tokenWithChecksum`); escape-run, HTML-tag and UTF-16 decoding; `allowList`, `inlineAllow` and `minConfidenceByType`; mask tuning and deterministic `encrypt` with `decrypt`; `createPatternDetector`, `createIdentifierDetector`, `identifierChecks` and the read-only `nationalRules` table; SARIF output (`toSarif`, `scan --format sarif`), multi-path `scan` and pre-commit hooks. Detect an IPv4 address followed by a full stop. Add a competitor comparison with measured results on 853 competitor test cases.
|
|
14
|
+
|
|
3
15
|
## 0.19.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Sensitive Data Sanitizer
|
|
2
2
|
|
|
3
|
-
An offline JavaScript library, detector framework, and CLI for redacting credentials and personal data from logs, AI sessions, and text files, including logs with invalid UTF-8 bytes. It combines required Secretlint
|
|
3
|
+
An offline JavaScript library, detector framework, and CLI for redacting credentials and personal data from logs, AI sessions, and text files, including logs with invalid UTF-8 bytes. It combines required Secretlint, 221 bundled Gitleaks text rules and 203 further Betterleaks rules with contextual credentials, default multilingual name/PII recognition, known values and bounded encoding detection. Optional local Gitleaks, TruffleHog, and Presidio detectors extend the union.
|
|
4
4
|
|
|
5
5
|
Library calls without a profile replace every actionable finding completely with `[REDACTED]`. Personal findings below the default confidence threshold of 0.5 remain inspectable without replacing ordinary log numbers; credentials always qualify. Publication methods verify full redaction and block output if a required detector fails or finds a residual. Optional typed transformations, compatible partial masks and encoding preservation are described in the API. Findings contain offsets and rule metadata; they omit matched values and source excerpts.
|
|
6
6
|
|
|
@@ -20,6 +20,12 @@ two-pass publication:
|
|
|
20
20
|
sensitive-data-sanitizer redact session.jsonl --stream --jsonl --two-pass --output safe.jsonl
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
For loggers that only mask credentials, import the
|
|
24
|
+
[credentials-only entry](docs/API.md#credentials-only-entry)
|
|
25
|
+
`@link-foundation/sensitive-data-sanitizer/credentials`: it skips the
|
|
26
|
+
personal-data modules and starts about three times faster. Both entries also
|
|
27
|
+
support `require`.
|
|
28
|
+
|
|
23
29
|
For synchronous log hooks, `createSyncSanitizer` supports custom detectors and
|
|
24
30
|
verified callback transformations. Rule/type controls, caller vocabulary,
|
|
25
31
|
structured field selectors and `compileKnown` configure reusable policies; see
|
|
@@ -89,6 +95,13 @@ Known Russian names match in all six cases and in any word order, with `ё`/`е`
|
|
|
89
95
|
spelling variants and initials (`с Петровым Данилом Сергеевичем`, `Петров Д. С.`).
|
|
90
96
|
A part of a longer name is matched alone only when it is listed itself.
|
|
91
97
|
|
|
98
|
+
With `properNames: 'capitalized'`, placeholder output keeps the sentence around a
|
|
99
|
+
name (`Кандидат Person-1`, `Меня зовут Person-1`, `Благодарим Вас, Person-1`), and
|
|
100
|
+
`transformation.existing: 'keep'` lets a second pass over sanitized text keep its
|
|
101
|
+
`Type-n` tokens and number new values after them. `isPlaceholderToken` and
|
|
102
|
+
`reservedPlaceholderTypes` expose the namespace; see the
|
|
103
|
+
[second-pass example](examples/second-pass-placeholders.mjs).
|
|
104
|
+
|
|
92
105
|
For irreversible output, choose `transformation: { mode: 'placeholder', map:
|
|
93
106
|
false }`: no restore map is returned or written. Detection limits still apply
|
|
94
107
|
in either mode. See the [placeholder API](docs/API.md#reversible-placeholders),
|
|
@@ -131,6 +144,7 @@ console.log(result.text); // password=[REDACTED] [REDACTED]
|
|
|
131
144
|
printf 'password=short\n' | sensitive-data-sanitizer redact -
|
|
132
145
|
sensitive-data-sanitizer redact input.txt --in-place
|
|
133
146
|
sensitive-data-sanitizer scan logs --config /private/policy.json
|
|
147
|
+
sensitive-data-sanitizer scan src/a.js src/b.js --format sarif > report.sarif
|
|
134
148
|
sensitive-data-sanitizer redact input.txt --gitleaks --trufflehog --output safe.txt
|
|
135
149
|
sensitive-data-sanitizer redact input.txt --presidio /path/presidio-bridge.py --model en_core_web_sm --language en
|
|
136
150
|
sensitive-data-sanitizer redact large-session.jsonl --jsonl --stream --output safe-session.jsonl
|
|
@@ -148,6 +162,8 @@ sensitive-data-sanitizer --help
|
|
|
148
162
|
|
|
149
163
|
Defaults: 32 MiB whole-text input bytes, 100,000 findings and 10,000 files. `--stream` permits 1 GiB total with plain-text records up to the total input limit or 8 MiB JSONL records, bounded workers and atomic publication. `--worker-timeout-ms N` sets the worker inactivity/per-batch deadline (default 60000 ms); verified file progress resets the deadline, so large files can run longer overall. `--max-bytes` sets the byte limit; JSON config sets the other sanitizer limits. `--paranoid` adds entropy heuristics and increases false positives. `--native-only` explicitly disables Secretlint.
|
|
150
164
|
|
|
165
|
+
`scan` accepts several paths and `--format sarif` emits SARIF 2.1.0 for code-scanning viewers. The repository's `.pre-commit-hooks.yaml` provides `sensitive-data-sanitizer` (credentials) and `sensitive-data-sanitizer-pii` hooks for [pre-commit](https://pre-commit.com). UTF-16 files with a byte order mark are read and written back in their own encoding.
|
|
166
|
+
|
|
151
167
|
## Configuration
|
|
152
168
|
|
|
153
169
|
For AI sessions, `--jsonl` preserves JSON records and declares `id`, `type`,
|
|
@@ -195,6 +211,8 @@ Keep policies containing real private values outside Git. Built-in exact public
|
|
|
195
211
|
}
|
|
196
212
|
```
|
|
197
213
|
|
|
214
|
+
Reviewed false positives can be kept with `allowList` (whole-value strings or anchored regexes) or, opt-in, with `inlineAllow: true`, which honours `gitleaks:allow`, `pragma: allowlist secret` and similar comments; credentials stay redacted unless `allowCredentialDisable: true` is also set. `minConfidenceByType` sets per-type thresholds, the `mask` transformation accepts `char`, `ignore`, `ignoreClasses`, `count` and `fromEnd`, and `{mode: 'encrypt', key}` produces deterministic AES-256-GCM tokens that `decrypt(text, key)` restores. See [the API](docs/API.md#allow-lists-suppression-comments-and-template-values) and [the competitor comparison](docs/COMPARISON.md).
|
|
215
|
+
|
|
198
216
|
Custom policies preserve exact reviewed `PERSON`, `ORGANIZATION` and `EMAIL` detections. Built-in public resolvers/documentation IPs are also exempt. Credential detections always win, including a public email used as a password or authorization value. Evidence is an explicit caller decision and does not make every occurrence harmless.
|
|
199
217
|
|
|
200
218
|
## Extend detection
|
|
@@ -218,6 +236,8 @@ const sanitizer = createSanitizer({
|
|
|
218
236
|
|
|
219
237
|
Install external binaries and language models separately. TruffleHog runs with verification and updates disabled. The Presidio example checks for an installed model and never downloads it at analysis time. Each selected detector is required, including during residual verification. See [the API and adapter contract](docs/API.md), [combined scanners](examples/combined-scanners.mjs), and [the local NER bridge](examples/presidio-bridge.py).
|
|
220
238
|
|
|
239
|
+
`createPatternDetector([{type, patterns, denyList, context, validate}])` adds Presidio-style pattern recognizers or Google-style custom infoTypes with hotword boosts, and `createIdentifierDetector` adds national identifiers with checksum validators; see [declarative pattern detectors](docs/API.md#declarative-pattern-detectors).
|
|
240
|
+
|
|
221
241
|
The framework also accepts Gitleaks, TruffleHog, detect-secrets, Presidio, or explicitly typed offset reports. Cloud reports can be converted locally; the package itself makes no cloud requests.
|
|
222
242
|
|
|
223
243
|
For CLI name recognition, `--presidio PATH` selects a local Python JSON bridge. `--python COMMAND` selects its interpreter, and `--model` / `--language` select an already installed model. These options require the bridge and participate in final-output verification.
|
|
@@ -241,7 +261,7 @@ See [contributing](docs/CONTRIBUTING.md). `add`, `multiply` and `delay` live in
|
|
|
241
261
|
|
|
242
262
|
The universal app's preview images regenerate on pushes to the default branch. Run `npm run example:web:preview-images` to regenerate them locally; see [the template guide](docs/TEMPLATE-PIPELINE.md) for setup.
|
|
243
263
|
|
|
244
|
-
Automatic `--env-secrets` discovery skips
|
|
264
|
+
Automatic `--env-secrets` discovery also selects `PGPASSWORD`-style suffixes and cookies, and skips configuration names such as `GIT_AUTH_TRANSPORT`, `AUTH_MODE`, `*_AUTH_GUARD`, `MAX_TOKEN_COUNT`, `SSH_KEY_PATH`, `SECRET_NAME`, `AWS_ACCESS_KEY_ID` and `GIT_CONFIG_KEY_<n>`; `knownSecretsFromEnv(env, undefined, { minLength: 8 })` also skips short values. Explicit `knownSecretsFromEnv(env, names)` selections still include their exact values.
|
|
245
265
|
|
|
246
266
|
For shared tool logs, `--credentials-only --env-secrets --gh-config` preserves
|
|
247
267
|
public account details while redacting credential patterns and exact local
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import '../src/personal-features.js';
|
|
2
3
|
import { readFileSync, realpathSync } from 'node:fs';
|
|
3
4
|
import { fileURLToPath, URL } from 'node:url';
|
|
4
5
|
import { resolve } from 'node:path';
|
|
@@ -6,9 +7,11 @@ import { createSanitizer } from '../src/engines.js';
|
|
|
6
7
|
import { failure } from '../src/detection.js';
|
|
7
8
|
import {
|
|
8
9
|
readTextFile,
|
|
10
|
+
readTextInput,
|
|
9
11
|
atomicWrite,
|
|
10
12
|
listTextCandidates,
|
|
11
|
-
|
|
13
|
+
decodeTextInput,
|
|
14
|
+
encodeTextOutput,
|
|
12
15
|
} from '../src/files.js';
|
|
13
16
|
import { auditGitHistory } from '../src/history.js';
|
|
14
17
|
import { rewriteGitHistory } from '../src/history-rewrite.js';
|
|
@@ -17,7 +20,7 @@ import {
|
|
|
17
20
|
knownSecretsFromEnv,
|
|
18
21
|
knownSecretsFromGitHubConfig,
|
|
19
22
|
} from '../src/known.js';
|
|
20
|
-
import {
|
|
23
|
+
import { toSarif } from '../src/sarif.js';
|
|
21
24
|
import { createWikidataVerifier } from '../src/public-verifier.js';
|
|
22
25
|
import { streamCommand } from './stream.js';
|
|
23
26
|
import { sessionStructuralFields } from '../src/structured.js';
|
|
@@ -31,7 +34,8 @@ import {
|
|
|
31
34
|
const help = `Usage: sensitive-data-sanitizer <redact|scan|restore|history> [path|-] [options]
|
|
32
35
|
|
|
33
36
|
redact Sanitize one text log or stdin; publish only after verification
|
|
34
|
-
scan Report metadata for
|
|
37
|
+
scan Report metadata for files, directories, or stdin (never source text);
|
|
38
|
+
several paths may follow scan (for example staged files)
|
|
35
39
|
restore Restore placeholders in a file using --map PATH (private output)
|
|
36
40
|
history Audit local reachable Git blobs, commit/tag metadata, and reflogs
|
|
37
41
|
history rewrite SOURCE --output DIRECTORY [--apply]
|
|
@@ -67,6 +71,7 @@ history rewrite SOURCE --output DIRECTORY [--apply]
|
|
|
67
71
|
--no-map Discard placeholder mapping after full anonymization
|
|
68
72
|
--placeholder-format TEMPLATE Default {Type}-{n}; also [{TYPE}_{n}]
|
|
69
73
|
--map-format FORMAT json or lino (otherwise inferred from .lino extension)
|
|
74
|
+
--format FORMAT scan report: json (default) or sarif (SARIF 2.1.0)
|
|
70
75
|
--map-credentials Explicitly keep credentials in the private restore map
|
|
71
76
|
--max-record-bytes N Maximum record bytes (text: total limit; JSONL: 8388608)
|
|
72
77
|
--hive-mask Opt-in first/last 3 mask for values longer than 12 characters
|
|
@@ -129,8 +134,9 @@ function parseArgs(argv) {
|
|
|
129
134
|
['--map', 'map'],
|
|
130
135
|
['--map-format', 'mapFormat'],
|
|
131
136
|
['--placeholder-format', 'placeholderFormat'],
|
|
137
|
+
['--format', 'format'],
|
|
132
138
|
]);
|
|
133
|
-
|
|
139
|
+
const paths = [];
|
|
134
140
|
for (let i = rewrite ? 2 : 1; i < argv.length; i++) {
|
|
135
141
|
const arg = argv[i];
|
|
136
142
|
if (boolean.has(arg)) {
|
|
@@ -140,13 +146,18 @@ function parseArgs(argv) {
|
|
|
140
146
|
throw failure('ERR_ARGUMENT');
|
|
141
147
|
}
|
|
142
148
|
config[valued.get(arg)] = argv[++i];
|
|
143
|
-
} else if (!
|
|
144
|
-
|
|
145
|
-
hasPath = true;
|
|
149
|
+
} else if (!arg.startsWith('--')) {
|
|
150
|
+
paths.push(arg);
|
|
146
151
|
} else {
|
|
147
152
|
throw failure('ERR_ARGUMENT');
|
|
148
153
|
}
|
|
149
154
|
}
|
|
155
|
+
// Only scan accepts several paths (for example staged files from a hook).
|
|
156
|
+
if (paths.length > 1 && (command !== 'scan' || paths.includes('-'))) {
|
|
157
|
+
throw failure('ERR_ARGUMENT');
|
|
158
|
+
}
|
|
159
|
+
config.path = paths[0] ?? '-';
|
|
160
|
+
config.paths = paths.length ? paths : ['-'];
|
|
150
161
|
validateArgs(config);
|
|
151
162
|
return config;
|
|
152
163
|
}
|
|
@@ -194,7 +205,11 @@ function validateFeatureArgs(config) {
|
|
|
194
205
|
|
|
195
206
|
function validateStructuredArgs(config) {
|
|
196
207
|
validateStreamArgs(config);
|
|
197
|
-
if (
|
|
208
|
+
if (
|
|
209
|
+
(config.twoPass && !config.stream) ||
|
|
210
|
+
(config.format !== undefined &&
|
|
211
|
+
(config.command !== 'scan' || !['json', 'sarif'].includes(config.format)))
|
|
212
|
+
) {
|
|
198
213
|
throw failure('ERR_ARGUMENT');
|
|
199
214
|
}
|
|
200
215
|
if ((config.json && config.jsonl) || (config.stream && config.json)) {
|
|
@@ -249,7 +264,7 @@ async function stdinText(stream, maxBytes, options) {
|
|
|
249
264
|
}
|
|
250
265
|
chunks.push(buffer);
|
|
251
266
|
}
|
|
252
|
-
return
|
|
267
|
+
return decodeTextInput(Buffer.concat(chunks), options);
|
|
253
268
|
}
|
|
254
269
|
|
|
255
270
|
export async function runCli(
|
|
@@ -266,9 +281,7 @@ export async function runCli(
|
|
|
266
281
|
return 0;
|
|
267
282
|
}
|
|
268
283
|
if (['--version', '-v'].includes(argv[0])) {
|
|
269
|
-
stdout.write(
|
|
270
|
-
`${JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version}\n`
|
|
271
|
-
);
|
|
284
|
+
stdout.write(`${packageVersion()}\n`);
|
|
272
285
|
return 0;
|
|
273
286
|
}
|
|
274
287
|
const config = parseArgs(argv);
|
|
@@ -422,24 +435,20 @@ function inputText(path, config, stdin) {
|
|
|
422
435
|
};
|
|
423
436
|
return path === '-'
|
|
424
437
|
? stdinText(stdin, config.maxBytes, options)
|
|
425
|
-
:
|
|
438
|
+
: readTextInput(path, config.maxBytes, options);
|
|
426
439
|
}
|
|
427
440
|
|
|
428
441
|
async function redactCommand(config, engine, { stdin, stdout }) {
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
);
|
|
442
|
+
const input = await inputText(config.path, config, stdin);
|
|
443
|
+
const result = await engine.sanitize(input.text);
|
|
432
444
|
await saveMap(config);
|
|
445
|
+
const output = encodeTextOutput(result.text, input.encoding);
|
|
433
446
|
if (config.output || config.inPlace) {
|
|
434
|
-
await atomicWrite(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
{
|
|
438
|
-
replace: Boolean(config.inPlace),
|
|
439
|
-
}
|
|
440
|
-
);
|
|
447
|
+
await atomicWrite(config.output ?? config.path, output, {
|
|
448
|
+
replace: Boolean(config.inPlace),
|
|
449
|
+
});
|
|
441
450
|
} else {
|
|
442
|
-
stdout.write(
|
|
451
|
+
stdout.write(output);
|
|
443
452
|
}
|
|
444
453
|
return 0;
|
|
445
454
|
}
|
|
@@ -464,8 +473,10 @@ async function historyCommand(config, engine, { stdout }) {
|
|
|
464
473
|
}
|
|
465
474
|
|
|
466
475
|
async function scanCommand(config, engine, { stdin, stdout }) {
|
|
467
|
-
const files =
|
|
468
|
-
|
|
476
|
+
const files = [];
|
|
477
|
+
for (const path of config.paths) {
|
|
478
|
+
files.push(...(path === '-' ? ['-'] : await listTextCandidates(path)));
|
|
479
|
+
}
|
|
469
480
|
const results = [],
|
|
470
481
|
skipped = [];
|
|
471
482
|
for (const file of files) {
|
|
@@ -473,7 +484,9 @@ async function scanCommand(config, engine, { stdin, stdout }) {
|
|
|
473
484
|
try {
|
|
474
485
|
results.push({
|
|
475
486
|
path,
|
|
476
|
-
findings: await engine.inspect(
|
|
487
|
+
findings: await engine.inspect(
|
|
488
|
+
(await inputText(file, config, stdin)).text
|
|
489
|
+
),
|
|
477
490
|
});
|
|
478
491
|
} catch (error) {
|
|
479
492
|
if (['ERR_BINARY', 'ERR_ENCODING', 'ERR_LIMIT'].includes(error.code)) {
|
|
@@ -484,7 +497,10 @@ async function scanCommand(config, engine, { stdin, stdout }) {
|
|
|
484
497
|
}
|
|
485
498
|
}
|
|
486
499
|
const complete = skipped.length === 0;
|
|
487
|
-
|
|
500
|
+
const report = { complete, results, skipped };
|
|
501
|
+
stdout.write(
|
|
502
|
+
`${JSON.stringify(config.format === 'sarif' ? toSarif(report, { version: packageVersion() }) : report, null, 2)}\n`
|
|
503
|
+
);
|
|
488
504
|
return !complete ? 2 : results.some((r) => r.findings.length) ? 1 : 0;
|
|
489
505
|
}
|
|
490
506
|
|
|
@@ -495,6 +511,12 @@ if (
|
|
|
495
511
|
process.exitCode = await runCli(process.argv.slice(2));
|
|
496
512
|
}
|
|
497
513
|
|
|
514
|
+
function packageVersion() {
|
|
515
|
+
return JSON.parse(
|
|
516
|
+
readFileSync(new URL('../package.json', import.meta.url), 'utf8')
|
|
517
|
+
).version;
|
|
518
|
+
}
|
|
519
|
+
|
|
498
520
|
function defaultByteLimit(config) {
|
|
499
521
|
return config.stream ? 1073741824 : 33554432;
|
|
500
522
|
}
|