New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@monokle/validation

Package Overview
Dependencies
Maintainers
5
Versions
91
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@monokle/validation - npm Package Compare versions

Comparing version 0.29.1 to 0.30.0

37

lib/validators/custom/simpleValidator.js

@@ -6,6 +6,7 @@ import { paramCase, sentenceCase } from 'change-case';

import unset from 'lodash/unset.js';
import { isNode } from 'yaml';
import { isNode, isMap, isScalar, isPair } from 'yaml';
import { AbstractPlugin } from '../../common/AbstractPlugin.js';
import { createLocations } from '../../utils/createLocations.js';
import { isDefined } from '../../utils/isDefined.js';
import { isContainerPrefix, isPodPrefix } from './utils.js';
/**

@@ -87,3 +88,3 @@ * Validator for simple custom policies.

const path = args.path.split('.');
const node = determineClosestNodeForPath(parsedDoc, path);
const node = determineClosestNodeForPath(parsedDoc, path, resource.kind);
const region = node?.range ? this._parser.parseErrorRegion(resource, node.range) : undefined;

@@ -128,9 +129,30 @@ const locations = createLocations(resource, region, path);

* - When $container specifies `securityContext` then it underlines whole context object.
* - When $container does not specify `securityContext` then it underlines whole container object.
* - When $container does not specify `securityContext` then it falls back to the container name.
* - Note: Container objects are quite big and otherwise the whole screen turns yellow/red.
* - When the property does not relate to a container and name cannot be used, it falls back to the whole object.
*/
function determineClosestNodeForPath(resource, path, prefix = []) {
const currentPath = prefix.concat(path);
while (currentPath.length > prefix.length) {
function determineClosestNodeForPath(resource, path, resourceKind) {
const currentPath = [...path];
while (currentPath.length > 0) {
const node = resource.getIn(currentPath, true);
if (isNode(node)) {
// Less aggressive error highlighting for missing properties
// Pod objects now fall back to the parent's spec.
// Container objects now fall back to the container's name.
if (isPodPrefix(currentPath, resourceKind)) {
const podPath = currentPath.slice(0, -1);
const parent = resource.getIn(podPath, true);
const spec = isMap(parent)
? parent.items.find(i => (isScalar(i.key) ? i.key.value === 'spec' : false))
: undefined;
if (isPair(spec) && isNode(spec.key)) {
return spec.key;
}
}
if (isContainerPrefix(currentPath)) {
const nameNode = resource.getIn([...currentPath, 'name'], true);
if (isNode(nameNode)) {
return nameNode;
}
}
return node;

@@ -140,4 +162,3 @@ }

}
const node = resource.getIn(currentPath, true);
return isNode(node) ? node : undefined;
return undefined;
}

@@ -144,0 +165,0 @@ function toPluginMetadata(plugin) {

import { PodSpec, PodTemplateSpec } from 'kubernetes-types/core/v1.js';
import { YamlPath } from '../../common/types.js';
export declare function validatePodSpec(resources: any[], validateFn: (resource: any, pod: PodSpec, prefix: string) => void): void;
export declare function validatePodTemplate(resources: any[], validateFn: (resource: any, pod: PodTemplateSpec, prefix: string) => void): void;
export declare function isContainerPrefix(currentPath: YamlPath): boolean;
export declare function isPodPrefix(currentPath: YamlPath, resourceKind: string): boolean;

@@ -45,1 +45,16 @@ import { isStatefulSet } from './schemas/statefulset.apps.v1.js';

}
export function isContainerPrefix(currentPath) {
return currentPath.at(-2) === 'containers';
}
export function isPodPrefix(currentPath, resourceKind) {
if (resourceKind === 'pod') {
return currentPath.join('.') === 'spec';
}
if (resourceKind === 'CronJob') {
return currentPath.join('.') === 'spec.jobTemplate.spec.template.spec';
}
if (['Deployment', 'StatefulSet', 'DaemonSet'].includes(resourceKind)) {
return currentPath.join('.') === 'spec.template.spec';
}
return false;
}

@@ -47,2 +47,8 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { unset }) {
unset(resource, path);
return {
description: 'Removes host process for Windows. You might end up with a service with reduced functionality.',
};
},
});

@@ -26,2 +26,10 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { unset }) {
unset(resource, path);
const isPID = path.includes('hostPID');
const isIPC = path.includes('hostIPC');
const remediation = isPID ? 'Removes the host PID.' : isIPC ? 'Removes the host IPC.' : 'Removes the host network.';
const description = `${remediation} You might end up with a service with reduced functionality.`;
return { description };
},
});

@@ -41,2 +41,8 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { unset }) {
unset(resource, path);
return {
description: 'Disables usage of privileged pods. You might end up with a service with reduced functionality.',
};
},
});

@@ -63,2 +63,11 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path, problem }, { get, set }) {
const capabilities = get(resource, path);
if (!Array.isArray(capabilities))
return;
set(resource, path, capabilities.filter(c => ALLOWED.includes(c)));
return {
description: 'Removes the sys admin capability. You might end up with a degraded service.',
};
},
});

@@ -25,2 +25,3 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix: undefined, // Autofix makes no sense, they need to decide on another kind of volume.
});

@@ -48,2 +48,3 @@ import { NSA_RELATIONS, PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix: undefined, // Autofix makes no sense, they need to decide on another kind of volume.
});

@@ -22,2 +22,8 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource }) {
delete resource?.metadata?.annotations?.['container.apparmor.security.beta.kubernetes.io/*'];
return {
description: 'Removes customization of app armor.',
};
},
});

@@ -85,2 +85,6 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { unset }) {
unset(resource, path);
return { description: 'Restricts usage of SE Linux.' };
},
});

@@ -44,2 +44,9 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { get, set }) {
const procMount = get(resource, path);
if (!procMount)
return;
set(resource, path, 'Default');
return { description: 'Sets the default Proc Mount ' };
},
});

@@ -51,2 +51,6 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { set }) {
set(resource, path, 'RuntimeDefault');
return { description: 'Changes profile from Unconfined to RuntimeDefault.' };
},
});

@@ -31,2 +31,9 @@ import { PSS_RELATIONS } from '../../../taxonomies/index.js';

},
fix({ resource, path }, { get, set }) {
const capabilities = get(resource, path);
if (!Array.isArray(capabilities))
return;
set(resource, path, capabilities.filter(c => ALLOWED.includes(c)));
return { description: 'Removes unsafe sysctl.' };
},
});

@@ -41,2 +41,3 @@ import { defineRule } from '../../custom/config.js';

},
fix: undefined, // Autofix cannot decide the desired allowed volume type.
});

@@ -18,3 +18,3 @@ import { CIS_RELATIONS, NSA_RELATIONS, PSS_RELATIONS } from '../../../taxonomies/index.js';

const allowPrivilegeEscalation = container.securityContext?.allowPrivilegeEscalation;
const valid = allowPrivilegeEscalation === false;
const valid = !allowPrivilegeEscalation;
if (valid)

@@ -28,3 +28,3 @@ return;

const allowPrivilegeEscalation = container.securityContext?.allowPrivilegeEscalation;
const valid = allowPrivilegeEscalation === false;
const valid = !allowPrivilegeEscalation;
if (valid)

@@ -38,3 +38,3 @@ return;

const allowPrivilegeEscalation = container.securityContext?.allowPrivilegeEscalation;
const valid = allowPrivilegeEscalation === false;
const valid = !allowPrivilegeEscalation;
if (valid)

@@ -48,2 +48,6 @@ return;

},
fix({ resource, path }, { set }) {
set(resource, path, false);
return { description: 'Disables privilege escalation. You might end up with a service with reduced functionality.' };
},
});

@@ -43,2 +43,6 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js';

},
fix({ resource, path }, { set }) {
set(resource, path, true);
return { description: 'Disables running as root. You might end up with a service with reduced functionality.' };
},
});

@@ -47,2 +47,6 @@ import { NSA_RELATIONS } from '../../../taxonomies/nsa.js';

},
fix({ resource, path }, { unset }) {
unset(resource, path);
return { description: 'Removes running as root user. You might end up with a service with reduced functionality.' };
},
});

@@ -58,2 +58,6 @@ import { PSS_RELATIONS } from '../../../taxonomies/pss.js';

},
fix({ resource, path }, { set }) {
set(resource, path, 'RuntimeDefault');
return { description: 'Changes profile to RuntimeDefault.' };
},
});
import { PSS_RELATIONS } from '../../../taxonomies/index.js';
import { defineRule } from '../../custom/config.js';
import { validatePodSpec } from '../../custom/utils.js';
const ALLOWED_DROP = 'ALL'; // Any list of capabilities that includes ALL
const REQUIRED_DROP = 'ALL'; // Any list of capabilities that includes ALL
const ALLOWED_ADD = ['NET_BIND_SERVICE'];

@@ -19,4 +19,4 @@ export const capabilitiesStrict = defineRule({

pod.initContainers?.forEach((container, index) => {
const validDrop = container.securityContext?.capabilities?.drop?.some(c => c === ALLOWED_DROP) ?? false;
if (validDrop) {
const validDrop = container.securityContext?.capabilities?.drop?.some(c => c === REQUIRED_DROP) ?? false;
if (!validDrop) {
report(resource, {

@@ -26,4 +26,4 @@ path: `${prefix}.initContainers.${index}.securityContext.capabilities.drop`,

}
const validAdd = container.securityContext?.capabilities?.add?.every(c => ALLOWED_ADD.includes(c));
if (validAdd) {
const validAdd = container.securityContext?.capabilities?.add?.every(c => ALLOWED_ADD.includes(c)) ?? true;
if (!validAdd) {
report(resource, {

@@ -35,4 +35,4 @@ path: `${prefix}.initContainers.${index}.securityContext.capabilities.add`,

pod.ephemeralContainers?.forEach((container, index) => {
const validDrop = container.securityContext?.capabilities?.drop?.some(c => c === ALLOWED_DROP) ?? false;
if (validDrop) {
const validDrop = container.securityContext?.capabilities?.drop?.some(c => c === REQUIRED_DROP) ?? false;
if (!validDrop) {
report(resource, {

@@ -42,4 +42,4 @@ path: `${prefix}.ephemeralContainers.${index}.securityContext.capabilities.drop`,

}
const validAdd = container.securityContext?.capabilities?.add?.every(c => ALLOWED_ADD.includes(c));
if (validAdd) {
const validAdd = container.securityContext?.capabilities?.add?.every(c => ALLOWED_ADD.includes(c)) ?? true;
if (!validAdd) {
report(resource, {

@@ -51,4 +51,4 @@ path: `${prefix}.ephemeralContainers.${index}.securityContext.capabilities.add`,

pod.containers.forEach((container, index) => {
const validDrop = container.securityContext?.capabilities?.drop?.some(c => c === ALLOWED_DROP) ?? false;
if (validDrop) {
const validDrop = container.securityContext?.capabilities?.drop?.some(c => c === REQUIRED_DROP) ?? false;
if (!validDrop) {
report(resource, {

@@ -58,4 +58,4 @@ path: `${prefix}.containers.${index}.securityContext.capabilities.drop`,

}
const validAdd = container.securityContext?.capabilities?.add?.every(c => ALLOWED_ADD.includes(c));
if (validAdd) {
const validAdd = container.securityContext?.capabilities?.add?.every(c => ALLOWED_ADD.includes(c)) ?? true;
if (!validAdd) {
report(resource, {

@@ -68,2 +68,16 @@ path: `${prefix}.containers.${index}.securityContext.capabilities.add`,

},
fix({ resource, path }, { get, set }) {
if (path.endsWith('.drop')) {
set(resource, path, ['ALL']);
return { description: 'Drops all capabilities. You might end up with a degraded service.' };
}
if (path.endsWith('.add')) {
const capabilities = get(resource, path);
if (!Array.isArray(capabilities))
return;
const allowedCapabilities = capabilities.filter(c => ALLOWED_ADD.includes(c));
set(resource, path, allowedCapabilities);
return { description: 'Removes disallowed capabilities. You might end up with a degraded service.' };
}
},
});

@@ -36,5 +36,5 @@ import { CIS_RELATIONS, NSA_RELATIONS } from '../../../taxonomies/index.js';

fix({ resource, path }, { set }) {
set(resource, path, 'ALL');
return { description: 'Drops all capabilities.' };
set(resource, path, ['ALL']);
return { description: 'Drops all capabilities. You might end up with a degraded service.' };
},
});
{
"name": "@monokle/validation",
"version": "0.29.1",
"version": "0.30.0",
"description": "Kubernetes resource validation",

@@ -5,0 +5,0 @@ "author": "Kubeshop",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc