fix: CSRF origin matching should be case-insensitive (#89127)
## Summary
This PR fixes ~two~ one bug~s~ in the `isCsrfOriginAllowed` function used for
Server Actions CSRF protection:
1. **Case sensitivity bug**: Domain matching was case-sensitive, but DNS
names are case-insensitive per [RFC
1035](https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.3). This
caused legitimate requests to fail CSRF checks when the Origin header
contained uppercase characters.
2. ~**Trailing dot bug**: FQDNs with trailing dots (e.g.,
`example.com.`) weren't matched. The trailing dot is valid DNS notation
representing the root zone.~ Edit: Reverted, see comments on PR
## The Problem
Before this fix:
```javascript
isCsrfOriginAllowed('sub.VERCEL.com', ['*.vercel.com']) // false ❌
isCsrfOriginAllowed('sub.vercel.com.', ['*.vercel.com']) // false ❌
```
Both of these should return `true` because:
- DNS is case-insensitive (RFC 1035 §2.3.3)
- Trailing dots are valid FQDN notation
## The Fix
Normalize both domain and pattern before comparison:
- Convert to lowercase
- Strip trailing dots
## Testing
Added new test cases for:
- Case-insensitive matching (various case combinations)
- Trailing dot handling (in both domain and pattern)
All existing tests continue to pass.
## Related
- This affects users who configure `serverActions.allowedOrigins` in
`next.config.js`
- The bug could cause legitimate Server Action requests to be rejected
with CSRF errors if the browser sends an Origin header with different
casing than the configured pattern