UNPKG

@mondaydotcomorg/atp-compiler

Version:

Production-ready compiler for transforming async iteration patterns into resumable operations with checkpoint-based state management

108 lines 3.71 kB
/** * Example Plugin: Security Validator * * Validates code for security issues before transformation * * @example * const compiler = new PluggableCompiler(); * compiler.use(new SecurityValidatorPlugin({ * forbiddenPatterns: [/eval\s*\(/], * maxComplexity: 20 * })); */ import _traverse from '@babel/traverse'; const traverse = _traverse.default || _traverse; export class SecurityValidatorPlugin { name = 'security-validator'; version = '1.0.0'; priority = 100; // Run first options; constructor(options = {}) { this.options = { forbiddenPatterns: options.forbiddenPatterns || [ /\beval\s*\(/, /new\s+Function\s*\(/, /constructor\s*\[\s*['"`]constructor['"`]\s*\]/, ], maxComplexity: options.maxComplexity || 50, maxNesting: options.maxNesting || 10, forbiddenGlobals: options.forbiddenGlobals || [ 'process', 'require', '__dirname', '__filename', ], }; } async validate(code, ast, phase) { // Only validate before transformation if (phase === 'post') { return; } // 1. Check forbidden patterns for (const pattern of this.options.forbiddenPatterns) { if (pattern.test(code)) { throw new SecurityValidationError(`Forbidden pattern detected: ${pattern}`, 'forbidden-pattern'); } } // 2. Check complexity and nesting let maxNestingFound = 0; let complexityScore = 0; traverse(ast, { enter(path) { const depth = path.scope.path.node ? getDepth(path) : 0; maxNestingFound = Math.max(maxNestingFound, depth); // Increment complexity for control flow if (path.isIfStatement() || path.isWhileStatement() || path.isForStatement() || path.isForOfStatement() || path.isSwitchCase() || path.isCatchClause()) { complexityScore++; } }, // 3. Check forbidden globals Identifier: (path) => { if (this.options.forbiddenGlobals.includes(path.node.name) && !path.scope.hasBinding(path.node.name)) { throw new SecurityValidationError(`Access to forbidden global: ${path.node.name}`, 'forbidden-global'); } }, }); if (maxNestingFound > this.options.maxNesting) { throw new SecurityValidationError(`Maximum nesting depth exceeded: ${maxNestingFound} > ${this.options.maxNesting}`, 'max-nesting'); } if (complexityScore > this.options.maxComplexity) { throw new SecurityValidationError(`Maximum complexity exceeded: ${complexityScore} > ${this.options.maxComplexity}`, 'max-complexity'); } } } /** * Security validation error */ export class SecurityValidationError extends Error { code; constructor(message, code) { super(message); this.code = code; this.name = 'SecurityValidationError'; } } /** * Get nesting depth of a path */ function getDepth(path) { let depth = 0; let current = path; while (current.parentPath) { if (current.isBlockStatement() || current.isFunctionDeclaration() || current.isArrowFunctionExpression()) { depth++; } current = current.parentPath; } return depth; } //# sourceMappingURL=security-validator-plugin.js.map