This document tracks the implementation of security and stability improvements for oudenv.sh, following the improvement plan with parallel BATS unit testing.
Problem: Unquoted variables can cause word splitting and glob expansion, leading to security vulnerabilities and unexpected behavior.
Implementation Steps:
- Scan oudenv.sh for all variable references
- Quote all variable expansions:
"${var}"instead of${var}or$var - Pay special attention to:
- Command substitutions:
"$(command)" - Array expansions:
"${array[@]}" - Path variables:
"${OUD_BASE}","${ORACLE_INSTANCE_BASE}" - User input: instance names, parameters
- Command substitutions:
Test Coverage: test_oudenv_security.bats lines 34-64
Status: ⏳ Not started
Problem: No validation of instance names and other inputs allows command injection and path traversal attacks.
Implementation Steps:
-
Add
validate_instance_name()function:validate_instance_name() { local name="$1" # Allow only alphanumeric, underscore, hyphen if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then echo "ERROR: Invalid instance name: $name" return 1 fi # Check length (max 255 chars) if [[ ${#name} -gt 255 ]]; then echo "ERROR: Instance name too long: $name" return 1 fi return 0 }
-
Add
validate_port()function:validate_port() { local port="$1" # Check if numeric if [[ ! "$port" =~ ^[0-9]+$ ]]; then echo "ERROR: Port must be numeric: $port" return 1 fi # Check range (1-65535) if (( port < 1 || port > 65535 )); then echo "ERROR: Port out of range: $port" return 1 fi return 0 }
-
Call validation functions before using inputs
Test Coverage: test_oudenv_security.bats lines 69-127
Status: ⏳ Not started
Problem: Unsafe temp file creation and file operations create race conditions and security vulnerabilities.
Implementation Steps:
-
Replace predictable temp file names with
mktemp:# BAD temp_file="/tmp/oudenv_$$" # GOOD temp_file="$(mktemp -t oudenv.XXXXXX)" || { echo "ERROR: Cannot create temp file"; return 1; } trap 'rm -f "$temp_file"' EXIT
-
Set restrictive permissions:
mktemp -t oudenv.XXXXXX chmod 600 "$temp_file" -
Add file existence checks before sourcing:
if [[ -f "$config_file" ]] && [[ -r "$config_file" ]]; then source "$config_file" else echo "ERROR: Config file not found or not readable: $config_file" return 1 fi
-
Prevent symlink attacks:
# Check if file is a regular file (not symlink) if [[ ! -f "$file" ]] || [[ -L "$file" ]]; then echo "ERROR: File is not a regular file: $file" return 1 fi
Test Coverage: test_oudenv_security.bats lines 132-167
Status: ⏳ Not started
Problem: Insufficient error handling causes silent failures and difficult-to-debug issues.
Implementation Steps:
-
Add comprehensive error checking:
# Check critical variables if [[ -z "${OUD_BASE}" ]]; then echo "ERROR: OUD_BASE not set" >&2 return 10 fi if [[ ! -d "${OUD_BASE}" ]]; then echo "ERROR: OUD_BASE directory does not exist: ${OUD_BASE}" >&2 return 11 fi
-
Implement cleanup on error:
cleanup() { local exit_code=$? # Remove temp files [[ -n "${temp_file}" ]] && rm -f "${temp_file}" # Reset environment on error if (( exit_code != 0 )); then unset OUD_INSTANCE fi return $exit_code } trap cleanup EXIT
-
Provide informative error messages with error codes
Test Coverage: test_oudenv_stability.bats lines 34-92
Status: ⏳ Not started
Problem: Brittle port parsing fails with non-standard formats and doesn't validate values.
Implementation Steps:
-
Robust port extraction from oudtab:
parse_oudtab_entry() { local instance="$1" local oudtab_line oudtab_line=$(grep "^${instance}:" "${OUDTAB}" | head -1) if [[ -z "$oudtab_line" ]]; then echo "ERROR: Instance not found in oudtab: $instance" >&2 return 1 fi IFS=':' read -r inst version port port_ssl port_admin port_rep status <<< "$oudtab_line" # Validate and export ports if [[ -n "$port" ]]; then validate_port "$port" || return 1 export OUD_PORT="$port" fi # ... repeat for other ports }
-
Fallback to process detection if oudtab missing
-
Handle missing or invalid ports gracefully
Test Coverage: test_oudenv_stability.bats lines 97-147
Status: ⏳ Not started
Problem: Paths with symlinks, relative references, or special characters cause issues.
Implementation Steps:
-
Normalize all paths:
normalize_path() { local path="$1" # Resolve to absolute path path=$(cd "$path" 2>/dev/null && pwd -P) || return 1 # Remove trailing slashes path="${path%/}" echo "$path" }
-
Use normalized paths consistently
-
Add symlink resolution
Test Coverage: test_oudenv_stability.bats lines 185-218
Status: ⏳ Not started
tests/
├── README.md # Testing documentation
├── common.bash # Shared test utilities
├── fixtures/ # Test data
│ ├── oudtab.sample
│ └── oudenv.conf.sample
├── test_helper/ # BATS libraries
│ ├── bats-support/
│ ├── bats-assert/
│ └── bats-file/
├── test_oudenv_security.bats # Security tests (30+ tests)
└── test_oudenv_stability.bats # Stability tests (35+ tests)
# Setup BATS (one-time)
./setup_bats.sh
# Run all tests
bats tests/*.bats
# Run specific test suite
bats tests/test_oudenv_security.bats
bats tests/test_oudenv_stability.bats
# Run specific test
bats tests/test_oudenv_security.bats -f "quote"- Write test for the feature/fix (initially marked as
skip) - Implement the fix in oudenv.sh
- Remove
skipfrom the test - Run test to verify fix:
bats tests/test_*.bats - Iterate until test passes
- Commit with test and implementation together
- Total tests created: 65+
- Security tests: 30 (all marked
skipuntil implementation) - Stability tests: 35 (all marked
skipuntil implementation) - Tests passing: 0 (implementation not started)
- ✅ Setup BATS infrastructure
- ⏳ Variable quoting (all instances)
- ⏳ Input validation functions
- ⏳ Activate and verify security tests
- ⏳ Secure file operations
- ⏳ Comprehensive error handling
- ⏳ Cleanup on error
- ⏳ Activate and verify error handling tests
- ⏳ Port parsing improvements
- ⏳ Path resolution
- ⏳ Process detection improvements
- ⏳ Activate and verify stability tests
Before considering a fix complete:
- Implementation in oudenv.sh
- Remove
skipfrom relevant BATS tests - All tests pass:
bats tests/*.bats - Manual testing with real OUD instances
- No regressions in existing functionality
- Update this document with status
- Commit changes with descriptive message
- All tests are initially marked as
skipto prevent failures before implementation - As you implement each fix, update the corresponding test by removing the
skipstatement - Run tests frequently during development to catch regressions early
- Tests use mock data and temporary directories to avoid affecting real OUD instances
- BATS Documentation
- Bash Best Practices
- ShellCheck - Static analysis for bash scripts
- Google Shell Style Guide
Last Updated: 2025-12-12 Status: Phase 1 & 2 - Infrastructure Complete, Implementation Not Started