If an application performs HTTP requests based on user input, it is often desirable to verify that the connection is done to an allowed host. Otherwise the functionality could be abused to request resources on the server or on the same network as the server (SSRF).
Xavier Leune made some pull requests to make this possible in curl. The idea is to hook in a callback that can verify the IP address that curl is going to connect to.
22159: exposes callbacks such as CURLOPT_OPENSOCKETFUNCTION. These are supported by curl, but exposing the socket to userland comes with problems.
23657: introduces CURLOPT_PRECONNECTFUNCTION. This is not supported by curl and is PHP-only, deviating from the normally thin abstraction on top of curl.
The current plan is to expose only CURLOPT_OPENSOCKETFUNCTION with the signature function(string $address, int $port): bool. This is pretty limited compared with what OPENSOCKETFUNCTION can normally do, but at least makes it possible to do SSRF protection.
What do you think? How can we expose SSRF protection to applications that perform curl requests?
Regards,
Sjoerd Langkemper
Hi Sjoerd,
Thanks for reopening this discussion ! I planned to do it in the
coming days too, I'm really eager to see this land in PHP :)
I'm pretty open about the 2 ways to implement it, however the discussion on
23657 about 22159 suggested a socket class bound to curl only, to make
things easier to manage and to remove the dependency to ext/socket.
In my opinion, CURLOPT_OPENSOCKETFUNCTION with the boolean may be a good
idea. I'm not sure there is a real use case to open a wider support in PHP
- this option exists for almost 2 decades and I'm not sure anyone needed it.
For the record I plan to implement the feature in a polyfill extension -
with the same approach that we'll retain for PHP, to offer support in lower
php versions.
There are a lot of small details we can discuss if we retain the
OPENSOCKET_FUNCTION: the signature may be expanded to offer the same level
of data as curl offers
https://curl.se/libcurl/c/CURLOPT_OPENSOCKETFUNCTION.html. This would
make things easier if we want to support a full CurlSocket object later.
There is a first draft here: https://github.com/xavierleune/curl-hardening
My idea was to use this extension as a sandbox before pushing a new
discussion here, I will follow the API we may agree on for PHP 8.7.
I think the approach in the current extension may address the concerns
expressed by Bukka on 22159, while giving room to expand the support later.
Do you think this approach is worth pursuing ?
Thanks,
Xavier
Le jeu. 15 oct. 2026 à 10:48, Sjoerd Langkemper sjoerd-php@linuxonly.nl a
écrit :
If an application performs HTTP requests based on user input, it is often
desirable to verify that the connection is done to an allowed host.
Otherwise the functionality could be abused to request resources on the
server or on the same network as the server (SSRF).Xavier Leune made some pull requests to make this possible in curl. The
idea is to hook in a callback that can verify the IP address that curl is
going to connect to.22159: exposes callbacks such as CURLOPT_OPENSOCKETFUNCTION. These are
supported by curl, but exposing the socket to userland comes with problems.
23657: introduces CURLOPT_PRECONNECTFUNCTION. This is not supported by
curl and is PHP-only, deviating from the normally thin abstraction on top
of curl.The current plan is to expose only CURLOPT_OPENSOCKETFUNCTION with the
signature function(string $address, int $port): bool. This is pretty
limited compared with what OPENSOCKETFUNCTION can normally do, but at
least makes it possible to do SSRF protection.What do you think? How can we expose SSRF protection to applications that
perform curl requests?Regards,
Sjoerd Langkemper
Le jeu. 15 oct. 2026 à 11:10, Xavier Leune xavier.leune+internals@gmail.com
a écrit :
Hi Sjoerd,
Thanks for reopening this discussion ! I planned to do it in the
coming days too, I'm really eager to see this land in PHP :)
I'm pretty open about the 2 ways to implement it, however the discussion
on 23657 about 22159 suggested a socket class bound to curl only, to make
things easier to manage and to remove the dependency to ext/socket.In my opinion, CURLOPT_OPENSOCKETFUNCTION with the boolean may be a good
idea. I'm not sure there is a real use case to open a wider support in PHP
- this option exists for almost 2 decades and I'm not sure anyone needed it.
For the record I plan to implement the feature in a polyfill extension -
with the same approach that we'll retain for PHP, to offer support in lower
php versions.There are a lot of small details we can discuss if we retain the
OPENSOCKET_FUNCTION: the signature may be expanded to offer the same level
of data as curl offers
https://curl.se/libcurl/c/CURLOPT_OPENSOCKETFUNCTION.html. This would
make things easier if we want to support a fullCurlSocketobject later.There is a first draft here: https://github.com/xavierleune/curl-hardening
My idea was to use this extension as a sandbox before pushing a new
discussion here, I will follow the API we may agree on for PHP 8.7.I think the approach in the current extension may address the concerns
expressed by Bukka on 22159, while giving room to expand the support later.Do you think this approach is worth pursuing ?
Thanks,
Xavier
Le jeu. 15 oct. 2026 à 10:48, Sjoerd Langkemper sjoerd-php@linuxonly.nl
a écrit :If an application performs HTTP requests based on user input, it is often
desirable to verify that the connection is done to an allowed host.
Otherwise the functionality could be abused to request resources on the
server or on the same network as the server (SSRF).Xavier Leune made some pull requests to make this possible in curl. The
idea is to hook in a callback that can verify the IP address that curl is
going to connect to.22159: exposes callbacks such as CURLOPT_OPENSOCKETFUNCTION. These are
supported by curl, but exposing the socket to userland comes with problems.
23657: introduces CURLOPT_PRECONNECTFUNCTION. This is not supported by
curl and is PHP-only, deviating from the normally thin abstraction on top
of curl.The current plan is to expose only CURLOPT_OPENSOCKETFUNCTION with the
signature function(string $address, int $port): bool. This is pretty
limited compared with what OPENSOCKETFUNCTION can normally do, but at
least makes it possible to do SSRF protection.What do you think? How can we expose SSRF protection to applications that
perform curl requests?Regards,
Sjoerd Langkemper
Yes, please make this happen! But don't introduce CURLOPT_PRECONNECTFUNCTION
- a CURLOPT_OPENSOCKETFUNCTION bound to the simpler callback that returns a
bool look enough.
I'd use it it Symfony's CurlHttpClient, to replace the blocking call to the
DNS that we have to do today.
It would also be a useful primitive to hack around the blocking DNS we have
to use at the moment - I would build an async DNS resolver out of this :)
Cheers,
Nicolas
Thanks Nicolas for your message, good to see some traction around the idea.
Before working on the next step; i would love to hear from bukka - he had
some concerns about the api so we makes sure it may be extended.
I would appreciate it if we may discuss the specifics here before I move
forward with a new PR and an RFC.
Have a nice day,
Xavier
Le jeu. 22 oct. 2026 à 09:14, Nicolas Grekas nicolas.grekas+php@gmail.com
a écrit :
Le jeu. 15 oct. 2026 à 11:10, Xavier Leune <
xavier.leune+internals@gmail.com> a écrit :Hi Sjoerd,
Thanks for reopening this discussion ! I planned to do it in the
coming days too, I'm really eager to see this land in PHP :)
I'm pretty open about the 2 ways to implement it, however the discussion
on 23657 about 22159 suggested a socket class bound to curl only, to make
things easier to manage and to remove the dependency to ext/socket.In my opinion, CURLOPT_OPENSOCKETFUNCTION with the boolean may be a good
idea. I'm not sure there is a real use case to open a wider support in PHP
- this option exists for almost 2 decades and I'm not sure anyone needed it.
For the record I plan to implement the feature in a polyfill extension -
with the same approach that we'll retain for PHP, to offer support in lower
php versions.There are a lot of small details we can discuss if we retain the
OPENSOCKET_FUNCTION: the signature may be expanded to offer the same level
of data as curl offers
https://curl.se/libcurl/c/CURLOPT_OPENSOCKETFUNCTION.html. This would
make things easier if we want to support a fullCurlSocketobject later.There is a first draft here:
https://github.com/xavierleune/curl-hardening
My idea was to use this extension as a sandbox before pushing a new
discussion here, I will follow the API we may agree on for PHP 8.7.I think the approach in the current extension may address the concerns
expressed by Bukka on 22159, while giving room to expand the support later.Do you think this approach is worth pursuing ?
Thanks,
Xavier
Le jeu. 15 oct. 2026 à 10:48, Sjoerd Langkemper sjoerd-php@linuxonly.nl
a écrit :If an application performs HTTP requests based on user input, it is
often desirable to verify that the connection is done to an allowed host.
Otherwise the functionality could be abused to request resources on the
server or on the same network as the server (SSRF).Xavier Leune made some pull requests to make this possible in curl. The
idea is to hook in a callback that can verify the IP address that curl is
going to connect to.22159: exposes callbacks such as CURLOPT_OPENSOCKETFUNCTION. These are
supported by curl, but exposing the socket to userland comes with problems.
23657: introduces CURLOPT_PRECONNECTFUNCTION. This is not supported by
curl and is PHP-only, deviating from the normally thin abstraction on top
of curl.The current plan is to expose only CURLOPT_OPENSOCKETFUNCTION with the
signature function(string $address, int $port): bool. This is pretty
limited compared with what OPENSOCKETFUNCTION can normally do, but at
least makes it possible to do SSRF protection.What do you think? How can we expose SSRF protection to applications
that perform curl requests?Regards,
Sjoerd Langkemper
Yes, please make this happen! But don't introduce CURLOPT_PRECONNECTFUNCTION
- a CURLOPT_OPENSOCKETFUNCTION bound to the simpler callback that returns
a bool look enough.
I'd use it it Symfony's CurlHttpClient, to replace the blocking call to
the DNS that we have to do today.
It would also be a useful primitive to hack around the blocking DNS we
have to use at the moment - I would build an async DNS resolver out of this
:)Cheers,
Nicolas
Is there any reason we should intentionally make this curl specific?
Meaning, we could design support for making it work for streams as
well, couldn't we? Why make a curl specific feature instead of a
language wide one?