UNPKG

@cosmstack/blackshield

Version:

A developer-first security toolkit for React/Next.js applications

139 lines (133 loc) 4.39 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/build/vite-plugin.ts var vite_plugin_exports = {}; __export(vite_plugin_exports, { blackshieldVite: () => blackshieldVite }); module.exports = __toCommonJS(vite_plugin_exports); // src/core/env-validator.ts var import_zod = require("zod"); // src/config/defaults.ts var DEFAULT_CONFIG = { dev: process.env.NODE_ENV === "development", envValidation: { allowedPublicVars: ["NEXT_PUBLIC_APP_URL", "NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_VERCEL_URL"], schema: void 0 }, xssProtection: { autoSanitize: true, customRules: {} }, boundaryProtection: { validateServerProps: true, customValidators: {} }, csrfProtection: { enabled: false, tokenHeader: "x-csrf-token", tokenCookie: "csrf-token", tokenExpiry: 3600 } }; var DANGEROUS_ENV_PATTERNS = [ /^NEXT_PUBLIC_.*SECRET/i, /^NEXT_PUBLIC_.*KEY/i, /^NEXT_PUBLIC_.*TOKEN/i, /^NEXT_PUBLIC_.*PASSWORD/i, /^NEXT_PUBLIC_.*PRIVATE/i, /^NEXT_PUBLIC_.*API_SECRET/i, /^NEXT_PUBLIC_.*DATABASE/i ]; // src/core/env-validator.ts function validateEnvironmentVariables(config = {}) { const errors = []; const warnings = []; const exposedVars = []; const publicVars = Object.keys(process.env).filter((key) => key.startsWith("NEXT_PUBLIC_")); exposedVars.push(...publicVars); for (const varName of publicVars) { const isDangerous = DANGEROUS_ENV_PATTERNS.some((pattern) => pattern.test(varName)); if (isDangerous) { const isAllowed = config.allowedPublicVars?.includes(varName); if (!isAllowed) { errors.push( `Potentially sensitive environment variable exposed: ${varName}. Consider moving to server-side only or add to allowedPublicVars if intentional.` ); } } } if (config.allowedPublicVars) { for (const varName of publicVars) { if (!config.allowedPublicVars.includes(varName)) { warnings.push( `Environment variable ${varName} is not in allowedPublicVars list. Consider adding it explicitly or removing NEXT_PUBLIC_ prefix.` ); } } } if (config.schema) { try { const envObject = Object.fromEntries(publicVars.map((key) => [key, process.env[key]])); config.schema.parse(envObject); } catch (error) { if (error instanceof import_zod.ZodError) { errors.push(`Environment schema validation failed: ${error.message}`); } else { errors.push( `Environment schema validation failed: ${error instanceof Error ? error.message : "Unknown error"}` ); } } } return { isValid: errors.length === 0, errors, warnings, exposedVars }; } // src/build/vite-plugin.ts function blackshieldVite(options = {}) { return { name: "blackshield", buildStart() { const validation = validateEnvironmentVariables(options.config?.envValidation); if (!validation.isValid) { console.error("\n\u{1F6E1}\uFE0F Blackshield: Environment validation failed!"); validation.errors.forEach((error) => { console.error(`\u274C ${error}`); }); if (options.failOnEnvErrors) { throw new Error("Build failed due to environment security issues"); } } if (validation.warnings.length > 0) { console.warn("\n\u{1F6E1}\uFE0F Blackshield: Environment warnings:"); validation.warnings.forEach((warning) => { console.warn(`\u26A0\uFE0F ${warning}`); }); } } }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { blackshieldVite });