Introduction
Spamfree Email module works on Javascript enabled and disabled browsers preventing email harvesting. The Email address given in content type fields like (body, summary etc,) are converted into corresponding mailto links and provides email obfuscation to protect email addresses from harvesting bots. A javascript array of the original email address is generated and is parsed back to HTML, this way it is shown in Javascript-enabled browser, at the same time for non JS browsers an image of the email address (using Gd library) is generated and displayed. This prevents non-javascript capable bots from harvesting email addresses. Every time the email generated javascript array will change making it difficult for the bots to do any guess work. Spamfree Email does not use any common css class names or ids making it further difficult for the bots to grab the text within that.
Working
After obfuscation, this email address: example.one@example.org
turns into this, but only for bots:
var eWNnEZVIu = new Array('g','@example.or','example.one'); document.getElementById('YvynIpoMZ').innerHTML = eWNnEZVIu[2]+eWNnEZVIu[1]+eWNnEZVIu[0]; document.getElementById('YvynIpoMZ').href = 'mailto:'+eWNnEZVIu[2]+eWNnEZVIu[1]+eWNnEZVIu[0];
Additional feature to handle non JS environment, can be turned off from admin
side.<noscript><img src="path to image" /></noscript>
How its different from others
When I examined other modules I could see that they are wrapping the email address with some specific HTML tags or CSS classes. A bot can simply grab the text within that HTML tag or class and process it to get the email. Also the modules have dependency on jquery or heavy decoding functions such as base 64 decode in javascript. Where as Spamfree email uses only pure javascript and js array for manipulating.
Some similar modules and differences
- Spamspan: Module obfuscates email in a sepcial format for non Js enabled browsers foe eg: example [at] example [dot] com . This can be easily decoded by a bot.
- Graceful Email Obfuscation Filter: This module has a dependancy with Contact module. Also the module uses a sepcial format for links which also is easy for the spambots to grab. eg: contact[at]example[dot]com
- Invisimail: In this module if we need to apply the filter we must select it as a formatter in display. Also it works only in JS environment.
Project url
https://www.drupal.org/project/spamfree_email
Git Command
-
git clone --branch 7.x-1.x https://git.drupal.org/project/spamfree_email.git cd spamfree_email
- Select the field types you need to be processed: admin/config/content/spamfree_email .
- If support for non Javascript browser is enabled, GD library is a must which will usually be installed on
server.
Usage
- Install the module and go to configuration page and select the fields in which
obfuscation to be added. - For selecting the font family, you need to upload the font and click Save first
and then only the font will appear in the font list.
PAReview:
http://pareview.sh/pareview/httpgitdrupalorgsandboxabhiklpm2465593git
Manual reviews of other projects
https://www.drupal.org/node/2443731#comment-9856567
https://www.drupal.org/node/2477289#comment-9866951
https://www.drupal.org/node/2464915#comment-9845417
Comments
Comment #1
markconroy CreditAttribution: markconroy at Annertech commentedHi abhiklpm,
Apologies, this is not a review, but I just wanted to chip in to say this looks like a great module.
I had a quick look through how it all works and I didn't see anything jumping out at me, but since I am on the road at the moment, I don't have the time to download and install it to check it out.
Hopefully it'll get through the application process quite quickly as it genuinely looks like a very interesting piece of work. Well done to you.
Comment #2
PA robot CreditAttribution: PA robot commentedWe are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and put yourself on the high priority list, then we will take a look at your project right away :-)
Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).
I'm a robot and this is an automated message from Project Applications Scraper.
Comment #3
abhiklpm CreditAttribution: abhiklpm commentedComment #4
markconroy CreditAttribution: markconroy at Annertech commentedHi abhiklpm,
Just had a quick look at your manual reviews. I think they are a bit short to qualify. You really need to show that you took the time to install and investigate the modules and offer a full review of them. A single comment is generally not enough.
There is documentation about what these manual reviews should entail. Make sure you have a read of it, it's quite helpful.
Comment #5
abhiklpm CreditAttribution: abhiklpm commentedComment #6
abhiklpm CreditAttribution: abhiklpm commentedComment #7
abhiklpm CreditAttribution: abhiklpm commentedComment #8
balis_m CreditAttribution: balis_m commentedThe module works great.
Automated Review
Git errors:
The last commit message is just one word, you should provide a meaningful short summary what you changed. See https://www.drupal.org/node/52287
Manual Review
Individual user account
Yes
No duplication
Yes
Master Branch
Yes
Licensing
Yes
3rd party assets/code
Yes
README.txt/README.md
No (README template)
Code long/complex enough for review
Yes
Secure code
Yes
Comment #9
Ayesh CreditAttribution: Ayesh commentedNice module!
There was a similar module that promised to do the very same, but unfortunately it had some security issues (which apparently reported by myself), and there were no fixes for that.
I installed the module, and works as it should.
- Module only obfuscates the first item in a multi-field array. Adding a foreach block to handle all field items should do the job (.module:48 of 684fd8f3)
- When the no-js fallback is enabled, it become pretty obvious and easy to extract all the email addresses easily.
This fetches the file, and the noscript tag contains the raw email address.
I can imagine two methods to solve this (other than dropping the 2% of js-disabled browsers).
- Pass the entity type, entity ID, field name, field item index and the occurrence position as URL arguments, and get the module to convert that value to the email-image.
Note that unless you check entity access, this can be a severe security issue. See SA-CONTRIB-2013-011.
- Use symmetric encryption to encrypt the email, and get server to decrypt and send the image back. In this case make sure you add some sort of DoS protection. This can be as simple as a drupal_get/validate_token call. Session independent tokens, the better. See SA-CORE-2013-002.
Comment #10
abhiklpm CreditAttribution: abhiklpm commentedHi @Ayesh,
Thanks for the review, below is my feedback on your suggestions:
- Module only obfuscates the first item in a multi-field array. Adding a foreach block to handle all field items should do the job (.module:48 of 684fd8f3) Done
- When the no-js fallback is enabled, it become pretty obvious and easy to extract all the email addresses easily.Done - I have encrypted the email and decrypted while image generation. Also added token to prevent DOS attack.
Comment #11
Ayesh CreditAttribution: Ayesh commentedI'm sorry but this introduces a security issue with the encryption key and anti-DoS security key.
1. The encryption key is not unique across the installed sites. The key is always
!^@#&*$%
, so an attacker could easily use this to decrypt the email address back.Solution: You can use site-specific keys to encrypt email addresses. Since you do not store them in the site,
drupal_get_private_key()
can be used as the symmetric key.Also, I would add some function_exists() calls to make sure this function exists, because in some server configurations, mcrypt module is not available. We better add this in a
hook_requirements
hook too I think.2. The drupal_get_token() call uses the string literal "date". While this token is unique across sites and sessions in a single site, same token is used for a site across a single session, which bots can be programmed to parse ones and requires a plethora of images, which will bypass the protection.
Consider passing the encrypted string to generate the token. This can harden the protection. If you check the usages of drupal_get_token in other modules and core, you will see the main variable is passed as the argument.
I'm sorry I had to add the security tag to this. Please do not remove this tag because it helps others to learn from these applications. This module will be very helpful to many people (myself included), so I will continue to keep this application live and give any help if needed.
Comment #12
abhiklpm CreditAttribution: abhiklpm commentedHi @Ayesh,
I have worked on your suggestion,
Please check and let me know your feedback.
Comment #13
Ayesh CreditAttribution: Ayesh commentedAwesome work!
No blockers I could find in a manual review, but a few performance improvements.
In both encryot and decrypts, module calls the (de/en)crypt functions multiple types. You can use the $_GET variable again and again without encrypting it again.
Also, you won't need to define the encryption key in a PHP constant. It's always unique even if you call it multiple times.
This module looks pretty much RTBC otherwise to me, but let's wait for a few others to review this. As always, taking the Review Bonus will speed up the process.
Comment #14
Ayesh CreditAttribution: Ayesh commentedI was not aware of this, but there seems to be a module Invisimail, which does the same more or less. Since that module already has 14k installs, I think people will want the noscript improvements to that module.
I'm not a git admin here, but I think you can still get vetted status on drupal.org and become a maintainer of that module (The project page says it's looking for new co-maintainers).
Comment #15
abhiklpm CreditAttribution: abhiklpm commentedHi @Ayesh,
I have removed the definition for private key, and also removed the redundant variables.
Regarding invisimail module even though the purpose is same, it works a bit differently like using formatters. This module can be used in any fields as per the backend configuration, so I think its better to go as a separate module.
Comment #16
abhiklpm CreditAttribution: abhiklpm commentedComment #17
abhiklpm CreditAttribution: abhiklpm commentedComment #18
Ayesh CreditAttribution: Ayesh commentedSorry for not being able to catch this up.
I would remove the
define("SPAMFREE_EMAIL_ENCRYPTION_KEY", drupal_get_private_key());
and use thedrupal_get_private_key()
directly because we have one less constant to keep in memory and thedrupal_get_private_key()
is cached anyways.Otherwise looks good to me.
Consider taking a review bonus (make three manual reviews of other projects and link to them in your application, and add the
PAReview: review bonus
tag).I'm not a git admin here. Just volunteering to maintain the queue. If we can get a few others to review this projects, this can be marked "Reviewed and tested by community". Klausi and other git admins will take a final look at this and then process this. Good luck!
Comment #19
Vikas.Kumar CreditAttribution: Vikas.Kumar commentedManual Review
Please compare with Invisimail
Comment #20
abhiklpm CreditAttribution: abhiklpm commentedInvisimail works using formatters and also it doesn't handle non Javascript environment.
While this module can be used in any fields as per the backend configuration, so I think it should be a separate module.
Comment #21
abhiklpm CreditAttribution: abhiklpm commentedhttps://www.drupal.org/node/2443731#comment-9856567
https://www.drupal.org/node/2477289#comment-9866951
https://www.drupal.org/node/2464915#comment-9845417
https://www.drupal.org/node/2481473#comment-9893781
Comment #22
klausiAnd please don't remove the security tag, we keep that for statistics and to show examples of security problems.
Comment #23
abhiklpm CreditAttribution: abhiklpm commentedComment #24
klausiRemoving review links that are not manual reviews.
Comment #25
klausimanual review:
The licensing issue is a blocker right now. Removing review bonus tag, you can add it again if you have done another 3 reviews of other projects.
Comment #26
abhiklpm CreditAttribution: abhiklpm commentedComment #27
PA robot CreditAttribution: PA robot commentedClosing due to lack of activity. If you are still working on this application, you should fix all known problems and then set the status to "Needs review". (See also the project application workflow).
I'm a robot and this is an automated message from Project Applications Scraper.
Comment #28
abhiklpm CreditAttribution: abhiklpm commentedFixed the below issues:
Reviewed projects:
https://www.drupal.org/node/2682243#comment-10948647
https://www.drupal.org/node/1054276#comment-10109848
https://www.drupal.org/node/2533528#comment-10121532
https://www.drupal.org/node/1044090#comment-10140872
Comment #29
klausiReview of the 7.x-1.x branch (commit d262e85):
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. You have to get a review bonus to get a review from me.
manual review:
Otherwise looks good to me.
Assigning to naveenvalecha as he might have time to take a final look at this.
Comment #30
abhiklpm CreditAttribution: abhiklpm commentedHi @klausi,
Fixed the Open page callback warning
Comment #31
Ayesh CreditAttribution: Ayesh commentedI think Klausi meant that using the session makes Drupal not to cache the pages, which is actually a big deal.
drupal_get_token/drupal_valid_token functions take the user session because the variables used to generate the token are known. A path, or something else that the user can figure out. Since each user has different sessions, this makes sure the user who generated the token is same as the user who validates it.
I apologize that it's I who mentioned this in first place.
But again, session independent tokens, the better.
I'm currently on mobile and was checking my tracker on the road. I will clone your repo again and write another review on latest status.
Comment #32
klausino objection for a week, so ...
Thanks for your contribution, Abhilash!
I updated your account so you can promote this to a full project and also create new projects as either a sandbox or a "full" project.
Here are some recommended readings to help with excellent maintainership:
You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and stay involved!
Thanks, 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.
Thanks to the dedicated reviewer(s) as well.
Comment #33
abhiklpm CreditAttribution: abhiklpm commentedThankyou all for approving this module.