Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

77 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

This project is dead. So sorry.

Due to the way that browsers now interact with autocomplete and accessibility features it's not feasible to use this same style of captcha. Keeping this for historical purposes.

Negative Captcha

What is a Negative Captcha?

A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting forms. Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read jumbled characters from an image. But this is bad. It creates usability problems, it hurts conversion rates, and it confuses the shit out of lots of people. Why not do it the other way around? Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.

How does it work?

In a negative captcha form there are two main parts and three ancillary parts. I'll explain them thusly.

Honeypots

Honeypots are form fields which look exactly like real form fields. Bots will see them and fill them out. Humans cannot see them and thusly will not fill them out. They are hidden indirectly- usually by positioning them off to the left of the browser. They look kind of like this:

<divstyle="position: absolute; left: -2000px;"><inputtype="text" name="name" value="" /></div>

Real fields

These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out of. The form name will be hashed so that bots will not know what it is. They look kind of like this:

<inputtype="text" name="685966bd3a1975667b4777cc56188c7e" />

Timestamp

This is a field that is used in the hash key to make the hash different on every GET request, and to prevent replayability.

Spinner

This is a rotating key that is used in the hash method to prevent replayability. I'm not sold on its usefulness.

Secret key

This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field from the hashed field name.

How does Negative Captcha work?

Installation

You can let bundler install Negative Captcha by adding this line to your application’s Gemfile:

gem'negative_captcha'

Controller Hooks

Place this before filter at the top of the controller you are protecting:

before_filter:setup_negative_captcha,:only=>[:new,:create]

In the same controller include the following private method:

privatedefsetup_negative_captcha@captcha=NegativeCaptcha.new(# A secret key entered in environment.rb. 'rake secret' will give you a good one.secret: NEGATIVE_CAPTCHA_SECRET,spinner: request.remote_ip,# Whatever fields are in your formfields: [:name,:email,:body],# If you wish to override the default CSS styles (position: absolute; left: -2000px;) used to position the fields off-screencss: "display: none",params: params)end

Modify your POST action(s) to check for the validity of the negative captcha form

defcreate# Decrypted params are stored in @captcha.values@comment=Comment.new(@captcha.values)# @captcha.valid? will return false if a bot submitted the formif@captcha.valid? && @comment.saveredirect_to@commentelse# @captcha.error will explain what went wrongflash[:notice]=@captcha.errorif@captcha.errorrender:action=>'new'endend

Automated tests

To make all field ids and names predictable for tests, simply add the following line in your spec helper.

NegativeCaptcha.test_mode=true

This will ensure that a field named email will not be referred to by a hash but by test-email instead. A tool like capybara can now bypass this security while still going through the captcha workflow.

Form Example

Modify your form to include the honeypots and other fields. You can probably leave any select, radio, and check box fields alone. The text field/text area helpers should be sufficient.

<% form_tag comments_path do -%><%# The `negative_captcha` call gives us the honeypots, spinners and whatnot %><%= raw negative_captcha(@captcha) %><ulclass="contact_us"><li><%=negative_label_tag(@captcha,:name,'Name:')%><%=negative_text_field_tag(@captcha,:name)%></li><li><%=negative_label_tag(@captcha,:email,'Email:')%><%=negative_text_field_tag(@captcha,:email)%></li><li><%=negative_label_tag(@captcha,:body,'Your Comment:')do%><span>Accepts a block.</span><%end%><%=negative_text_area_tag(@captcha,:body)%></li><li><%=submit_tag%></li></ul><%end-%>

Test and enjoy!

Possible Gotchas and other concerns

  • It is still possible for someone to write a bot to exploit a single site by closely examining the DOM. This means that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution. But if you have a small application, negative captchas will likely be a very, very good solution for you. There are no easy work-arounds to this quite yet. Let me know if you have one.
  • I'm not a genius. It is possible that a bot can figure out the hashed values and determine which forms are which. I don't know how, but I think they might be able to. I welcome people who have thought this out more thoroughly to criticize this method and help me find solutions. I like this idea a lot and want it to succeed.

Credit

The idea of a negative captcha is not mine. It originates (I think) from Damien Katz of CouchDB. I (Erik Peterson) wrote the plugin. Calvin Yu wrote the original class which I refactored quite a bit and made into the gem.

About

A plugin to make the process of creating a negative captcha in Rails much less painful

Resources

Stars

786 stars

Watchers

27 watching

Forks

Releases

Packages

Used by

Contributors

Languages