Skip to content

Commit 45c46d2

Browse files
committed
chore: changes to clean raw input
1 parent 35fd198 commit 45c46d2

File tree

2 files changed

+62
-11
lines changed

2 files changed

+62
-11
lines changed

packages/cli/src/__tests__/utils.test.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { blue, red, yellow } from 'colorette';
2828
import { existsSync, statSync } from 'fs';
2929
import * as path from 'path';
3030
import * as process from 'process';
31-
import { ConfigApis } from '../types';
31+
import { CommandOptions, ConfigApis } from '../types';
3232

3333
jest.mock('os');
3434
jest.mock('colorette');
@@ -592,9 +592,31 @@ describe('cleanRawInput', () => {
592592
'--config=fixtures/redocly.yaml',
593593
'--output',
594594
'fixtures',
595+
'--client-cert',
596+
'fixtures/client-cert.pem',
597+
'--client-key',
598+
'fixtures/client-key.pem',
599+
'--ca-cert',
600+
'fixtures/ca-cert.pem',
601+
'--organization',
602+
'my-org',
603+
'--input',
604+
'timeout=10000',
605+
'--input',
606+
'{"apiKey":"some=111=1111"}',
595607
];
596-
expect(cleanRawInput(rawInput)).toEqual(
597-
'redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder'
608+
expect(
609+
cleanRawInput(rawInput, {
610+
input: ['timeout=10000', '{"apiKey":"some=111=1111"}'],
611+
organization: 'my-org',
612+
'client-cert': 'fixtures/client-cert.pem',
613+
'client-key': 'fixtures/client-key.pem',
614+
'ca-cert': 'fixtures/ca-cert.pem',
615+
config: 'fixtures/redocly.yaml',
616+
output: 'fixtures',
617+
} as CommandOptions)
618+
).toEqual(
619+
'redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder --client-cert *** --client-key *** --ca-cert *** --organization *** --input *** --input ***'
598620
);
599621
});
600622
it('should preserve safe data from raw CLI input', () => {
@@ -608,7 +630,13 @@ describe('cleanRawInput', () => {
608630
'--skip-rule',
609631
'operation-4xx-response',
610632
];
611-
expect(cleanRawInput(rawInput)).toEqual(
633+
expect(
634+
cleanRawInput(rawInput, {
635+
format: 'stylish',
636+
extends: 'minimal',
637+
'skip-rule': ['operation-4xx-response'],
638+
} as CommandOptions)
639+
).toEqual(
612640
'redocly lint file-json --format stylish --extends=minimal --skip-rule operation-4xx-response'
613641
);
614642
});

packages/cli/src/utils/miscellaneous.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import type {
4444
import type { RawConfigProcessor } from '@redocly/openapi-core/lib/config';
4545
import type { Totals, Entrypoint, ConfigApis, CommandOptions, OutputExtensions } from '../types';
4646

47+
const KEYS_TO_CLEAN = ['organization', 'o', 'input', 'i', 'client-cert', 'client-key', 'ca-cert'];
48+
4749
export async function getFallbackApisOrExit(
4850
argsApis: string[] | undefined,
4951
config: ConfigApis
@@ -583,14 +585,16 @@ export async function sendTelemetry(
583585
exit_code,
584586
environment: process.env.REDOCLY_ENVIRONMENT,
585587
environment_ci: process.env.CI,
586-
raw_input: cleanRawInput(process.argv.slice(2)),
588+
raw_input: cleanRawInput(process.argv.slice(2), args),
587589
has_config: has_config ? 'yes' : 'no',
588590
spec_version,
589591
spec_keyword,
590592
spec_full_version,
591593
};
592594
const { otelTelemetry } = await import('../otel');
593595
otelTelemetry.init();
596+
console.log('JSON.stringify(cleanArgs(args)),', JSON.stringify(cleanArgs(args)));
597+
console.log('RAW_I', cleanRawInput(process.argv.slice(2), args));
594598
otelTelemetry.send(data.command, data);
595599
} catch (err) {
596600
// Do nothing.
@@ -627,7 +631,7 @@ function isDirectory(value: string) {
627631
return fs.existsSync(value) && fs.statSync(value).isDirectory();
628632
}
629633

630-
function cleanString(value?: string): string | undefined {
634+
function cleanString(value: string): string | undefined {
631635
if (!value) {
632636
return value;
633637
}
@@ -647,11 +651,9 @@ function cleanString(value?: string): string | undefined {
647651
}
648652

649653
export function cleanArgs(args: CommandOptions) {
650-
const keysToClean = ['organization', 'o', 'input', 'i', 'client-cert', 'client-key', 'ca-cert'];
651-
652654
const result: Record<string, unknown> = {};
653655
for (const [key, value] of Object.entries(args)) {
654-
if (keysToClean.includes(key)) {
656+
if (KEYS_TO_CLEAN.includes(key)) {
655657
result[key] = '***';
656658
} else if (typeof value === 'string') {
657659
result[key] = cleanString(value);
@@ -665,8 +667,29 @@ export function cleanArgs(args: CommandOptions) {
665667
return result;
666668
}
667669

668-
export function cleanRawInput(argv: string[]) {
669-
return argv.map((entry) => entry.split('=').map(cleanString).join('=')).join(' ');
670+
export function cleanRawInput(argv: string[], parsedArgs: CommandOptions) {
671+
const stringsToMask: string[] = [];
672+
for (const [key, value] of Object.entries(parsedArgs)) {
673+
if (KEYS_TO_CLEAN.includes(key)) {
674+
if (typeof value === 'string') {
675+
stringsToMask.push(value);
676+
} else if (Array.isArray(value)) {
677+
stringsToMask.push(...value);
678+
}
679+
}
680+
}
681+
682+
return argv
683+
.map((entry) => {
684+
for (const stringToMask of stringsToMask) {
685+
if (entry.includes(stringToMask)) {
686+
// Replace only the exact sensitive string with ***
687+
return entry.replace(stringToMask, '***');
688+
}
689+
}
690+
return entry.split('=').map(cleanString).join('=');
691+
})
692+
.join(' ');
670693
}
671694

672695
export function checkForDeprecatedOptions<T>(argv: T, deprecatedOptions: Array<keyof T>) {

0 commit comments

Comments
 (0)