From 2292b843ba1fe7114cb7de311d1f8ddfb24e1c1f Mon Sep 17 00:00:00 2001 From: JohnDoe6345789 Date: Fri, 26 Dec 2025 01:16:07 +0000 Subject: [PATCH] docs: dbal,script,lua (2 files) --- .../entities/lua_script/create_lua_script.hpp | 40 +++-- dbal/docs/CVE_ANALYSIS_2025_12.md | 149 ++++++++++++++++-- 2 files changed, 162 insertions(+), 27 deletions(-) diff --git a/dbal/cpp/src/entities/lua_script/create_lua_script.hpp b/dbal/cpp/src/entities/lua_script/create_lua_script.hpp index 206797774..8273692b2 100644 --- a/dbal/cpp/src/entities/lua_script/create_lua_script.hpp +++ b/dbal/cpp/src/entities/lua_script/create_lua_script.hpp @@ -18,28 +18,44 @@ namespace lua_script { * Create a new Lua script in the store */ inline Result create(InMemoryStore& store, const CreateLuaScriptInput& input) { - if (input.name.empty() || input.name.length() > 100) { - return Error::validationError("Name must be between 1 and 100 characters"); + if (!validation::isValidLuaScriptName(input.name)) { + return Error::validationError("Lua script name must be 1-255 characters"); } - if (input.code.empty()) { - return Error::validationError("Script code cannot be empty"); + if (!validation::isValidLuaScriptCode(input.code)) { + return Error::validationError("Lua script code must be a non-empty string"); } - if (!validation::isValidLuaSyntax(input.code)) { - return Error::validationError("Invalid Lua syntax"); + if (!validation::isValidLuaTimeout(input.timeout_ms)) { + return Error::validationError("Timeout must be between 100 and 30000 ms"); } - + if (input.created_by.empty()) { + return Error::validationError("created_by is required"); + } + + for (const auto& entry : input.allowed_globals) { + if (entry.empty()) { + return Error::validationError("allowed_globals must contain non-empty strings"); + } + } + + if (store.lua_script_names.find(input.name) != store.lua_script_names.end()) { + return Error::conflict("Lua script name already exists: " + input.name); + } + LuaScript script; - script.id = store.generateId("lua_script", ++store.lua_script_counter); + script.id = store.generateId("lua", ++store.lua_script_counter); script.name = input.name; script.description = input.description; script.code = input.code; - script.category = input.category; - script.is_active = input.is_active; + script.is_sandboxed = input.is_sandboxed; + script.allowed_globals = input.allowed_globals; + script.timeout_ms = input.timeout_ms; + script.created_by = input.created_by; script.created_at = std::chrono::system_clock::now(); script.updated_at = script.created_at; - + store.lua_scripts[script.id] = script; - + store.lua_script_names[script.name] = script.id; + return Result(script); } diff --git a/dbal/docs/CVE_ANALYSIS_2025_12.md b/dbal/docs/CVE_ANALYSIS_2025_12.md index a84e85502..5bfe1b897 100644 --- a/dbal/docs/CVE_ANALYSIS_2025_12.md +++ b/dbal/docs/CVE_ANALYSIS_2025_12.md @@ -537,25 +537,144 @@ class SecurePathResolver { - No server-side encryption enforcement - No bucket policy validation for public access -**Recommendation**: +**🏰 Fort Knox Remediation**: ```typescript -async validateBucketSecurity(): Promise { - const { GetBucketPolicyStatusCommand, GetBucketEncryptionCommand } = - await import('@aws-sdk/client-s3') +import { + S3Client, + GetBucketPolicyStatusCommand, + GetBucketEncryptionCommand, + GetBucketVersioningCommand, + GetBucketLoggingCommand, + GetPublicAccessBlockCommand +} from '@aws-sdk/client-s3' + +/** + * Fort Knox S3 Security Validator + * Ensures bucket meets security requirements before any operation + */ +class S3SecurityValidator { + private s3Client: S3Client + private validatedBuckets = new Map() + private static readonly VALIDATION_TTL_MS = 300_000 // 5 minutes - // Check bucket isn't public - const policyStatus = await this.s3Client.send( - new GetBucketPolicyStatusCommand({ Bucket: this.bucket }) - ) - if (policyStatus.PolicyStatus?.IsPublic) { - throw DBALError.internal('S3 bucket must not be public') + async validateBucketSecurity(bucket: string): Promise { + // Check cache first + const cached = this.validatedBuckets.get(bucket) + if (cached && Date.now() - cached.timestamp < S3SecurityValidator.VALIDATION_TTL_MS) { + if (!cached.valid) { + throw DBALError.forbidden(`Bucket ${bucket} failed security validation`) + } + return + } + + const violations: string[] = [] + + // CHECK 1: Public Access Block (must be enabled) + try { + const publicAccess = await this.s3Client.send( + new GetPublicAccessBlockCommand({ Bucket: bucket }) + ) + const config = publicAccess.PublicAccessBlockConfiguration + if (!config?.BlockPublicAcls || + !config?.BlockPublicPolicy || + !config?.IgnorePublicAcls || + !config?.RestrictPublicBuckets) { + violations.push('Public access block not fully enabled') + } + } catch (error: any) { + if (error.name !== 'NoSuchPublicAccessBlockConfiguration') { + violations.push('Public access block not configured') + } + } + + // CHECK 2: Bucket Policy Status (must not be public) + try { + const policyStatus = await this.s3Client.send( + new GetBucketPolicyStatusCommand({ Bucket: bucket }) + ) + if (policyStatus.PolicyStatus?.IsPublic) { + violations.push('Bucket policy allows public access') + } + } catch (error: any) { + // No policy is fine + } + + // CHECK 3: Encryption (must be enabled with AES-256 or KMS) + try { + const encryption = await this.s3Client.send( + new GetBucketEncryptionCommand({ Bucket: bucket }) + ) + const rules = encryption.ServerSideEncryptionConfiguration?.Rules || [] + const hasEncryption = rules.some(rule => { + const algo = rule.ApplyServerSideEncryptionByDefault?.SSEAlgorithm + return algo === 'AES256' || algo === 'aws:kms' + }) + if (!hasEncryption) { + violations.push('Server-side encryption not enabled') + } + } catch (error: any) { + violations.push('Encryption configuration not found') + } + + // CHECK 4: Versioning (recommended for data protection) + try { + const versioning = await this.s3Client.send( + new GetBucketVersioningCommand({ Bucket: bucket }) + ) + if (versioning.Status !== 'Enabled') { + // Warning only, not a blocking violation + console.warn(`[SECURITY] Bucket ${bucket}: versioning not enabled (recommended)`) + } + } catch {} + + // CHECK 5: Access Logging (recommended for audit) + try { + const logging = await this.s3Client.send( + new GetBucketLoggingCommand({ Bucket: bucket }) + ) + if (!logging.LoggingEnabled) { + console.warn(`[SECURITY] Bucket ${bucket}: access logging not enabled (recommended)`) + } + } catch {} + + // Cache result + const isValid = violations.length === 0 + this.validatedBuckets.set(bucket, { timestamp: Date.now(), valid: isValid }) + + if (!isValid) { + this.logSecurityViolation('S3_BUCKET_SECURITY_FAILURE', { bucket, violations }) + throw DBALError.forbidden( + `Bucket security validation failed: ${violations.join(', ')}` + ) + } } - // Verify encryption - const encryption = await this.s3Client.send( - new GetBucketEncryptionCommand({ Bucket: this.bucket }) - ) - // Validate encryption settings... + private logSecurityViolation(event: string, details: unknown): void { + console.error(JSON.stringify({ + timestamp: new Date().toISOString(), + severity: 'CRITICAL', + event, + details + })) + } +} + +// Integration: Call before every S3 operation +class SecureS3Storage implements BlobStorage { + private validator: S3SecurityValidator + + async upload(key: string, data: Buffer, options: UploadOptions): Promise { + await this.validator.validateBucketSecurity(this.bucket) + + // Also enforce client-side encryption for sensitive data + const encryptedData = await this.encryptIfRequired(data, options) + + return this.doUpload(key, encryptedData, { + ...options, + ServerSideEncryption: 'aws:kms', // Force KMS encryption + BucketKeyEnabled: true, // Cost optimization + }) + } } ```