Changing load/dump in source files (#190641)

## Summary

Updates usage of `js-yaml` `load` and `dump` to `safeLoad` and
`safeDump`, in preparation for a major version update of dependency,
where the default behavior will be that of the safe function variants.


## Note to reviewers
`safeDump` will throw if it encounters invalid types (e.g. `undefined`),
whereas the `dump` function will still write the file including the
invalid types. This may have an affect within your use cases - if
throwing is not acceptable or is unhandled. To avoid this the
`skipInvalid` option can be used (see
https://github.com/nodeca/js-yaml#dump-object---options-) - this will
write the file, stripping out any invalid types from the input.

Please consider this when reviewing the changes to your code. If the
`skipInvalid` option is needed, please add it, or let us know to make
the change.

---------

Co-authored-by: Sid <siddharthmantri1@gmail.com>
Co-authored-by: “jeramysoucy” <jeramy.soucy@elastic.co>
Co-authored-by: Elena Shostak <elena.shostak@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Maxim Palenov <maxim.palenov@elastic.co>
This commit is contained in:
Kurt 2024-08-21 07:29:36 -04:00 committed by GitHub
parent 5acd638327
commit bcc46b60e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 265 additions and 57 deletions

View file

@ -36,6 +36,7 @@ async function main() {
const preamble = locationFileLines.slice(0, 1); const preamble = locationFileLines.slice(0, 1);
// eslint-disable-next-line @kbn/eslint/no_unsafe_js_yaml
const locationObj = jsYaml.load( const locationObj = jsYaml.load(
locationFileLines.slice(1).join('\n') locationFileLines.slice(1).join('\n')
) as BackstageLocationResource; ) as BackstageLocationResource;
@ -43,6 +44,7 @@ async function main() {
(fileName) => `${resourceDefinitionsBaseUrl}/${fileName}` (fileName) => `${resourceDefinitionsBaseUrl}/${fileName}`
); );
// eslint-disable-next-line @kbn/eslint/no_unsafe_js_yaml
const locationYaml = jsYaml.dump(locationObj, { lineWidth: 400 }); const locationYaml = jsYaml.dump(locationObj, { lineWidth: 400 });
fs.writeFileSync(locationFile, `${preamble.join('\n')}\n${locationYaml}`); fs.writeFileSync(locationFile, `${preamble.join('\n')}\n${locationYaml}`);

View file

@ -6,6 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
// eslint-disable-next-line @kbn/eslint/no_unsafe_js_yaml
import { dump } from 'js-yaml'; import { dump } from 'js-yaml';
import { BuildkiteClient, BuildkiteCommandStep } from './buildkite'; import { BuildkiteClient, BuildkiteCommandStep } from './buildkite';

View file

@ -8,7 +8,10 @@
import axios, { AxiosInstance } from 'axios'; import axios, { AxiosInstance } from 'axios';
import { execSync, ExecSyncOptions } from 'child_process'; import { execSync, ExecSyncOptions } from 'child_process';
// eslint-disable-next-line @kbn/eslint/no_unsafe_js_yaml
import { dump } from 'js-yaml'; import { dump } from 'js-yaml';
import { parseLinkHeader } from './parse_link_header'; import { parseLinkHeader } from './parse_link_header';
import { Artifact } from './types/artifact'; import { Artifact } from './types/artifact';
import { Build, BuildStatus } from './types/build'; import { Build, BuildStatus } from './types/build';

View file

@ -10,6 +10,8 @@ import * as Fs from 'fs';
import * as globby from 'globby'; import * as globby from 'globby';
import minimatch from 'minimatch'; import minimatch from 'minimatch';
// eslint-disable-next-line @kbn/eslint/no_unsafe_js_yaml
import { load as loadYaml } from 'js-yaml'; import { load as loadYaml } from 'js-yaml';
import { BuildkiteClient, BuildkiteStep } from '../buildkite'; import { BuildkiteClient, BuildkiteStep } from '../buildkite';

View file

@ -7,7 +7,7 @@
*/ */
import fs from 'fs'; import fs from 'fs';
import { extname } from 'path'; import { extname } from 'path';
import { load as loadYaml } from 'js-yaml'; import { safeLoad as loadYaml } from 'js-yaml';
export const readRolesFromResource = (resourcePath: string) => { export const readRolesFromResource = (resourcePath: string) => {
if (!fs.existsSync(resourcePath) || extname(resourcePath) !== '.yml') { if (!fs.existsSync(resourcePath) || extname(resourcePath) !== '.yml') {

View file

@ -314,6 +314,7 @@ module.exports = {
'@kbn/eslint/no_constructor_args_in_property_initializers': 'error', '@kbn/eslint/no_constructor_args_in_property_initializers': 'error',
'@kbn/eslint/no_this_in_property_initializers': 'error', '@kbn/eslint/no_this_in_property_initializers': 'error',
'@kbn/eslint/no_unsafe_console': 'error', '@kbn/eslint/no_unsafe_console': 'error',
'@kbn/eslint/no_unsafe_js_yaml': 'error',
'@kbn/imports/no_unresolvable_imports': 'error', '@kbn/imports/no_unresolvable_imports': 'error',
'@kbn/imports/uniform_imports': 'error', '@kbn/imports/uniform_imports': 'error',
'@kbn/imports/no_unused_imports': 'error', '@kbn/imports/no_unused_imports': 'error',

View file

@ -18,5 +18,6 @@ module.exports = {
no_constructor_args_in_property_initializers: require('./rules/no_constructor_args_in_property_initializers'), no_constructor_args_in_property_initializers: require('./rules/no_constructor_args_in_property_initializers'),
no_this_in_property_initializers: require('./rules/no_this_in_property_initializers'), no_this_in_property_initializers: require('./rules/no_this_in_property_initializers'),
no_unsafe_console: require('./rules/no_unsafe_console'), no_unsafe_console: require('./rules/no_unsafe_console'),
no_unsafe_js_yaml: require('./rules/no_unsafe_js_yaml'),
}, },
}; };

View file

@ -0,0 +1,90 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
module.exports = {
meta: {
fixable: 'code',
schema: [],
},
create(context) {
const sourceCode = context.getSourceCode();
const jsYamlIdentifiers = new Set();
const isUnsafeMethod = (node) => node.name === 'load' || node.name === 'dump';
return {
ImportDeclaration(node) {
if (node.source.value === 'js-yaml') {
node.specifiers.forEach((specifier) => {
jsYamlIdentifiers.add(specifier.local.name);
if (specifier.imported && isUnsafeMethod(specifier.imported)) {
context.report({
node: specifier,
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
fix(fixer) {
const replacement =
specifier.imported.name === 'load'
? fixer.replaceText(specifier.imported, 'safeLoad')
: fixer.replaceText(specifier.imported, 'safeDump');
return replacement;
},
});
}
});
}
},
CallExpression(node) {
const callee = node.callee;
if (isUnsafeMethod(callee)) {
const scope = sourceCode.getScope(node);
const variable = scope.variables.find((v) => v.name === callee.name);
if (variable && variable.defs.length) {
const [def] = variable.defs;
if (def?.parent?.source?.value === 'js-yaml') {
context.report({
node: callee,
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
fix(fixer) {
const replacement =
callee.name === 'load'
? fixer.replaceText(callee, 'safeLoad')
: fixer.replaceText(callee, 'safeDump');
return replacement;
},
});
}
}
}
if (
callee.type === 'MemberExpression' &&
isUnsafeMethod(callee.property) &&
jsYamlIdentifiers.has(callee.object.name)
) {
context.report({
node: callee.property,
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
fix(fixer) {
const replacement =
callee.property.name === 'load'
? fixer.replaceText(callee.property, 'safeLoad')
: fixer.replaceText(callee.property, 'safeDump');
return replacement;
},
});
}
},
};
},
};

View file

@ -0,0 +1,104 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
const { RuleTester } = require('eslint');
const rule = require('./no_unsafe_js_yaml');
const ruleTester = new RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
sourceType: 'module',
ecmaVersion: 2018,
},
});
ruleTester.run('no_unsafe_js_yaml', rule, {
valid: [
"import { safeLoad } from 'js-yaml'; const data = safeLoad(yamlString);",
"import { safeDump } from 'js-yaml'; const yaml = safeDump(data);",
"import * as yaml from 'js-yaml'; const data = yaml.safeLoad(yamlString);",
"import yaml from 'js-yaml'; yaml.safeLoad('yamlString');",
],
invalid: [
{
code: "import { load } from 'js-yaml'; const data = load(yamlString);",
errors: [
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
line: 1,
column: 10,
endLine: 1,
endColumn: 14,
},
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
line: 1,
column: 46,
endLine: 1,
endColumn: 50,
},
],
output: "import { safeLoad } from 'js-yaml'; const data = safeLoad(yamlString);",
},
{
code: "import { dump } from 'js-yaml'; const yaml = dump(data);",
errors: [
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
line: 1,
column: 10,
endLine: 1,
endColumn: 14,
},
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
line: 1,
column: 46,
endLine: 1,
endColumn: 50,
},
],
output: "import { safeDump } from 'js-yaml'; const yaml = safeDump(data);",
},
{
code: "import * as yaml from 'js-yaml'; const data = yaml.load(yamlString);",
errors: [
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
},
],
output: "import * as yaml from 'js-yaml'; const data = yaml.safeLoad(yamlString);",
},
{
code: "import yaml from 'js-yaml'; yaml.load('someYAMLContent')",
errors: [
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
},
],
output: "import yaml from 'js-yaml'; yaml.safeLoad('someYAMLContent')",
},
{
code: "import yaml, { safeDump } from 'js-yaml'; safeDump(data); yaml.load('someYAMLContent');",
errors: [
{
message:
'Use `safeLoad` instead of `load` and `safeDump` instead of `dump` from `js-yaml`.',
},
],
output:
"import yaml, { safeDump } from 'js-yaml'; safeDump(data); yaml.safeLoad('someYAMLContent');",
},
],
});

View file

@ -7,7 +7,7 @@
*/ */
import chalk from 'chalk'; import chalk from 'chalk';
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { isPlainObjectType } from './is_plain_object_type'; import { isPlainObjectType } from './is_plain_object_type';
/** /**
@ -32,7 +32,9 @@ export function extractByJsonPointer(document: unknown, pointer: string): unknow
throw new Error( throw new Error(
`JSON Pointer ${chalk.bold(pointer)} resolution failure. Expected ${chalk.magenta( `JSON Pointer ${chalk.bold(pointer)} resolution failure. Expected ${chalk.magenta(
path.join('/') path.join('/')
)} to be a plain object but it has type "${typeof target}" in \n\n${dump(document)}` )} to be a plain object but it has type "${typeof target}" in \n\n${safeDump(document, {
skipInvalid: true,
})}`
); );
} }
@ -66,7 +68,7 @@ export function extractObjectByJsonPointer(
throw new Error( throw new Error(
`JSON Pointer resolution failure. Expected ${chalk.magenta( `JSON Pointer resolution failure. Expected ${chalk.magenta(
pointer pointer
)} to be a plain object in \n\n${dump(document)}` )} to be a plain object in \n\n${safeDump(document, { skipInvalid: true })}`
); );
} }

View file

@ -8,7 +8,7 @@
import fs from 'fs/promises'; import fs from 'fs/promises';
import { basename, extname } from 'path'; import { basename, extname } from 'path';
import { load } from 'js-yaml'; import { safeLoad } from 'js-yaml';
import chalk from 'chalk'; import chalk from 'chalk';
import { logger } from '../logger'; import { logger } from '../logger';
import { isPlainObjectType } from './is_plain_object_type'; import { isPlainObjectType } from './is_plain_object_type';
@ -45,7 +45,7 @@ async function readYamlFile(filePath: string): Promise<Record<string, unknown>>
// Typing load's result to Record<string, unknown> is optimistic as we can't be sure // Typing load's result to Record<string, unknown> is optimistic as we can't be sure
// there is object inside a yaml file. We don't have this validation layer so far // there is object inside a yaml file. We don't have this validation layer so far
// but using JSON Schemas here should mitigate this problem. // but using JSON Schemas here should mitigate this problem.
return load(await fs.readFile(filePath, { encoding: 'utf8' })); return safeLoad(await fs.readFile(filePath, { encoding: 'utf8' }));
} }
async function readJsonFile(filePath: string): Promise<Record<string, unknown>> { async function readJsonFile(filePath: string): Promise<Record<string, unknown>> {

View file

@ -7,7 +7,7 @@
*/ */
import fs from 'fs/promises'; import fs from 'fs/promises';
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { dirname } from 'path'; import { dirname } from 'path';
export async function writeYamlDocument(filePath: string, document: unknown): Promise<void> { export async function writeYamlDocument(filePath: string, document: unknown): Promise<void> {
@ -23,21 +23,16 @@ export async function writeYamlDocument(filePath: string, document: unknown): Pr
function stringifyToYaml(document: unknown): string { function stringifyToYaml(document: unknown): string {
try { try {
// We don't want to have `undefined` values serialized into YAML.
// `JSON.stringify()` simply skips `undefined` values while js-yaml v 3.14 DOES NOT.
// js-yaml >= v4 has it fixed so `dump()`'s behavior is consistent with `JSON.stringify()`.
// Until js-yaml is updated to v4 use the hack with JSON serialization/deserialization.
const clearedDocument = JSON.parse(JSON.stringify(document));
// Disable YAML Anchors https://yaml.org/spec/1.2.2/#3222-anchors-and-aliases // Disable YAML Anchors https://yaml.org/spec/1.2.2/#3222-anchors-and-aliases
// It makes YAML much more human readable // It makes YAML much more human readable
return dump(clearedDocument, { return safeDump(document, {
noRefs: true, noRefs: true,
sortKeys: sortYamlKeys, sortKeys: sortYamlKeys,
skipInvalid: true, // Skip invalid types like `undefined`
}); });
} catch (e) { } catch (e) {
// Try to stringify with YAML Anchors enabled // Try to stringify with YAML Anchors enabled
return dump(document, { noRefs: false, sortKeys: sortYamlKeys }); return safeDump(document, { noRefs: false, sortKeys: sortYamlKeys, skipInvalid: true });
} }
} }

View file

@ -16,7 +16,7 @@ import {
unlinkSync, unlinkSync,
writeFileSync, writeFileSync,
} from 'fs'; } from 'fs';
import { dump, load } from 'js-yaml'; import { safeDump, safeLoad } from 'js-yaml';
import { OpenAPIV3 } from 'openapi-types'; import { OpenAPIV3 } from 'openapi-types';
import { bundle, BundlerConfig } from '../../src/openapi_bundler'; import { bundle, BundlerConfig } from '../../src/openapi_bundler';
@ -56,7 +56,10 @@ function dumpSpecs(folderPath: string, oasSpecs: Record<string, OpenAPIV3.Docume
mkdirSync(folderPath, { recursive: true }); mkdirSync(folderPath, { recursive: true });
for (const [fileName, oasSpec] of Object.entries(oasSpecs)) { for (const [fileName, oasSpec] of Object.entries(oasSpecs)) {
writeFileSync(join(folderPath, `${fileName}.schema.yaml`), dump(oasSpec)); writeFileSync(
join(folderPath, `${fileName}.schema.yaml`),
safeDump(oasSpec, { skipInvalid: true }) // Skip invalid types like `undefined`
);
} }
} }
@ -66,7 +69,7 @@ export function readBundledSpecs(folderPath: string): Record<string, OpenAPIV3.D
for (const fileName of readdirSync(folderPath)) { for (const fileName of readdirSync(folderPath)) {
const yaml = readFileSync(join(folderPath, fileName), { encoding: 'utf8' }); const yaml = readFileSync(join(folderPath, fileName), { encoding: 'utf8' });
bundledSpecs[fileName] = load(yaml); bundledSpecs[fileName] = safeLoad(yaml);
} }
return bundledSpecs; return bundledSpecs;

View file

@ -7,7 +7,7 @@
*/ */
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import { load } from 'js-yaml'; import { safeLoad } from 'js-yaml';
import { join } from 'path'; import { join } from 'path';
import { bundleFolder, readBundledSpecs } from './bundle_specs'; import { bundleFolder, readBundledSpecs } from './bundle_specs';
@ -25,7 +25,7 @@ describe('OpenAPI Bundler - specs with multiple modifications', () => {
const [bundledSpec] = Object.values(readBundledSpecs(outputFolderPath)); const [bundledSpec] = Object.values(readBundledSpecs(outputFolderPath));
const expected = load( const expected = safeLoad(
readFileSync(join(folderToBundlePath, 'expected.yaml'), { encoding: 'utf8' }) readFileSync(join(folderToBundlePath, 'expected.yaml'), { encoding: 'utf8' })
); );

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { OpenAPIV3 } from 'openapi-types'; import { OpenAPIV3 } from 'openapi-types';
import { bundleSpecs } from './bundle_specs'; import { bundleSpecs } from './bundle_specs';
import { createOASDocument } from '../create_oas_document'; import { createOASDocument } from '../create_oas_document';
@ -48,7 +48,8 @@ describe('OpenAPI Bundler - circular specs', () => {
}) })
); );
expect(dump(bundledSpec.paths['/api/some_api']!.get!.responses['200'])).toMatchInlineSnapshot(` expect(safeDump(bundledSpec.paths['/api/some_api']!.get!.responses['200']))
.toMatchInlineSnapshot(`
"content: "content:
application/json: application/json:
schema: &ref_0 schema: &ref_0

View file

@ -16,7 +16,7 @@ import {
unlinkSync, unlinkSync,
writeFileSync, writeFileSync,
} from 'fs'; } from 'fs';
import { dump, load } from 'js-yaml'; import { safeDump, safeLoad } from 'js-yaml';
import { OpenAPIV3 } from 'openapi-types'; import { OpenAPIV3 } from 'openapi-types';
import { merge, MergerConfig } from '../../src/openapi_merger'; import { merge, MergerConfig } from '../../src/openapi_merger';
@ -56,7 +56,10 @@ function dumpSpecs(folderPath: string, oasSpecs: Record<string, OpenAPIV3.Docume
mkdirSync(folderPath, { recursive: true }); mkdirSync(folderPath, { recursive: true });
for (const [fileName, oasSpec] of Object.entries(oasSpecs)) { for (const [fileName, oasSpec] of Object.entries(oasSpecs)) {
writeFileSync(join(folderPath, `${fileName}.schema.yaml`), dump(oasSpec)); writeFileSync(
join(folderPath, `${fileName}.schema.yaml`),
safeDump(oasSpec, { skipInvalid: true })
);
} }
} }
@ -66,7 +69,7 @@ export function readMergedSpecs(folderPath: string): Record<string, OpenAPIV3.Do
for (const fileName of readdirSync(folderPath)) { for (const fileName of readdirSync(folderPath)) {
const yaml = readFileSync(join(folderPath, fileName), { encoding: 'utf8' }); const yaml = readFileSync(join(folderPath, fileName), { encoding: 'utf8' });
mergedSpecs[fileName] = load(yaml); mergedSpecs[fileName] = safeLoad(yaml);
} }
return mergedSpecs; return mergedSpecs;

View file

@ -19,7 +19,7 @@ var allManifestPaths = Object.values(manifestsSource).flat();
try { try {
for (var manifestRelPath of allManifestPaths) { for (var manifestRelPath of allManifestPaths) {
var manifest = yaml.load(fs.readFileSync(manifestRelPath, 'utf8')); var manifest = yaml.safeLoad(fs.readFileSync(manifestRelPath, 'utf8'));
if (manifest.enabled) { if (manifest.enabled) {
manifest.enabled.forEach(function (x) { manifest.enabled.forEach(function (x) {
console.log(x); console.log(x);

View file

@ -8,7 +8,7 @@
import { readFileSync, writeFileSync } from 'fs'; import { readFileSync, writeFileSync } from 'fs';
import { resolve } from 'path'; import { resolve } from 'path';
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { Build, Config, mkdirp } from '../../lib'; import { Build, Config, mkdirp } from '../../lib';
export async function createOSPackageKibanaYML(config: Config, build: Build) { export async function createOSPackageKibanaYML(config: Config, build: Build) {
@ -24,7 +24,7 @@ export async function createOSPackageKibanaYML(config: Config, build: Build) {
[/#pid.file:.*/g, 'pid.file: /run/kibana/kibana.pid'], [/#pid.file:.*/g, 'pid.file: /run/kibana/kibana.pid'],
[ [
/#logging.appenders.default:.*kibana\.log\n/gs, /#logging.appenders.default:.*kibana\.log\n/gs,
dump({ safeDump({
logging: { logging: {
appenders: { appenders: {
file: { file: {

View file

@ -14,7 +14,7 @@ import { DEFAULTS } from '../constants';
export async function readConfig(filePath: string): Promise<PartialConfig> { export async function readConfig(filePath: string): Promise<PartialConfig> {
const data = await promises.readFile(filePath); const data = await promises.readFile(filePath);
const decodedPartialConfig = PartialConfigRT.decode(yaml.load(data.toString())); const decodedPartialConfig = PartialConfigRT.decode(yaml.safeLoad(data.toString()));
if (isLeft(decodedPartialConfig)) { if (isLeft(decodedPartialConfig)) {
throw new Error( throw new Error(
`Could not validate config: ${PathReporter.report(decodedPartialConfig).join('\n')}` `Could not validate config: ${PathReporter.report(decodedPartialConfig).join('\n')}`

View file

@ -48,7 +48,7 @@ export function getSelectorsAndResponsesFromYaml(configuration: string): {
let responses: Response[] = []; let responses: Response[] = [];
try { try {
const result = yaml.load(configuration); const result = yaml.safeLoad(configuration);
if (result) { if (result) {
// iterate selector/response types // iterate selector/response types
@ -107,5 +107,5 @@ export function getYamlFromSelectorsAndResponses(selectors: Selector[], response
return current; return current;
}, schema); }, schema);
return yaml.dump(schema); return yaml.safeDump(schema);
} }

View file

@ -44,7 +44,7 @@ describe('<ControlGeneralView />', () => {
const configuration = input?.vars?.configuration?.value; const configuration = input?.vars?.configuration?.value;
try { try {
const json = yaml.load(configuration); const json = yaml.safeLoad(configuration);
expect(json.file.selectors.length).toBe(getAllByTestId('cloud-defend-selector').length); expect(json.file.selectors.length).toBe(getAllByTestId('cloud-defend-selector').length);
expect(json.file.responses.length).toBe(getAllByTestId('cloud-defend-file-response').length); expect(json.file.responses.length).toBe(getAllByTestId('cloud-defend-file-response').length);
@ -69,7 +69,7 @@ describe('<ControlGeneralView />', () => {
const configuration = input?.vars?.configuration?.value; const configuration = input?.vars?.configuration?.value;
try { try {
const json = yaml.load(configuration); const json = yaml.safeLoad(configuration);
expect(json.file.selectors.length).toBe(getAllByTestId('cloud-defend-selector').length); expect(json.file.selectors.length).toBe(getAllByTestId('cloud-defend-selector').length);
} catch (err) { } catch (err) {
@ -91,7 +91,7 @@ describe('<ControlGeneralView />', () => {
const configuration = input?.vars?.configuration?.value; const configuration = input?.vars?.configuration?.value;
try { try {
const json = yaml.load(configuration); const json = yaml.safeLoad(configuration);
expect(json.file.responses.length).toBe(getAllByTestId('cloud-defend-file-response').length); expect(json.file.responses.length).toBe(getAllByTestId('cloud-defend-file-response').length);
} catch (err) { } catch (err) {
@ -113,7 +113,7 @@ describe('<ControlGeneralView />', () => {
const configuration = input?.vars?.configuration?.value; const configuration = input?.vars?.configuration?.value;
try { try {
const json = yaml.load(configuration); const json = yaml.safeLoad(configuration);
expect(json.process.responses.length).toBe( expect(json.process.responses.length).toBe(
getAllByTestId('cloud-defend-process-response').length getAllByTestId('cloud-defend-process-response').length
@ -166,7 +166,7 @@ describe('<ControlGeneralView />', () => {
const configuration = input?.vars?.configuration?.value; const configuration = input?.vars?.configuration?.value;
try { try {
const json = yaml.load(configuration); const json = yaml.safeLoad(configuration);
expect(json.file.responses[0].match).toHaveLength(1); expect(json.file.responses[0].match).toHaveLength(1);
} catch (err) { } catch (err) {
@ -205,7 +205,7 @@ describe('<ControlGeneralView />', () => {
const configuration = input?.vars?.configuration?.value; const configuration = input?.vars?.configuration?.value;
try { try {
const json = yaml.load(configuration); const json = yaml.safeLoad(configuration);
expect(json.file.selectors).toHaveLength(4); expect(json.file.selectors).toHaveLength(4);
expect(json.file.selectors[3].name).toEqual(json.file.selectors[0].name + '1'); expect(json.file.selectors[3].name).toEqual(json.file.selectors[0].name + '1');

View file

@ -205,7 +205,7 @@ function decodeDiscoveryRulesYaml(
defaultDiscoveryRules: IDiscoveryRule[] = [] defaultDiscoveryRules: IDiscoveryRule[] = []
): IDiscoveryRule[] { ): IDiscoveryRule[] {
try { try {
const parsedYaml: DiscoveryRulesParsedYaml = yaml.load(discoveryRulesYaml) ?? []; const parsedYaml: DiscoveryRulesParsedYaml = yaml.safeLoad(discoveryRulesYaml) ?? [];
if (parsedYaml.length === 0) { if (parsedYaml.length === 0) {
return defaultDiscoveryRules; return defaultDiscoveryRules;
@ -232,5 +232,5 @@ function encodeDiscoveryRulesYaml(discoveryRules: IDiscoveryRule[]): string {
[`${operation}-${type}`]: probe, [`${operation}-${type}`]: probe,
}) })
); );
return yaml.dump(mappedDiscoveryRules); return yaml.safeDump(mappedDiscoveryRules);
} }

View file

@ -99,7 +99,7 @@ function ensureValidMultiText(textMultiValue: string[] | undefined) {
function escapeInvalidYamlString(yamlString: string) { function escapeInvalidYamlString(yamlString: string) {
try { try {
yaml.load(yamlString); yaml.safeLoad(yamlString);
} catch (error) { } catch (error) {
if (error instanceof yaml.YAMLException) { if (error instanceof yaml.YAMLException) {
return `"${yamlString}"`; return `"${yamlString}"`;

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { generateCustomLogsYml } from './generate_custom_logs_yml'; import { generateCustomLogsYml } from './generate_custom_logs_yml';
const baseMockConfig = { const baseMockConfig = {
@ -46,7 +46,7 @@ describe('generateCustomLogsYml', () => {
it('should return a yml configuration with customConfigurations', () => { it('should return a yml configuration with customConfigurations', () => {
const mockConfig = { const mockConfig = {
...baseMockConfig, ...baseMockConfig,
customConfigurations: dump({ customConfigurations: safeDump({
['agent.retry']: { ['agent.retry']: {
enabled: true, enabled: true,
retriesCount: 3, retriesCount: 3,

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { dump, load } from 'js-yaml'; import { safeDump, safeLoad } from 'js-yaml';
export const generateCustomLogsYml = ({ export const generateCustomLogsYml = ({
datasetName = '', datasetName = '',
@ -26,7 +26,7 @@ export const generateCustomLogsYml = ({
esHost: string[]; esHost: string[];
logfileId: string; logfileId: string;
}) => { }) => {
const customConfigYaml = load(customConfigurations ?? ''); const customConfigYaml = safeLoad(customConfigurations ?? '');
const processors = [ const processors = [
{ {
add_fields: { add_fields: {
@ -38,7 +38,7 @@ export const generateCustomLogsYml = ({
}, },
]; ];
return dump({ return safeDump({
...{ ...{
outputs: { outputs: {
default: { default: {

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
interface SystemLogsStream { interface SystemLogsStream {
id: string; id: string;
@ -36,7 +36,7 @@ export const generateSystemLogsYml = ({
esHost: string[]; esHost: string[];
uuid: string; uuid: string;
}) => { }) => {
return dump({ return safeDump({
outputs: { outputs: {
default: { default: {
type: 'elasticsearch', type: 'elasticsearch',

View file

@ -12,7 +12,7 @@ import {
FleetUnauthorizedError, FleetUnauthorizedError,
type PackageClient, type PackageClient,
} from '@kbn/fleet-plugin/server'; } from '@kbn/fleet-plugin/server';
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { PackageDataStreamTypes } from '@kbn/fleet-plugin/common/types'; import { PackageDataStreamTypes } from '@kbn/fleet-plugin/common/types';
import { getObservabilityOnboardingFlow, saveObservabilityOnboardingFlow } from '../../lib/state'; import { getObservabilityOnboardingFlow, saveObservabilityOnboardingFlow } from '../../lib/state';
import type { SavedObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status'; import type { SavedObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status';
@ -501,7 +501,7 @@ function parseIntegrationsTSV(tsv: string) {
} }
const generateAgentConfig = ({ esHost, inputs = [] }: { esHost: string[]; inputs: unknown[] }) => { const generateAgentConfig = ({ esHost, inputs = [] }: { esHost: string[]; inputs: unknown[] }) => {
return dump({ return safeDump({
outputs: { outputs: {
default: { default: {
type: 'elasticsearch', type: 'elasticsearch',

View file

@ -138,7 +138,7 @@ const manageZipFields = async (beat, filePath, beatFields) => {
try { try {
await extract(filePath, { dir: beat.outputDir }); await extract(filePath, { dir: beat.outputDir });
console.log('building fields', beat.index); console.log('building fields', beat.index);
const obj = yaml.load( const obj = yaml.safeLoad(
fs.readFileSync(`${beat.outputDir}/winlogbeat-${BEATS_VERSION}-windows-x86_64/fields.yml`, { fs.readFileSync(`${beat.outputDir}/winlogbeat-${BEATS_VERSION}-windows-x86_64/fields.yml`, {
encoding: 'utf-8', encoding: 'utf-8',
}) })
@ -172,7 +172,7 @@ const manageTarFields = async (beat, filePath, beatFields) =>
return reject(new Error(err)); return reject(new Error(err));
} }
console.log('building fields', beat.index); console.log('building fields', beat.index);
const obj = yaml.load( const obj = yaml.safeLoad(
fs.readFileSync(`${beat.outputDir}/fields.yml`, { encoding: 'utf-8' }) fs.readFileSync(`${beat.outputDir}/fields.yml`, { encoding: 'utf-8' })
); );
const ebeatFields = convertSchemaToHash(obj, beatFields); const ebeatFields = convertSchemaToHash(obj, beatFields);

View file

@ -11,7 +11,7 @@ import type { KbnClient } from '@kbn/test';
import type { ToolingLog } from '@kbn/tooling-log'; import type { ToolingLog } from '@kbn/tooling-log';
import chalk from 'chalk'; import chalk from 'chalk';
import execa from 'execa'; import execa from 'execa';
import { dump } from 'js-yaml'; import { safeDump } from 'js-yaml';
import { import {
fetchFleetServerUrl, fetchFleetServerUrl,
getAgentVersionMatchingCurrentStack, getAgentVersionMatchingCurrentStack,
@ -111,7 +111,7 @@ export const startElasticAgentWithDocker = async ({
}) })
).stdout; ).stdout;
} catch (error) { } catch (error) {
log.error(dump(error)); log.error(safeDump(error));
throw error; throw error;
} }

View file

@ -6,7 +6,7 @@
*/ */
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import { load } from 'js-yaml'; import { safeLoad } from 'js-yaml';
import { FtrProviderContext } from '../../common/ftr_provider_context'; import { FtrProviderContext } from '../../common/ftr_provider_context';
export default function ApiTest({ getService }: FtrProviderContext) { export default function ApiTest({ getService }: FtrProviderContext) {
@ -39,7 +39,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
expect(req.status).to.be(200); expect(req.status).to.be(200);
const ymlConfig = load(req.text); const ymlConfig = safeLoad(req.text);
expect(ymlConfig.inputs[0].data_stream.namespace).to.be(''); expect(ymlConfig.inputs[0].data_stream.namespace).to.be('');
expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be(''); expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be('');
expect(ymlConfig.inputs[0].streams[0].paths).to.be.empty(); expect(ymlConfig.inputs[0].streams[0].paths).to.be.empty();
@ -75,7 +75,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
expect(req.status).to.be(200); expect(req.status).to.be(200);
const ymlConfig = load(req.text); const ymlConfig = safeLoad(req.text);
expect(ymlConfig.inputs[0].data_stream.namespace).to.be(namespace); expect(ymlConfig.inputs[0].data_stream.namespace).to.be(namespace);
expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be(datasetName); expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be(datasetName);
expect(ymlConfig.inputs[0].streams[0].paths).to.be.eql([logFilepath]); expect(ymlConfig.inputs[0].streams[0].paths).to.be.eql([logFilepath]);
@ -107,7 +107,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
expect(req.status).to.be(200); expect(req.status).to.be(200);
const ymlConfig = load(req.text); const ymlConfig = safeLoad(req.text);
expect(ymlConfig.inputs[0].data_stream.namespace).to.be('default'); expect(ymlConfig.inputs[0].data_stream.namespace).to.be('default');
expect(ymlConfig.inputs[0].streams.length).to.be(2); expect(ymlConfig.inputs[0].streams.length).to.be(2);
expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be('system.auth'); expect(ymlConfig.inputs[0].streams[0].data_stream.dataset).to.be('system.auth');