- Affected version
- 2.3.9
Summary
Reproduce
What happens
In CLI context
Stack trace
Suggested fix
Skip the IP assignment when there isn't a real request IP available, e.g.:
XF\Job\ApprovalQueueProcess crashes with InvalidArgumentException: Invalid string IP when the moderator log entry is created from CLI.Reproduce
- Have content (e.g. a post) sitting in the approval queue.
- A moderator approves it through the UI, which enqueues an
ApprovalQueueProcessjob rather than acting inline. - The job is later picked up by the CLI runner (
php cmd.php xf:run-jobs, or the system cron).
What happens
XF\ModeratorLog\AbstractHandler::setupLogEntityActor() sees $actor->user_id == \XF::visitor()->user_id (because ApprovalQueueProcess::run() wraps the action in \XF::asVisitor($asUser, …)) and calls:
Code:
$log->ip_address = Ip::stringToBinary(\XF::app()->request()->getIp());
In CLI context
$_SERVER['REMOTE_ADDR'] is unset, so Request::getIp() returns an empty string and Ip::stringToBinary('') throws.Stack trace
Code:
InvalidArgumentException: Invalid string IP: src/XF/Util/Ip.php:17
#0 src/XF/ModeratorLog/AbstractHandler.php(137): XF\Util\Ip::stringToBinary('')
#1 src/XF/ModeratorLog/AbstractHandler.php(118): XF\ModeratorLog\AbstractHandler->setupLogEntityActor(...)
#2 src/XF/ModeratorLog/AbstractHandler.php(92): XF\ModeratorLog\AbstractHandler->log(...)
#3 src/XF/ModeratorLog/Logger.php(79): XF\ModeratorLog\Logger->logChanges('post', ...)
#4 src/XF/Logger.php(49): XF\Logger->logModeratorChanges('post', ...)
#5 src/XF/Entity/Post.php(626): XF\Entity\Post->_postSave()
#9 src/XF/Service/Post/ApproverService.php(39): XF\Mvc\Entity\Entity->save()
#10 src/XF/ApprovalQueue/PostHandler.php(30): XF\Service\Post\ApproverService->approve()
#11 src/XF/ApprovalQueue/AbstractHandler.php(202): XF\ApprovalQueue\PostHandler->actionApprove(...)
#12 src/XF/Job/ApprovalQueueProcess.php(71): XF\ApprovalQueue\AbstractHandler->performAction('approve', ...)
#13 src/XF.php(914): XF\Job\ApprovalQueueProcess->XF\Job\{closure}()
#14 src/XF/Job/ApprovalQueueProcess.php(57): XF::asVisitor(..., Closure)
#15 src/XF/Job/Manager.php(275): XF\Job\ApprovalQueueProcess->run(8)
…
#18 src/XF/Cli/Command/RunJobs.php(58): XF\Job\Manager->runJobEntry(...)
Suggested fix
Skip the IP assignment when there isn't a real request IP available, e.g.:
Code:
protected function setupLogEntityActor(ModeratorLog $log, User $actor)
{
$log->user_id = $actor->user_id ?? 0;
if ($actor->user_id == \XF::visitor()->user_id)
{
$ip = \XF::app()->request()->getIp();
if ($ip !== '')
{
$log->ip_address = Ip::stringToBinary($ip);
}
}
}
xf_moderator_log.ip_address is already nullable/blob, so leaving it empty for CLI-originated log rows is consistent with other "no request" code paths.