Spam Master was born out of need to protect websites against constant malicious spam registrations, comments and contacts that affect the majority of websites. The module uses RBL technology (real time block lists), it provides a service software Saas.

Project link

https://www.drupal.org/project/spammaster

Git instructions

git clone --branch 8.x-1.x https://git.drupalcode.org/project/spammaster

PAReview checklist

https://pareview.sh/pareview/https-git.drupal.org-project-spammaster

Comments

pedro-alves created an issue. See original summary.

shaktik’s picture

shaktik’s picture

shaktik’s picture

shaktik’s picture

shaktik’s picture

Status: Needs review » Needs work

Please check and fix Call to method get() on an unknown class error below.

Shakti-Kumar:spammaster shakti.kumar$ ../../../../vendor/bin/drupal-check -ad .
20/20 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

------ -----------------------------------------------------------------------------------------------------
Line src/Controller/SpamMasterCleanUpController.php
------ -----------------------------------------------------------------------------------------------------
28 Property Drupal\spammaster\Controller\SpamMasterCleanUpController::$loggerFactory has unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface as its type.
42 Property Drupal\spammaster\Controller\SpamMasterCleanUpController::$loggerFactory
(Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface) does not accept
Drupal\Core\Logger\LoggerChannelFactoryInterface.

73 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
85 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
96 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
108 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
120 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
132 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
144 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
156 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
168 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
180 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
192 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
204 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
216 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
228 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
240 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
252 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
264 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
276 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
288 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
300 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
310 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
312 Undefined variable: $spammaster_date
337 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
346 Call to method get() on an unknown class
Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.
348 Undefined variable: $time
------ -----------------------------------------------------------------------------------------------------

avpaderno’s picture

Status: Needs work » Needs review

The file correctly contains the use Drupal\Core\Logger\LoggerChannelFactoryInterface; line. It's drupal-check that wrongly assumes the class is Drupal\spammaster\Controller\Drupal\Core\Logger\LoggerChannelFactoryInterface.

avpaderno’s picture

Status: Needs review » Needs work
Issue tags: +PAreview: security
  • What follows is a quick review of the project; it doesn't mean to be complete
  • For every point, I didn't make a complete list of where the code should be fixed, but an example of what is wrong in the code
  • Not all the points are application stoppers; some of them describe changes that would be preferable to make
$output_help .= '<p>' . t('Your Spam Master version is:') . ' <strong>' . $spammaster_version . '</strong></p>';

That line should use placeholders, in the same way the other lines did.

  $spammastercroncontroller = \Drupal::service('spammaster.cron_controller');

  // Implements daily cron.
  if (\Drupal::time()->getRequestTime() - \Drupal::state()->get('spammaster.daily_con') >= 86400) {
    \Drupal::state()->set('spammaster.daily_con', \Drupal::time()->getRequestTime());

    // CronController Call.
    $spammastercroncontroller->spammasterdailycron();

A controller is used to render a page. Used like that, it's a service, which doesn't need to extend the ControllerBase class.

    // Watchdog log.
    \Drupal::logger('spammaster')->notice('Spam Master: daily cron run successfully');

    // Spam Master log.
    $spammaster_date = date('Y-m-d H:i:s');
    \Drupal::database()->insert('spammaster_keys')->fields([
      'date' => $spammaster_date,
      'spamkey' => 'spammaster',
      'spamvalue' => 'Spam Master: daily cron run successfully',
    ])->execute();

Why is the code saving the log messages in a custom database table, when it's already using the system logger?

      $spammaster_subject_title = 'Congratulations!!!';
      $message['from'] = \Drupal::config('system.site')->get('mail');
      $message['subject'] = $spammaster_subject_title;

$message['from'] is already set from Drupal; there is no need for a third-party module to set it to the same value.

        $form['spammaster_page'] = [
          '#type' => 'textfield',
          '#disabled' => TRUE,
          '#default_value' => 'registration',
          '#attributes' => [
            'class' => [
              'spammaster_special_class',
            ],
            'style' => [
              'display: none !important;',
            ],
          ],
        ];

If the form element should not be visible in the form, it should not be a text field. Drupal has a specific type for those values that need to be passed in the form without to be visible nor editable.

  $spammaster_registration_controller->spammasterregistrationcheck($form, $formstate, $spammasterip, $spammasteremail);

The coding standards say how a method should be named. The spam prefix in the method name is also useless.

  $contact_extra_recaptcha = $spammaster_settings_protection->get('spammaster.extra_recaptcha');
  $contact_extra_honeypot = $spammaster_settings_protection->get('spammaster.extra_honeypot');

There are third-party modules for CAPTCHA and honeypot. Is there any reason the users would prefer what this module implements?

      \Drupal::logger('spammaster-recaptcha')->notice('Spam Master: ' . $spammaster_page . ' empty reCaptcha IP: ' . $spammaster_ip);

Instead of concatenating strings, the code should use placeholders.

    $form_state->setErrorByName('spammaster_extra_field_1', 'SPAM MASTER: ' . $spammaster_block_message);

Error messages, like any other message shown to the users, must be translatable.

  $spammaster_admin_email = $site_settings->get('mail');
  $spammaster_ip = $_SERVER['SERVER_ADDR'];
  // If empty ip.
  if (empty($spammaster_ip) || $spammaster_ip == '0') {
    $spammaster_ip = 'I ' . gethostbyname($_SERVER['HTTP_HOST']);
  }
  $spammaster_hostname = gethostbyaddr($_SERVER['SERVER_ADDR']);
  // If empty host.
  if (empty($spammaster_hostname) || $spammaster_hostname == '0') {
    $spammaster_hostname = 'H ' . gethostbyname($_SERVER['HTTP_HOST']);
  }

  // Encode ssl post link for security.
  $spammaster_license_url = 'aHR0cHM6Ly9zcGFtbWFzdGVyLnRlY2hnYXNwLmNvbS93cC1jb250ZW50L3BsdWdpbnMvc3BhbS1tYXN0ZXItYWRtaW5pc3RyYXRvci9pbmNsdWRlcy9saWNlbnNlL2xpY190cmlhbC5waHA=';

  // Call drupal hhtpclient.
  $client = \Drupal::httpClient();
  // Post data.
  $request = $client->post(base64_decode($spammaster_license_url), [
    'form_params' => [
      'spam_license_key' => $spammaster_lic_hash,
      'spam_trial_nounce' => $spammaster_lic_nounce,
      'platform' => $spammaster_platform,
      'platform_version' => $spammaster_platform_version,
      'platform_type' => $spammaster_multisite_joined,
      'spam_master_version' => $spammaster_version,
      'spam_master_type' => $spammaster_type,
      'blog_name' => $spammaster_site_name,
      'blog_address' => $address,
      'blog_email' => $spammaster_admin_email,
      'blog_hostname' => $spammaster_hostname,
      'blog_ip' => $spammaster_ip,
      'spam_master_cron' => $spammaster_cron,
    ],
  ]);

The code is sending the email used from the site to an external site without asking for the permission to do so. There isn't anything in the project page that inform users using the module of this. (GDPR is also about informing the users of which information is used and ask consensus.)

  user_role_change_permissions(RoleInterface::ANONYMOUS_ID, [
    'generate spam master' => TRUE,
  ]);

The module doesn't define that permission.

spammaster.spammasterdailycron:
  path: '/spammaster'
  defaults:
    _controller: '\Drupal\spammaster\Controller\SpamMasterCronController::spammasterdailycron'
    _title: 'Spam Master Cron Controller'
  requirements:
    _permission: 'access content'

spammaster.spammasterlictrialcreation:
  path: '/spammaster'
  defaults:
    _controller: '\Drupal\spammaster\Controller\SpamMasterMailController::spammasterlictrialcreation'
    _title: 'Spam Master Mail Controller'
  requirements:
    _permission: 'access content'

Each route needs to have a different path. Those aren't even controllers, since they don't render anything. The permission used for the routes is also wrong, as it is giving to every user who can access the content on the site the access to information that they should not see, including the license. (This is a information disclosure issue.)

        $spammaster_settings = $this->configFactory->getEditable('spammaster.settings');
        $spammaster_total_block_count = $spammaster_settings->get('spammaster.total_block_count');
        $spammaster_total_block_count_1 = ++$spammaster_total_block_count;

That is not a setting, but a state value. There is an API to store the state of a module.

      if (!empty($spam_key_delete)) {
        $this->connection->query('DELETE FROM {spammaster_keys} WHERE id = :row', [':row' => $spam_key_delete]);
        $this->messenger->addMessage('Saved Spam Master Log deletion.');
        $this->loggerFactory->get('spammaster-log')->notice('Spam Master: log deletion, Id: ' . $spam_key_delete);
        $this->connection->insert('spammaster_keys')->fields([
          'date' => $spammaster_key_date,
          'spamkey' => 'spammaster-log',
          'spamvalue' => 'Spam Master: log deletion, Id: ' . $spam_key_delete,
        ])->execute();
      }

Deleting content from a database table is done with $this->connection->delete().

pedro-alves’s picture

Thank you very much for you time kiamlaluno.

Based on your comments I updated the module to version rc42.

  • Adding privacy policy text and data shared under project page GDPR.
  • Changing default email settings from active to disabled on install.
  • Using placeholders for text.
  • Moving Controllers that are not pages to Services.
  • Removing LoogerFactory to only implement our logs since these are used for statistical data and allow different retention times per log type.
  • Removing mail message from since it's already set from Drupal.
  • Applying naming conventions to functions.
  • Changing spammaster-page form type to hidden.
  • Adding translatable to setErrorByName.
  • Adding permission to "generate spam master" install.
  • Routes and permissions that needed path and were set to access content are no longer used.
  • Permission for the statistics controller changed to administer site configuration.
  • Changing get and set setting to value get and set state.
  • Deleting content from the database using constructor this,connection,delete.

Small explanation regarding using our logs table, recaptcha and honeypot.
These logs table is used in the stats controller and allow user set different retention times per log type (from disabled to infinite).
Honeypot is used by the stats controller but more importantly it's also used by the firewall via buffer. recaptcha is used by the stats controller to provide statistics.

In case of problem I can remove those module functionalities by deleting the log table and calls and the honeypot, repcatcha functions. No problem.

Thanks again.

pedro-alves’s picture

Status: Needs work » Needs review

kiamlaluno,

With the latest version both honeypot and recaptcha are used for text and graph statistical data but more importantly they are both being checked for spam in the local threats db and online via service rbl real time block lists checks.

I'm moving the issue to Needs Review.
Thanks

pedro-alves’s picture

Status: Needs review » Needs work

Just noticed that module version. alert level, cms type, module status, protection number and probability percentage are state values.
Needs work tomorrow.

pedro-alves’s picture

Status: Needs work » Needs review

All state values are now implemented.
Changing status.
Thanks.

rohitrajputsahab’s picture

Status: Needs review » Needs work

22/22 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

[ERROR] Found 49 errors (Drupal check). Please solve these errors also.
------ -----------------------------------------------------------------------
Line spammaster.install
------ -----------------------------------------------------------------------
250 Array has 5 duplicate keys with value 'name' ('name', 'name', 'name',
'name', 'name').
------ -----------------------------------------------------------------------

------ ---------------------------------------------------------------------
Line src/Form/SpamMasterBufferForm.php
------ ---------------------------------------------------------------------
27 Drupal\spammaster\Form\SpamMasterBufferForm::__construct() does not
call parent constructor from Drupal\Core\Form\ConfigFormBase.
------ ---------------------------------------------------------------------

------ -----------------------------------------------------------------------
Line src/Form/SpamMasterLogForm.php
------ -----------------------------------------------------------------------
42 Drupal\spammaster\Form\SpamMasterLogForm::__construct() does not call
parent constructor from Drupal\Core\Form\ConfigFormBase.
------ -----------------------------------------------------------------------

------ -------------------------------------------------------------------------
Line src/Form/SpamMasterProtectionForm.php
------ -------------------------------------------------------------------------
33 Drupal\spammaster\Form\SpamMasterProtectionForm::__construct() does not
call parent constructor from Drupal\Core\Form\ConfigFormBase.
------ -------------------------------------------------------------------------

------ -----------------------------------------------------------------------
Line src/Form/SpamMasterSettingsForm.php
------ -----------------------------------------------------------------------
33 Drupal\spammaster\Form\SpamMasterSettingsForm::__construct() does not
call parent constructor from Drupal\Core\Form\ConfigFormBase.
34 Access to an undefined property
Drupal\spammaster\Form\SpamMasterSettingsForm::$SpamMasterLicService.
162 Access to an undefined property
Drupal\spammaster\Form\SpamMasterSettingsForm::$SpamMasterLicService.
193 Variable $license_status might not be defined.
202 Variable $spammaster_alert_level_label might not be defined.
202 Variable $spammaster_alert_level_text might not be defined.
215 Variable $protection_total_number_text might not be defined.
227 Variable $spammaster_alert_level_p_label might not be defined.
272 Result of function header (void) is used.
------ -----------------------------------------------------------------------

------ -------------------------------------------------------------------------
Line src/Form/SpamMasterWhiteForm.php
------ -------------------------------------------------------------------------
33 Drupal\spammaster\Form\SpamMasterWhiteForm::__construct() does not call
parent constructor from Drupal\Core\Form\ConfigFormBase.
------ -------------------------------------------------------------------------

------ --------------------------------------
Line src/SpamMasterCleanUpService.php
------ --------------------------------------
321 Undefined variable: $spammaster_date
357 Undefined variable: $spammaster_date
------ --------------------------------------

------ -------------------------------------------------------------------------
Line src/SpamMasterCommentService.php
------ -------------------------------------------------------------------------
90 Property Drupal\spammaster\SpamMasterCommentService::$spammasterip has
unknown class Drupal\spammmaster\SpamMasterCommentService as its type.
97 Property Drupal\spammaster\SpamMasterCommentService::$spammasteremail
has unknown class Drupal\spammmaster\SpamMasterCommentService as its
type.
104 Property Drupal\spammaster\SpamMasterCommentService::$spammastercomment
has unknown class Drupal\spammmaster\SpamMasterCommentService as its
type.
------ -------------------------------------------------------------------------

------ -------------------------------------------------------------------------
Line src/SpamMasterContactService.php
------ -------------------------------------------------------------------------
90 Property Drupal\spammaster\SpamMasterContactService::$spammasterip has
unknown class Drupal\spammmaster\spamMasterContactCheck as its type.
97 Property Drupal\spammaster\SpamMasterContactService::$spammasteremail
has unknown class Drupal\spammmaster\spamMasterContactCheck as its
type.
104 Property Drupal\spammaster\SpamMasterContactService::$spammastermessage
has unknown class Drupal\spammmaster\spamMasterContactCheck as its
type.
------ -------------------------------------------------------------------------

------ ---------------------------------------------------------------------
Line src/SpamMasterCronService.php
------ ---------------------------------------------------------------------
64 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterLicService.
65 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterMailService.
66 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterCleanUpService.
96 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterLicService.
100 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterMailService.
130 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterMailService.
138 Access to an undefined property
Drupal\spammaster\SpamMasterCronService::$SpamMasterCleanUpService.
------ ---------------------------------------------------------------------

------ -------------------------------------------------------------------------
Line src/SpamMasterHoneypotService.php
------ -------------------------------------------------------------------------
90 Property Drupal\spammaster\SpamMasterHoneypotService::$spammasterip has
unknown class Drupal\spammmaster\SpamMasterHoneypotService as its type.
97 Property Drupal\spammaster\SpamMasterHoneypotService::$spammasterpage
has unknown class Drupal\spammmaster\SpamMasterHoneypotService as its
type.
104 Property
Drupal\spammaster\SpamMasterHoneypotService::$spammasterextrafield1 has
unknown class Drupal\spammmaster\SpamMasterHoneypotService as its type.
111 Property
Drupal\spammaster\SpamMasterHoneypotService::$spammasterextrafield2 has
unknown class Drupal\spammmaster\SpamMasterHoneypotService as its type.
------ -------------------------------------------------------------------------

------ -----------------------------------------------------------------
Line src/SpamMasterLicService.php
------ -----------------------------------------------------------------
79 Access to an undefined property
Drupal\spammaster\SpamMasterLicService::$SpamMasterMailService.
310 Access to an undefined property
Drupal\spammaster\SpamMasterLicService::$SpamMasterMailService.
------ -----------------------------------------------------------------

------ -----------------------------------------------------------------------
Line src/SpamMasterMailService.php
------ -----------------------------------------------------------------------
420 Variable $spam_master_warning might not be defined.
423 Variable $spam_master_alert_level_deconstructed might not be defined.
429 Variable $spam_master_total_block_count_result might not be defined.
434 Variable $spam_master_warning_signature might not be defined.
628 Variable $spam_master_warning might not be defined.
630 Variable $spam_master_alert_level_deconstructed might not be defined.
640 Variable $spam_master_total_block_count_result might not be defined.
657 Variable $spam_master_warning_signature might not be defined.
834 Variable $spam_master_alert_level_deconstructed might not be defined.
844 Variable $spam_master_total_block_count_result might not be defined.
------ -----------------------------------------------------------------------

------ ------------------------------------------------------------------------
Line src/SpamMasterRecaptchaService.php
------ ------------------------------------------------------------------------
89 Property Drupal\spammaster\SpamMasterRecaptchaService::$spammasterpage
has unknown class Drupal\spammmaster\SpamMasterRecaptchaService as its
type.
96 Property Drupal\spammaster\SpamMasterRecaptchaService::$spammasterip
has unknown class Drupal\spammmaster\SpamMasterRecaptchaService as its
type.
------ ------------------------------------------------------------------------

------ -------------------------------------------------------------------------
Line src/SpamMasterRegistrationService.php
------ -------------------------------------------------------------------------
90 Property Drupal\spammaster\SpamMasterRegistrationService::$spammasterip
has unknown class Drupal\spammmaster\SpamMasterRegistrationService as
its type.
97 Property
Drupal\spammaster\SpamMasterRegistrationService::$spammasteremail has
unknown class Drupal\spammmaster\SpamMasterRegistrationService as its
type.
------ -------------------------------------------------------------------------

pedro-alves’s picture

Status: Needs work » Needs review

Thank you very much.
Fixed and status changed to needs review.

avpaderno’s picture

Assigned: Unassigned » avpaderno
Status: Needs review » Fixed

Thank you for your contribution! I am going to update your account.

These are some recommended readings to help with excellent maintainership:

You can find more contributors chatting on the IRC #drupal-contribute channel. So, come hang out and stay involved.
Thank you, also, for your patience with the review process.
Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

I thank all the dedicated reviewers as well.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

pedro-alves’s picture

Assigned: avpaderno » pedro-alves
pedro-alves’s picture

avpaderno’s picture

Assigned: pedro-alves » avpaderno