Skip to content

Add honeypot_enabled config option#149

Merged
markets merged 8 commits into
markets:masterfrom
jjb:add-honeypot-enabled-config
Jun 23, 2026
Merged

Add honeypot_enabled config option#149
markets merged 8 commits into
markets:masterfrom
jjb:add-honeypot-enabled-config

Conversation

@jjb

@jjb jjb commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds honeypot_enabled config, mirroring spinner_enabled / timestamp_enabled. Default true — no behavior change. When false, the view helper emits only the spinner field and honeypot_spam? short-circuits to false.

Why

Password managers can autofill the hidden honeypot text input with unrelated saved values. The controller treats the submission as spam and the gem responds with head(200) — a blank white page with no flash. We saw real users blocked this way in production; 30-day audit on our app: 0 honeypot true positives, 7 false positives.

honeypots = [] works as a workaround (controller iterates nothing; view falls back to a nameless input browsers can't submit) but still emits the wrapper <div> / <style> / <label> / <input> into the DOM, and isn't documented as a way to disable the feature.

drawback

when the spinner is on and the honepot is off, we end up with markup like this:

<div>
  <style media="screen">
    . {display:none;}
  </style>
  <input type="hidden" name="spinner" value="..." />
</div>

which works fine but has some invalid/irrelevant aspects to it

we could refactor things to generate nice output in all circumstances, it's a larger refator, but not very hard. i could do it if there is interest and you could give feedback and merge 1-2 precursor PRs as i make them.

@jjb
jjb force-pushed the add-honeypot-enabled-config branch 2 times, most recently from e417863 to bd3367b Compare June 10, 2026 06:38
Mirrors the existing `spinner_enabled` / `timestamp_enabled` switches.
When `InvisibleCaptcha.honeypot_enabled = false`:

- the view helper renders only the spinner field (no hidden text input
  for password managers to autofill into)
- the controller-side `honeypot_spam?` check returns false without
  inspecting params

Use case: in some apps (especially those whose users heavily lean on
password managers like 1Password / Bitwarden / Dashlane), the manager
autofills the honeypot text input with an unrelated saved value, the
controller treats the submission as spam, and the gem responds with
`head(200)` — a blank white page with no flash. Real users get blocked.

Setting `honeypots = []` works as a workaround but still emits a stray
nameless text input in the DOM (the gem's view helper always renders
a honeypot field). This option lets the user disable the honeypot
explicitly while keeping timestamp + spinner protection.

Default is true (no behavior change for existing apps).
@jjb
jjb force-pushed the add-honeypot-enabled-config branch from bd3367b to db2b2d0 Compare June 10, 2026 06:39
@jjb
jjb marked this pull request as draft June 10, 2026 06:45
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.32%. Comparing base (b0093de) to head (dd37902).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #149      +/-   ##
==========================================
- Coverage   98.44%   98.32%   -0.12%     
==========================================
  Files          22       22              
  Lines         449      478      +29     
==========================================
+ Hits          442      470      +28     
- Misses          7        8       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jjb
jjb marked this pull request as ready for review June 10, 2026 07:07
@jjb
jjb marked this pull request as draft June 10, 2026 07:09
@jjb
jjb marked this pull request as ready for review June 10, 2026 17:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new global configuration flag honeypot_enabled to allow disabling honeypot rendering and honeypot-based spam detection (while preserving existing defaults/behavior when enabled). This addresses real-world false positives caused by password managers autofilling the hidden honeypot field.

Changes:

  • Introduces InvisibleCaptcha.honeypot_enabled (default: true) and wires it into initialization and documentation.
  • Updates view helper rendering to omit honeypot markup when disabled, and controller logic to short-circuit honeypot checks.
  • Adds controller and view-helper specs covering the new configuration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
lib/invisible_captcha.rb Adds the honeypot_enabled config accessor and initializes it to true.
lib/invisible_captcha/controller_ext.rb Skips honeypot spam detection entirely when honeypot_enabled is false.
lib/invisible_captcha/view_helpers.rb Conditionally omits honeypot label/text input when disabled; still supports spinner output.
spec/controllers_spec.rb Adds coverage ensuring requests pass when honeypot is disabled even if the honeypot param is present.
spec/view_helpers_spec.rb Adds coverage for honeypot field presence/absence and combined behavior with spinner.
README.md Documents the new honeypot_enabled option and initializer usage.
CHANGELOG.md Notes the new config option under Unreleased.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to 48
label = options.delete(:sentence_for_humans) || InvisibleCaptcha.sentence_for_humans
css_class = "#{honeypot}_#{Time.zone.now.to_i}"
end

styles = visibility_css(css_class, options)
Comment thread spec/view_helpers_spec.rb
Comment on lines +90 to +94
it 'still renders the spinner if honeypot_enabled is false and spinner_enabled is true' do
InvisibleCaptcha.honeypot_enabled = false
InvisibleCaptcha.spinner_enabled = true
expect(invisible_captcha).to match(/name="spinner"/)
end
@markets

markets commented Jun 23, 2026

Copy link
Copy Markdown
Owner

hey @jjb I think we can work on the "drawback" in future PRs, I'm going to merge this one for now. Thanks!

@markets
markets merged commit 2a9ea33 into markets:master Jun 23, 2026
20 checks passed
@jjb
jjb deleted the add-honeypot-enabled-config branch July 5, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants