--- title: Security Best Practices description: Secure your Wails application sidebar: order: 8 --- ## Overview Security is critical for desktop applications. Follow these practices to keep your application secure. ## Input Validation ### Always Validate ```go func (s *UserService) CreateUser(email, password string) (*User, error) { // Validate email if !isValidEmail(email) { return nil, errors.New("invalid email") } // Validate password strength if len(password) < 8 { return nil, errors.New("password too short") } // Sanitise input email = strings.TrimSpace(email) email = html.EscapeString(email) // Continue... } ``` ### Sanitise HTML ```go import "html" func (s *Service) SaveComment(text string) error { // Escape HTML text = html.EscapeString(text) // Validate length if len(text) > 1000 { return errors.New("comment too long") } return s.db.Save(text) } ``` ## Authentication ### Secure Password Storage ```go import "golang.org/x/crypto/bcrypt" func hashPassword(password string) (string, error) { hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) return string(hash), err } func verifyPassword(hash, password string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } ``` ### Session Management ```go type Session struct { UserID int Token string ExpiresAt time.Time } func (a *AuthService) CreateSession(userID int) (*Session, error) { token := generateSecureToken() session := &Session{ UserID: userID, Token: token, ExpiresAt: time.Now().Add(24 * time.Hour), } return session, a.saveSession(session) } ``` ## Data Protection ### Encrypt Sensitive Data ```go import "crypto/aes" import "crypto/cipher" func encrypt(data []byte, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(block) if err != nil { return nil, err } nonce := make([]byte, gcm.NonceSize()) return gcm.Seal(nonce, nonce, data, nil), nil } ``` ### Secure Storage ```go // Use OS keychain for sensitive data import "github.com/zalando/go-keyring" func saveAPIKey(key string) error { return keyring.Set("myapp", "api_key", key) } func getAPIKey() (string, error) { return keyring.Get("myapp", "api_key") } ``` ## Network Security ### Use HTTPS ```go func makeAPICall(url string) (*Response, error) { // Always use HTTPS if !strings.HasPrefix(url, "https://") { return nil, errors.New("only HTTPS allowed") } return http.Get(url) } ``` ### Verify Certificates ```go import "crypto/tls" func secureClient() *http.Client { return &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ MinVersion: tls.VersionTLS12, }, }, } } ``` ## File Operations ### Validate Paths ```go func readFile(path string) ([]byte, error) { // Prevent path traversal if strings.Contains(path, "..") { return nil, errors.New("invalid path") } // Check file exists in allowed directory absPath, err := filepath.Abs(path) if err != nil { return nil, err } if !strings.HasPrefix(absPath, allowedDir) { return nil, errors.New("access denied") } return os.ReadFile(absPath) } ``` ## Rate Limiting ```go type RateLimiter struct { requests map[string][]time.Time mu sync.Mutex limit int window time.Duration } func (r *RateLimiter) Allow(key string) bool { r.mu.Lock() defer r.mu.Unlock() now := time.Now() // Clean old requests var recent []time.Time for _, t := range r.requests[key] { if now.Sub(t) < r.window { recent = append(recent, t) } } if len(recent) >= r.limit { return false } r.requests[key] = append(recent, now) return true } ``` ## Best Practices ### ✅ Do - Validate all input - Use HTTPS for network calls - Encrypt sensitive data - Use secure password hashing - Implement rate limiting - Keep dependencies updated - Log security events - Use OS keychains ### ❌ Don't - Don't trust user input - Don't store passwords in plain text - Don't hardcode secrets - Don't skip certificate verification - Don't expose sensitive data in logs - Don't use weak encryption - Don't ignore security updates ## Security Checklist - [ ] All user input validated - [ ] Passwords hashed with bcrypt - [ ] Sensitive data encrypted - [ ] HTTPS used for all network calls - [ ] Rate limiting implemented - [ ] File paths validated - [ ] Dependencies up to date - [ ] Security logging enabled - [ ] Error messages don't leak info - [ ] Code reviewed for vulnerabilities ## Next Steps - [Architecture](/guides/architecture) - Application architecture patterns - [Best Practices](/features/bindings/best-practices) - Bindings best practices