-
Notifications
You must be signed in to change notification settings - Fork 27.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow passing wildcard domains in serverActions.allowedDomains #59428
Changes from 3 commits
9f3127b
b6964ce
5b4978c
cdffa1b
eb3ff9d
3b2bc3c
ee662fa
b9404a6
c330fb7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { isCsrfOriginAllowed } from './csrf-protection' | ||
|
||
describe('isCsrfOriginAllowed', () => { | ||
it('should return true when allowedOrigins contains originDomain', () => { | ||
expect(isCsrfOriginAllowed('vercel.com', ['vercel.com'])).toBe(true) | ||
expect(isCsrfOriginAllowed('www.vercel.com', ['www.vercel.com'])).toBe(true) | ||
}) | ||
|
||
it('should return true when allowedOrigins contains originDomain with matching regex', () => { | ||
expect(isCsrfOriginAllowed('asdf.vercel.com', ['*.vercel.com'])).toBe(true) | ||
expect(isCsrfOriginAllowed('asdf.jkl.vercel.com', ['*.vercel.com'])).toBe( | ||
true | ||
) | ||
}) | ||
|
||
it('should return false when allowedOrigins contains originDomain with non-matching regex', () => { | ||
expect(isCsrfOriginAllowed('asdf.vercel.com', ['*.vercel.app'])).toBe(false) | ||
}) | ||
|
||
it('should return false when allowedOrigins does not contain originDomain', () => { | ||
expect(isCsrfOriginAllowed('vercel.com', ['nextjs.org'])).toBe(false) | ||
}) | ||
|
||
it('should return false when allowedOrigins is undefined', () => { | ||
expect(isCsrfOriginAllowed('vercel.com', undefined)).toBe(false) | ||
}) | ||
|
||
it('should return false when allowedOrigins is empty', () => { | ||
expect(isCsrfOriginAllowed('vercel.com', [])).toBe(false) | ||
}) | ||
|
||
it('should return false when allowedOrigins is empty string', () => { | ||
expect(isCsrfOriginAllowed('vercel.com', [''])).toBe(false) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { isMatch } from 'next/dist/compiled/micromatch' | ||
|
||
export const isCsrfOriginAllowed = ( | ||
originDomain: string, | ||
allowedOrigins: string[] | undefined | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should default the config to always have an allowedOrigins value, it should just be an empty array if it was omitted by the user. then we can get rid of some of the existential operators There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If that is too invasive a change for this PR then update the function to only accept an array and then move the existence check to the callsite There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existence check in this case is to account for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making the array itself required would only allow for us to remove the optional chaining at the top level and the fallback to false, which I am also happy to do but wanted to point out above ^. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I was suggesting is that wherever the next.config.js is processed and turned into the value passed as We could even go as far as constructing the minimatch regex there so all we have to do is call the match here. I just took a look though and it seems this logic is pretty spread out |
||
): boolean => { | ||
return ( | ||
allowedOrigins?.some( | ||
(allowedOrigin) => | ||
allowedOrigin && | ||
(allowedOrigin === originDomain || isMatch(originDomain, allowedOrigin)) | ||
) ?? false | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment is left over from when it was using regex directly I believe