require "test_helper" class InputValidationTest < ActionDispatch::IntegrationTest # ==================== # SQL INJECTION PREVENTION TESTS # ==================== test "SQL injection is prevented by Rails ORM" do # Rails ActiveRecord prevents SQL injection through parameterized queries # This test verifies the protection is in place # Try SQL injection in email field post signin_path, params: { email_address: "admin' OR '1'='1", password: "password123" } # Should not authenticate with SQL injection assert_response :redirect assert_redirected_to signin_path assert_match(/invalid/i, flash[:alert].to_s) end # ==================== # XSS PREVENTION TESTS # ==================== test "XSS in user input is escaped" do # Create user with XSS payload in name xss_payload = "" user = User.create!(email_address: "xss_test@example.com", password: "password123", name: xss_payload) # Sign in post signin_path, params: { email_address: "xss_test@example.com", password: "password123" } assert_response :redirect # Get a page that displays user name get root_path assert_response :success # The XSS payload should be escaped, not executed # Rails automatically escapes output in ERB templates user.destroy end # ==================== # PARAMETER TAMPERING TESTS # ==================== test "parameter tampering in OAuth authorization is prevented" do user = User.create!(email_address: "oauth_tamper_test@example.com", password: "password123") application = Application.create!( name: "OAuth Test App", slug: "oauth-test-app", app_type: "oidc", redirect_uris: ["http://localhost:4000/callback"].to_json, active: true ) # Sign in post signin_path, params: { email_address: "oauth_tamper_test@example.com", password: "password123" } assert_response :redirect # Try to tamper with OAuth authorization parameters get "/oauth/authorize", params: { client_id: application.client_id, redirect_uri: "http://evil.com/callback", # Tampered redirect URI response_type: "code", scope: "openid profile admin", # Tampered scope to request admin access user_id: 1 # Tampered user ID } # Should reject the tampered redirect URI assert_response :bad_request user.sessions.delete_all user.destroy application.destroy end test "parameter tampering in token request is prevented" do user = User.create!(email_address: "token_tamper_test@example.com", password: "password123") application = Application.create!( name: "Token Tamper Test App", slug: "token-tamper-test", app_type: "oidc", redirect_uris: ["http://localhost:4000/callback"].to_json, active: true ) # Try to tamper with token request parameters post "/oauth/token", params: { grant_type: "authorization_code", code: "fake_code", redirect_uri: "http://localhost:4000/callback", client_id: "tampered_client_id", user_id: 999 # Tampered user ID } # Should reject tampered client_id assert_response :unauthorized user.destroy application.destroy end # ==================== # JSON INPUT VALIDATION TESTS # ==================== test "JSON input validation prevents malicious payloads" do # Try to send malformed JSON post "/oauth/token", params: '{"grant_type":"authorization_code",}'.to_json, headers: { "CONTENT_TYPE" => "application/json" } # Should handle malformed JSON gracefully assert_includes [400, 422], response.status end test "JSON input sanitization prevents injection" do # Try JSON injection attacks post "/oauth/token", params: { grant_type: "authorization_code", code: "test_code", redirect_uri: "http://localhost:4000/callback", nested: { __proto__: "tampered", constructor: { prototype: "tampered" } } }.to_json, headers: { "CONTENT_TYPE" => "application/json" } # Should sanitize or reject prototype pollution attempts # The request should be handled (either accept or reject, not crash) assert response.body.present? end # ==================== # HEADER INJECTION TESTS # ==================== test "HTTP header injection is prevented" do # Try to inject headers via user input malicious_input = "value\r\nX-Injected-Header: malicious" post signin_path, params: { email_address: malicious_input, password: "password123" } # Should sanitize or reject header injection attempts assert_nil response.headers["X-Injected-Header"] end # ==================== # PATH TRAVERSAL TESTS # ==================== test "path traversal is prevented" do # Try to access files outside intended directory malicious_paths = [ "../../../etc/passwd", "..\\..\\..\\windows\\system32\\drivers\\etc\\hosts", "/etc/passwd", "C:\\Windows\\System32\\config\\sam" ] malicious_paths.each do |malicious_path| # Try to access files with path traversal get root_path, params: { file: malicious_path } # Should prevent access to files outside public directory assert_response :redirect, "Should reject path traversal attempt" end end test "null byte injection is prevented" do # Try null byte injection malicious_input = "test\x00@example.com" post signin_path, params: { email_address: malicious_input, password: "password123" } # Should sanitize null bytes assert_response :redirect end end