Documentation
¶
Overview ¶
Package security provides comprehensive security testing and validation for Hitch's safety mechanisms.
Overview ¶
This package doesn't provide production security features but rather contains integration tests that validate the security properties of Hitch's architecture. It ensures that all safety mechanisms (input sanitization, temp branch testing, lock management, panic recovery) work together correctly.
Purpose ¶
The security package serves as:
- Integration test suite for security-critical components
- Validation of defense-in-depth architecture
- Regression tests for security-related bugs
- Documentation of security properties through tests
Security Properties Tested ¶
The package validates these security properties:
Input Sanitization:
- Branch names with command injection attempts
- Environment names with path traversal
- User input with special characters
- Malformed Git references
State Protection:
- Repository state is never corrupted
- Failed operations leave no artifacts
- Temp branches are always cleaned up
- Original branches are preserved
Concurrency Control:
- Locks prevent race conditions
- Multiple users can't modify same environment
- Lock recovery works correctly
- Stale locks are detected
Panic Safety:
- Panics don't corrupt repository
- Locks are released on panic
- State is restored after crashes
- Error context is preserved
Test Structure ¶
Tests use a comprehensive test harness:
type SecurityIntegrationTest struct {
testRepo *testutil.TestRepo
sanitizer *git.InputSanitizer
validator *git.RepositoryValidator
tempTester *safety.TempBranchTester
meta *metadata.Metadata
lockManager *metadata.LockManager
panicRecovery *metadata.PanicRecovery
}
This provides all components needed to test security properties.
Integration Test Scenarios ¶
The package includes tests for:
Command Injection Prevention:
func TestInputSanitization_CommandInjection(t *testing.T) {
maliciousBranches := []string{
"feature/test; rm -rf /",
"feature/test`whoami`",
"feature/test$(cat /etc/passwd)",
}
// Verify all are blocked
}
Path Traversal Prevention:
func TestInputSanitization_PathTraversal(t *testing.T) {
maliciousEnvs := []string{
"../../../etc/passwd",
"..\\..\\windows\\system32",
}
// Verify all are sanitized
}
Concurrent Modification Prevention:
func TestLockManager_RaceCondition(t *testing.T) {
// Two users try to modify same environment
// Verify only one succeeds
}
State Corruption Prevention:
func TestPanicRecovery_StateRestoration(t *testing.T) {
// Operation panics mid-execution
// Verify repository state is restored
}
Defense in Depth ¶
Tests validate multiple layers of defense:
Layer 1: Input Validation
- git.InputSanitizer blocks malicious input
- Early rejection before any operations
Layer 2: Repository Validation
- git.RepositoryValidator checks repo health
- Ensures consistent starting state
Layer 3: Safe Testing
- safety.TempBranchTester tests in isolation
- No changes to actual branches
Layer 4: Lock Protection
- metadata.LockManager prevents races
- Atomic metadata updates
Layer 5: Panic Recovery
- metadata.PanicRecovery handles crashes
- Cleanup and restoration guaranteed
Example Integration Test ¶
func TestFullSecurityStack(t *testing.T) {
sit := NewSecurityIntegrationTest(t)
defer sit.Cleanup()
// Test input sanitization
branchName := "feature/test; rm -rf /"
if sit.sanitizer.IsValidBranchName(branchName) {
t.Error("Malicious branch name should be rejected")
}
// Test safe merge
validBranch := "feature/safe"
sit.CreateBranch(validBranch)
config := safety.TestConfig{
SourceBranch: validBranch,
TargetBranch: "dev",
BaseBranch: "main",
Operation: "promote",
}
result := sit.tempTester.TestMerge(context.Background(), config)
if !result.Success {
t.Errorf("Safe merge should succeed: %v", result.Error)
}
// Verify no temp branches left behind
if sit.testRepo.BranchExists("main-hitch-promote-test") {
t.Error("Temp branch should be cleaned up")
}
}
Security Best Practices ¶
The tests validate that Hitch follows security best practices:
- Validate all input before use
- Use parameterized git commands (go-git library)
- Never execute shell commands with user input
- Test operations before applying them
- Use atomic commits for metadata updates
- Implement proper cleanup in defer statements
- Handle panics gracefully
- Provide clear security error messages
Threat Model ¶
Tests are designed around this threat model:
Threats:
- Malicious branch names (command injection)
- Path traversal in environment names
- Race conditions between users
- Crashes leaving corrupt state
- Failed operations leaving artifacts
Mitigations:
- Input sanitization (git.InputSanitizer)
- Safe operations (safety.TempBranchTester)
- Concurrency control (metadata.LockManager)
- Crash recovery (metadata.PanicRecovery)
- Cleanup guarantees (defer statements)
Testing Approach ¶
Security tests use:
- Isolation (enforced globally)
- Fresh repositories for each test
- Real git operations (not mocks)
- Comprehensive cleanup
- Attack pattern validation
Coverage Areas ¶
Security integration tests cover:
Input Vectors:
- Branch names
- Environment names
- User emails
- Commit messages
- File paths
Operation Safety:
- Promote operations
- Demote operations
- Rebuild operations
- Release operations
- Cleanup operations
Failure Scenarios:
- Merge conflicts
- Lock conflicts
- Panics during operations
- Network failures
- Disk full scenarios
Dependencies ¶
The package depends on all security-critical components:
- internal/git: Input sanitization and validation
- internal/safety: Safe operation testing
- internal/metadata: Lock management and panic recovery
- internal/testutil: Isolated test repositories
Running Security Tests ¶
Run tests:
go test -v ./internal/security # or use just command just test
This ensures tests run in isolated environments with:
- Clean git environment
- No interference from host system
- Reproducible results
- True integration testing
Continuous Security Testing ¶
In CI/CD pipelines:
# Run security tests on every commit go test -v ./internal/security # Run with race detector go test -race -v ./internal/security # Generate coverage report go test -coverprofile=security-coverage.out ./internal/security
Security Regression Prevention ¶
When fixing security issues:
- Add failing test demonstrating the issue
- Implement the fix
- Verify test now passes
- Test remains as regression prevention
Example:
// TestCVE_2024_12345_PathTraversal prevents regression of path traversal fix
func TestCVE_2024_12345_PathTraversal(t *testing.T) {
sit := NewSecurityIntegrationTest(t)
defer sit.Cleanup()
// Attack that was possible before fix
maliciousEnv := "../../etc/passwd"
// Verify attack is now blocked
sanitized := sit.sanitizer.SanitizeEnvironmentName(maliciousEnv)
if strings.Contains(sanitized, "..") {
t.Error("Path traversal should be sanitized")
}
}
Future Enhancements ¶
Potential additions to security testing:
- Fuzzing of input sanitization
- Property-based testing of safety mechanisms
- Performance testing under load
- Chaos engineering for failure scenarios
- Security benchmarking
Related Documentation ¶
See also:
- internal/git: Input sanitization implementation
- internal/safety: Safe operation implementation
- internal/metadata: Lock management implementation
- SECURITY.md: Security policy and reporting
Index ¶
- type SecurityValidator
- func (sv *SecurityValidator) CheckForCommandInjection(input string) bool
- func (sv *SecurityValidator) CheckForPathTraversal(input string) bool
- func (sv *SecurityValidator) SanitizeInput(input string) string
- func (sv *SecurityValidator) ValidateBranchName(branchName string) ValidationResult
- func (sv *SecurityValidator) ValidateCommitMessage(message string) ValidationResult
- func (sv *SecurityValidator) ValidateEnvironmentName(envName string) ValidationResult
- func (sv *SecurityValidator) ValidateUserEmail(email string) ValidationResult
- type ValidationResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type SecurityValidator ¶
type SecurityValidator struct{}
SecurityValidator provides input validation and security checks
func NewSecurityValidator ¶
func NewSecurityValidator() *SecurityValidator
NewSecurityValidator creates a new security validator
func (*SecurityValidator) CheckForCommandInjection ¶
func (sv *SecurityValidator) CheckForCommandInjection(input string) bool
CheckForCommandInjection checks for basic command injection attempts relevant to Hitch
func (*SecurityValidator) CheckForPathTraversal ¶
func (sv *SecurityValidator) CheckForPathTraversal(input string) bool
CheckForPathTraversal checks for path traversal attempts
func (*SecurityValidator) SanitizeInput ¶
func (sv *SecurityValidator) SanitizeInput(input string) string
SanitizeInput performs basic sanitization on user input for Hitch-specific operations
func (*SecurityValidator) ValidateBranchName ¶
func (sv *SecurityValidator) ValidateBranchName(branchName string) ValidationResult
ValidateBranchName validates a branch name for basic Hitch-specific security issues
func (*SecurityValidator) ValidateCommitMessage ¶
func (sv *SecurityValidator) ValidateCommitMessage(message string) ValidationResult
ValidateCommitMessage validates a commit message for basic Hitch-specific security issues
func (*SecurityValidator) ValidateEnvironmentName ¶
func (sv *SecurityValidator) ValidateEnvironmentName(envName string) ValidationResult
ValidateEnvironmentName validates an environment name for basic Hitch-specific security issues
func (*SecurityValidator) ValidateUserEmail ¶
func (sv *SecurityValidator) ValidateUserEmail(email string) ValidationResult
ValidateUserEmail validates a user email for basic Hitch-specific security issues
type ValidationResult ¶
ValidationResult contains the result of a security validation