MCPcopy Create free account
hub / github.com/ajitpratap0/GoSQLX / Validate

Method Validate

cmd/gosqlx/internal/validate/security.go:183–248  ·  view source on GitHub ↗

Validate performs comprehensive security checks on a file path. This is the core validation method that performs all security checks in the correct order to prevent TOCTOU attacks and other vulnerabilities. Validation sequence: 1. Path traversal check on original path 2. Symlink resolution to real

(path string)

Source from the content-addressed store, hash-verified

181//
182// Validate performs comprehensive security checks on a file path
183func (v *SecurityValidator) Validate(path string) error {
184 // 1. Check for path traversal attempts BEFORE resolving symlinks
185 // This is critical - we must check the original path for ".." sequences
186 // before they get normalized away by EvalSymlinks
187 if err := v.checkPathTraversal(path); err != nil {
188 return err
189 }
190
191 // 2. Resolve symlinks and get real path
192 realPath, err := filepath.EvalSymlinks(path)
193 if err != nil {
194 // Check if it's a symlink error vs file not found
195 if _, statErr := os.Lstat(path); statErr == nil {
196 // File exists but symlink resolution failed
197 return fmt.Errorf("invalid file path (broken symlink): %w", err)
198 }
199 return fmt.Errorf("invalid file path: %w", err)
200 }
201
202 // 3. Check if symlink points to different location (potential security issue)
203 if !v.AllowSymlinks {
204 // Use Lstat to detect symlinks without following them
205 linkInfo, err := os.Lstat(path)
206 if err != nil {
207 // If Lstat fails, continue with regular validation
208 // The file might not exist or we don't have permissions
209 } else if linkInfo.Mode()&os.ModeSymlink != 0 {
210 // This is an actual symlink (not just path normalization)
211 return fmt.Errorf("symlinks are not allowed for security reasons: %s -> %s", path, realPath)
212 }
213 }
214
215 // 4. Get file info
216 info, err := os.Stat(realPath)
217 if err != nil {
218 return fmt.Errorf("cannot access file: %w", err)
219 }
220
221 // 5. Check it's a regular file (not directory, device, socket, etc.)
222 if !info.Mode().IsRegular() {
223 return fmt.Errorf("not a regular file: %s (mode: %s)", path, info.Mode())
224 }
225
226 // 6. Check file size
227 if info.Size() > v.MaxFileSize {
228 return fmt.Errorf("file too large: %d bytes (max %d bytes)", info.Size(), v.MaxFileSize)
229 }
230
231 // 7. Validate file extension
232 if err := v.validateExtension(realPath); err != nil {
233 return err
234 }
235
236 // 8. Test read permissions
237 // G304: realPath is fully validated above via EvalSymlinks and security checks
238 file, err := os.Open(realPath) // #nosec G304
239 if err != nil {
240 return fmt.Errorf("cannot open file: %w", err)

Calls 5

checkPathTraversalMethod · 0.95
validateExtensionMethod · 0.95
OpenMethod · 0.80
ErrorfMethod · 0.65
CloseMethod · 0.45