Static Application Security Testing (SAST)

Static Application Security Testing (SAST)

SAST analyzes source code to identify security vulnerabilities without executing the application.

Automated SAST Implementation:

// iOS - Custom SAST scanner
import Foundation

class StaticSecurityAnalyzer {
    
    struct SecurityIssue {
        let severity: Severity
        let category: String
        let description: String
        let file: String
        let line: Int
        let recommendation: String
        
        enum Severity {
            case critical, high, medium, low, info
        }
    }
    
    // Analyze Swift source files
    func analyzeSourceCode(at path: String) -> [SecurityIssue] {
        var issues: [SecurityIssue] = []
        
        let fileManager = FileManager.default
        guard let enumerator = fileManager.enumerator(atPath: path) else { return issues }
        
        while let file = enumerator.nextObject() as? String {
            if file.hasSuffix(".swift") {
                let filePath = (path as NSString).appendingPathComponent(file)
                issues.append(contentsOf: analyzeSwiftFile(at: filePath))
            }
        }
        
        return issues
    }
    
    private func analyzeSwiftFile(at path: String) -> [SecurityIssue] {
        var issues: [SecurityIssue] = []
        
        guard let content = try? String(contentsOfFile: path) else { return issues }
        let lines = content.components(separatedBy: .newlines)
        
        for (index, line) in lines.enumerated() {
            // Check for hardcoded secrets
            if let issue = checkForHardcodedSecrets(line: line, lineNumber: index + 1, file: path) {
                issues.append(issue)
            }
            
            // Check for insecure random number generation
            if let issue = checkForInsecureRandom(line: line, lineNumber: index + 1, file: path) {
                issues.append(issue)
            }
            
            // Check for disabled certificate validation
            if let issue = checkForDisabledCertValidation(line: line, lineNumber: index + 1, file: path) {
                issues.append(issue)
            }
            
            // Check for insecure data storage
            if let issue = checkForInsecureStorage(line: line, lineNumber: index + 1, file: path) {
                issues.append(issue)
            }
        }
        
        return issues
    }
    
    private func checkForHardcodedSecrets(line: String, lineNumber: Int, file: String) -> SecurityIssue? {
        let patterns = [
            ("password\\s*=\\s*\"[^\"]+\"", "Hardcoded password detected"),
            ("apiKey\\s*=\\s*\"[^\"]+\"", "Hardcoded API key detected"),
            ("secret\\s*=\\s*\"[^\"]+\"", "Hardcoded secret detected"),
            ("token\\s*=\\s*\"[^\"]+\"", "Hardcoded token detected")
        ]
        
        for (pattern, message) in patterns {
            if let _ = line.range(of: pattern, options: .regularExpression) {
                return SecurityIssue(
                    severity: .critical,
                    category: "Hardcoded Secrets",
                    description: message,
                    file: file,
                    line: lineNumber,
                    recommendation: "Use Keychain or environment variables for sensitive data"
                )
            }
        }
        
        return nil
    }
    
    private func checkForInsecureRandom(line: String, lineNumber: Int, file: String) -> SecurityIssue? {
        if line.contains("arc4random()") || line.contains("rand()") {
            return SecurityIssue(
                severity: .medium,
                category: "Weak Cryptography",
                description: "Insecure random number generation",
                file: file,
                line: lineNumber,
                recommendation: "Use SecRandomCopyBytes for cryptographic randomness"
            )
        }
        
        return nil
    }
}