# Module: Configuration Validators # Purpose: Provides validation functions for configuration integrity, types, and semantic correctness. # Dependencies: None (core utility) # Configuration Validation and Detection Engine # Validates configuration structures and detects potential security/dependency issues use std log # Validate interpolation patterns and detect potential issues export def validate-interpolation [ config: record --detailed = false # Show detailed validation results ] { mut errors = [] mut warnings = [] # Convert config to JSON for pattern detection let json_str = ($config | to json) # Check for unresolved interpolation patterns let unresolved_patterns = (detect-unresolved-patterns $json_str) if ($unresolved_patterns | length) > 0 { $errors = ($errors | append { type: "unresolved_interpolation" severity: "error" patterns: $unresolved_patterns message: $"Unresolved interpolation patterns found: ($unresolved_patterns | str join ', ')" }) } # Check for circular dependencies let circular_deps = (detect-circular-dependencies $json_str) if ($circular_deps | length) > 0 { $errors = ($errors | append { type: "circular_dependency" severity: "error" dependencies: $circular_deps message: $"Circular interpolation dependencies detected: ($circular_deps | str join ', ')" }) } # Check for unsafe environment variable access let unsafe_env_vars = (detect-unsafe-env-patterns $json_str) if ($unsafe_env_vars | length) > 0 { $warnings = ($warnings | append { type: "unsafe_env_access" severity: "warning" variables: $unsafe_env_vars message: $"Potentially unsafe environment variable access: ($unsafe_env_vars | str join ', ')" }) } # Validate git repository context let git_validation = (validate-git-context $json_str) if not $git_validation.valid { $warnings = ($warnings | append { type: "git_context" severity: "warning" message: $git_validation.message }) } let has_errors = ($errors | length) > 0 let has_warnings = ($warnings | length) > 0 if not $detailed and $has_errors { let error_messages = ($errors | each { |err| $err.message }) error make { msg: ($error_messages | str join "; ") } } { valid: (not $has_errors), errors: $errors, warnings: $warnings, summary: { total_errors: ($errors | length), total_warnings: ($warnings | length), interpolation_patterns_detected: (count-interpolation-patterns $json_str) } } } # Security-hardened interpolation with input validation export def secure-interpolation [ config: record --allow-unsafe = false # Allow potentially unsafe patterns --max-depth = 5 # Maximum interpolation depth ] { # Security checks before interpolation let security_validation = (validate-interpolation-security $config $allow_unsafe) if not $security_validation.valid { error make { msg: $"Security validation failed: ($security_validation.errors | str join '; ')" } } # Apply interpolation with depth limiting let base_path = ($config | get -o paths.base | default "") if ($base_path | is-not-empty) { interpolate-with-depth-limit $config $base_path $max_depth } else { $config } } # Detect unresolved interpolation patterns export def detect-unresolved-patterns [ text: string ] { # Find patterns that look like interpolation but might not be handled let unknown_patterns = ($text | str replace --regex "\\{\\{([^}]+)\\}\\}" "") # Known patterns that should be resolved let known_patterns = [ "paths.base" "env\\." "now\\." "git\\." "sops\\." "providers\\." "path\\.join" ] mut unresolved = [] # Check for patterns that don't match known types let all_matches = ($text | str replace --regex "\\{\\{([^}]+)\\}\\}" "$1") if ($all_matches | str contains "{{") { # Basic detection - in a real implementation, this would be more sophisticated let potential_unknown = ($text | str replace --regex "\\{\\{(\\w+\\.\\w+)\\}\\}" "") if ($text | str contains "{{unknown.") { $unresolved = ($unresolved | append "unknown.*") } } $unresolved } # Detect circular interpolation dependencies export def detect-circular-dependencies [ text: string ] { mut circular_deps = [] # Simple detection for self-referencing patterns if (($text | str contains "{{paths.base}}") and ($text | str contains "paths.base.*{{paths.base}}")) { $circular_deps = ($circular_deps | append "paths.base -> paths.base") } $circular_deps } # Detect unsafe environment variable patterns export def detect-unsafe-env-patterns [ text: string ] { mut unsafe_vars = [] # Patterns that might be dangerous let dangerous_patterns = ["PATH" "LD_LIBRARY_PATH" "PYTHONPATH" "SHELL" "PS1"] for pattern in $dangerous_patterns { if ($text | str contains $"{{env.($pattern)}}") { $unsafe_vars = ($unsafe_vars | append $pattern) } } $unsafe_vars } # Validate git repository context for git interpolations export def validate-git-context [ text: string ] { if ($text | str contains "{{git.") { # Check if we're in a git repository let git_check = (do { ^git rev-parse --git-dir err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) } | complete) let is_git_repo = ($git_check.exit_code == 0) if not $is_git_repo { return { valid: false message: "Git interpolation patterns detected but not in a git repository" } } } { valid: true, message: "" } } # Count interpolation patterns for metrics export def count-interpolation-patterns [ text: string ] { # Count all {{...}} patterns by finding matches # Simple approximation: count occurrences of "{{" let pattern_count = ($text | str replace --all "{{" "\n{{" | lines | where ($it | str contains "{{") | length) $pattern_count } # Validate interpolation security def validate-interpolation-security [ config: record allow_unsafe: bool ] { mut errors = [] let json_str = ($config | to json) # Check for code injection patterns let dangerous_patterns = [ "\\$\\(" "\\`" "\\;" "\\|\\|" "\\&&" "rm " "sudo " "eval " "exec " ] for pattern in $dangerous_patterns { if ($json_str =~ $pattern) { $errors = ($errors | append $"Potential code injection pattern detected: ($pattern)") } } # Check for unsafe environment variable access if not $allow_unsafe { let unsafe_env_vars = ["PATH" "LD_LIBRARY_PATH" "PYTHONPATH" "PS1" "PROMPT_COMMAND"] for var in $unsafe_env_vars { if ($json_str | str contains $"{{env.($var)}}") { $errors = ($errors | append $"Unsafe environment variable access: ($var)") } } } # Check for path traversal attempts if (($json_str | str contains "../") or ($json_str | str contains "..\\")) { $errors = ($errors | append "Path traversal attempt detected") } { valid: (($errors | length) == 0) errors: $errors } }