Skip to content

Conversation

@webda2l
Copy link
Contributor

@webda2l webda2l commented Sep 8, 2025

Q A
Branch? 7.4
Bug fix? no
New feature? yes
Deprecations? no
License MIT

The IsCsrfTokenValid attribute currently only reads the token value from the request payload, which is somewhat restrictive. This PR add the ability to choose more sources.

@stof
Copy link
Member

stof commented Sep 8, 2025

Reading it from cookies is a bad idea, as the security of the CSRF protection has never been evaluated for such usage, which is a totally different behavior (a cookie could be submitted based on a stored value rather than a value submitted as part of the request, which has to be known by the attacker submitting the request)

@nicolas-grekas
Copy link
Member

I'd rather make this explicit using an option on the attribute. Fishing for security values is calling for troubles :)

@webda2l
Copy link
Contributor Author

webda2l commented Sep 8, 2025

I'd rather make this explicit using an option on the attribute. Fishing for security values is calling for troubles :)

A simple improvement could be to allow tokenKey as a Symfony Expression as well that its current string format, to handle more advanced scenarios.

#[IsCsrfTokenValid(
   id: new Expression('"delete-item-" ~ args["post"].getId()'),
   tokenKey: 'token'               // Default behavior by reading request.getPayload
   tokenKey: new Expression('request.query.getString("_token")'),     // Simple
   tokenKey: new Expression('request.getPayload().get("token") ?? request.query.get("_token")'),    // More advanced
)]

But the naming tokenKey is not the best so...
So, it could require a new field value / valueExpr / tokenValue / tokenExpr, but will require an extra check to trigger an error if tokenKey and this new field are both set.

@nicolas-grekas
Copy link
Member

we could use a bitfield - that'd prevent everybody needed this from figuring out the correct expression (there's only a very limited way of reading that token - and we even don't want to open for things like cookies):
#[IsCsrfTokenValid(tokenSource: IsCsrfTokenValid::SOURCE_QUERY | IsCsrfTokenValid::SOURCE_HEADER)]

@webda2l webda2l force-pushed the feature/iscsrftokenvalid-requestquery branch from 43c46e8 to 2119ddc Compare September 9, 2025 12:12
@webda2l webda2l changed the title [Security] Add request query parameters as a source for #[IsCsrfTokenValid] [Security] Add $tokenSource argument to #[IsCsrfTokenValid] Sep 9, 2025
@webda2l webda2l force-pushed the feature/iscsrftokenvalid-requestquery branch 2 times, most recently from b545acb to 0ddd4e6 Compare September 9, 2025 13:32
$sources = [
IsCsrfTokenValid::SOURCE_PAYLOAD => static fn () => $request->getPayload()->get($tokenKey),
IsCsrfTokenValid::SOURCE_QUERY => static fn () => $request->query->get($tokenKey),
IsCsrfTokenValid::SOURCE_HEADER => static fn () => $request->headers->get($tokenKey),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we really expect the header name to be _token like payload fields ?

If the name cannot be common, we cannot really support a bitfield IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can yes, that'd be just a custom header. Ppl that want something else can always do it the procedural way I'd say

@webda2l webda2l force-pushed the feature/iscsrftokenvalid-requestquery branch from 075183a to ec51c23 Compare September 9, 2025 17:33
@webda2l webda2l changed the title [Security] Add $tokenSource argument to #[IsCsrfTokenValid] [Security] Add $tokenSource argument to #[IsCsrfTokenValid] to support reading tokens from the query string or headers Sep 9, 2025
…pport reading tokens from the query string or headers
@nicolas-grekas nicolas-grekas force-pushed the feature/iscsrftokenvalid-requestquery branch from ec51c23 to 3a36435 Compare September 10, 2025 06:22
@nicolas-grekas
Copy link
Member

Thank you @webda2l.

@nicolas-grekas nicolas-grekas merged commit ac219f8 into symfony:7.4 Sep 10, 2025
11 of 12 checks passed
This was referenced Oct 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants