Skip to content
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

cli detection is fallible #51

Open
lynxlynxlynx opened this issue Sep 16, 2019 · 3 comments
Open

cli detection is fallible #51

lynxlynxlynx opened this issue Sep 16, 2019 · 3 comments

Comments

@lynxlynxlynx
Copy link
Contributor

lynxlynxlynx commented Sep 16, 2019

cv does the drupal8 way of detecting cli mode:

cv/bin/cv

Line 4 in 14fe9da

if (PHP_SAPI !== 'cli') {

However this fails if it's php-cgi executing the code, since that will always return cgi-fcgi. I made #50, so it at least be obvious. See note in the docs comment. There are about five other instances of this check throughout the code.

Please either expand the detection or add a flag to force ignore it. People have been hacking around it for years: https://civicrm.stackexchange.com/questions/4723/how-do-i-import-contacts-through-the-command-line/4724#4724

In my case it was enough to call php with an absolute path, not let the shell resolve it. So perhaps just further enhancing the error message is enough.

@totten
Copy link
Member

totten commented Sep 17, 2019

This is an interesting situation; thanks for reporting.

I think it's a good point to be cautious about depending on the SAPI. However, that contrib comment on php.net feels sketchy:

  1. It doesn't give a concrete alternative for asserting that you're on CLI. (There's a hand-wavy reference to inspecting $_SERVER and $_ENV... but I don't have a valid use-case/environment to inspect. Moreover, I know that $_ENV is unreliable in some common php.ini configurations.) If there's a better way to detect CLI, I'd like to see it.

  2. It doesn't give a use-case/reason for running CLI commands via CGI SAPI.

I'm particularly struggling to see the use-case/reason/steps-to-reproduce. The whole point of the Common Gateway Interface is to define a gateway between an HTTP daemon and some worker process. The basic model is: pass in an HTTP request; send back an HTTP response.

Consider these example commands:

cv api contact.get > my-contacts.json

cv api contact.get --out=csv > my-contacts.csv

If you run on CLI SAPI, the output is a JSON or CSV document. When I manually ran a script on CGI SAPI, the output was an HTTP response, including headers. You'd have to unpack it to get the desired content.

Additionally, cv's Bootstrap.php (or CmsBootstrap.php) inspects the inputs to decide how to boot. If you simply swap the CLI SAPI with the CGI SAPI, then it starts to look like an HTTP request, but you're probably not providing all the inputs (env-vars and headers) defined by the CGI spec. With a munged HTTP request, it won't boot correctly.

tldr: php-cgi is not a drop-replacement for php-cli. For CLI commands, use php-cli.

The idea of an override is interesting. Maybe the above is just my lack of imagine.

IMHO, it's pretty important (from security POV) to ensure that HTTP users are not allowed to invoke CLI commands. So an override should be a strong representation from the local admin that they really know what they're doing.

For example, maybe this:

$isCli = (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg');
if (!$isCli && file_exists('/etc/cv.json')) { 
  $_cv_json = json_decode(file_get_contents('/etc/cv.json'));
  if (isset($_cv_json['allow_sapi']) && in_array(PHP_SAPI, $_cv_json['allow_sapi']) {
    $isCli = TRUE;
  }
}
if (!$isCli) error(...);

@lynxlynxlynx
Copy link
Contributor Author

In the meanwhile I updated the sysadmin docs with a note about the/a workaround.
I agree on the security aspect, someone may still install it in the web accessible paths regardless any warnings. But /etc wouldn't work for shared hosting, so I suggest checking also ~/cv.json.

@mattwire
Copy link

mattwire commented Nov 1, 2019

Just adding a note here, that the security aspect is important, so is using the same PHP version as the site - for example using cv to run CiviCRM cron with a different PHP version can cause/trigger issues that would not happen when run via web etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants