in cloudrun-malware-scanner/config.ts [89:235]
async function validateConfig(config: any, storage: Storage): Promise<Config> {
delete config.comments;
if (config.buckets == null || config.buckets.length === 0) {
logger.fatal(`No buckets configured for scanning`);
throw new Error('No buckets configured');
}
logger.info('BUCKET_CONFIG: ' + JSON.stringify(config, null, 2));
// Check buckets are specified and exist.
let success = true;
for (let x = 0; x < config.buckets.length; x++) {
const bucketDefs = config.buckets[x] as BucketDefs;
for (const bucketType of BUCKET_TYPES) {
if (
!(await checkBucketExists(
bucketDefs[bucketType],
`config.buckets[${x.toString()}].${bucketType}`,
storage,
))
) {
success = false;
}
}
if (
bucketDefs.unscanned === bucketDefs.clean ||
bucketDefs.unscanned === bucketDefs.quarantined ||
bucketDefs.clean === bucketDefs.quarantined
) {
logger.fatal(
`Config Error: buckets[${x.toString()}]: bucket names are not unique`,
);
success = false;
}
}
if (
!(await checkBucketExists(
config.ClamCvdMirrorBucket as string,
'ClamCvdMirrorBucket',
storage,
))
) {
success = false;
}
// Validate ignoreZeroLengthFiles
if (config.ignoreZeroLengthFiles == null) {
config.ignoreZeroLengthFiles = false;
} else if (typeof config.ignoreZeroLengthFiles !== 'boolean') {
logger.fatal(
`Config Error: ignoreZeroLengthFiles must be true or false: ${JSON.stringify(config.ignoreZeroLengthFiles)}`,
);
success = false;
}
// Validate fileExclusionPatterns[] and convert to fileExclusionRegexps[]
config.fileExclusionRegexps = [];
if (config.fileExclusionPatterns != null) {
if (!(config.fileExclusionPatterns instanceof Array)) {
logger.fatal(
`Config Error: fileExclusionPatterns must be an array of Strings`,
);
success = false;
} else {
// config.fileExclusionPatterns is an array, check each value and
// convert to a regexp in fileExclusionRegexps[]
for (let i = 0; i < config.fileExclusionPatterns.length; i++) {
let pattern: string | undefined;
let flags: string | undefined;
// Each element can either be a simple pattern:
// "^.*\\.tmp$"
// or an array with pattern and flags, eg for case-insensive matching:
// [ "^.*\\tmp$", "i" ]
const element = config.fileExclusionPatterns[i] as
| string
| Array<string>;
if (typeof element === 'string') {
// validate regex as simple string
pattern = element;
} else if (
Array.isArray(element) &&
element.length <= 2 &&
element.length >= 1 &&
typeof element[0] === 'string'
) {
// validate regex as [pattern, flags]
pattern = element[0];
flags = element[1];
} else {
pattern = undefined;
}
if (pattern == null) {
logger.fatal(
`Config Error: fileExclusionPatterns[${i}] must be either a string or an array of 2 strings: ${JSON.stringify(config.fileExclusionPatterns[i])}`,
);
success = false;
} else {
try {
config.fileExclusionRegexps[i] = new RegExp(pattern, flags);
} catch (e) {
logger.fatal(
e,
`Config Error: fileExclusionPatterns[${i}]: Regexp compile failed for ${JSON.stringify(config.fileExclusionPatterns[i])}: ${e as Error}`,
);
success = false;
}
}
}
}
}
delete config.fileExclusionPatterns;
// Validate quarantine.fileExtensionAllowList[]
config.quarantine = config.quarantine ?? {};
try {
config.quarantine.fileExtensionAllowList = validateFileExtensionList(
config.quarantine.fileExtensionAllowList,
);
} catch (e) {
logger.fatal(
e,
`Config Error: quarantine.fileExtensionAllowList[]: ${(e as Error).message}`,
);
success = false;
}
// Validate quarantine.fileExtensionDenyList[]
try {
config.quarantine.fileExtensionDenyList = validateFileExtensionList(
config.quarantine.fileExtensionDenyList,
);
} catch (e) {
logger.fatal(
e,
`Config Error: quarantine.fileExtensionDenyList[]: ${(e as Error).message}`,
);
success = false;
}
if (!success) {
throw new Error('Invalid configuration');
}
return Object.freeze(config as Config);
}