Protect sign-ups with ShieldShiba
A free captcha that checks the email address and the browser.
ShieldShiba sits next to the email field on a sign-up or contact form. When a visitor types an address, the widget runs a short proof-of-work in the browser and checks the email, the IP, and the browser. There is no puzzle. A visitor who passes sees Verified and the form gets a token. Your server sends that token to PostShiba before it accepts the sign-up.
The token is bound to the email the visitor typed, so a solved check cannot be reused for a different address. Blocked visitors never see the reason. When the block came from their IP, usually a VPN or proxy, the widget asks them to turn off the VPN and try again. When you block free email, it asks them to use their business email address. Only your server and the ShieldShiba page see the reasons.
PostShiba stores the email's domain and a SHA-256 digest of the address, never the address itself. It also keeps the IP, the user agent, and the verdict.
Before you start
- A PostShiba account. Open Security, then ShieldShiba.
- The hostnames that will embed the widget.
1. Create a site
On ShieldShiba, choose Add site. List the hostnames under Allowed hostnames. Subdomains of a listed hostname are allowed.
Each site has two keys.
- The Site key starts with
ss_pk_. It is public and goes in your HTML. - The Secret key starts with
ss_sk_. Keep it on your server. Use Rotate secret on the same page if it leaks. The old secret stops working at once.
Two checks are per site.
- Block hosting networks is on by default. Turn it off to allow data-center and hosting IPs.
- Block free email is off by default. Turn it on if sign-ups should use a work address.
2. Embed the widget
Load the script once, then put a <shield-shiba> tag inside the form. Point email-field at the email input with a CSS selector.
When the visitor passes, the widget adds a hidden input named shield_shiba_token to the form. A blocked visitor gets no token.
3. Verify the token
Send the token, the email from the submitted form, and your secret key to the verify endpoint. No API key. The email must match the address the visitor typed.
A valid token returns 200.
Accept the sign-up only when success is true and verdict is good_boy. Blocked visitors never get a token, so a successful verify always returns good_boy. hostname is the page the widget ran on. email is normalized.
Each token is single-use and valid for 5 minutes. Just before a token expires, the widget clears it and asks the visitor to verify again.
| Status | Body | Meaning |
|---|---|---|
401 |
{"success": false, "error": "invalid_secret"} |
The secret key does not belong to the token's site. |
422 |
{"success": false, "error": "invalid_token"} |
The token is missing, unknown, already used, expired, or bound to a different email. |
Treat any error as a failed check. Ask the visitor to try again. The account labels these verdicts Passed and Blocked.
Reasons
The inspector stops at the first failing check. That reason is stored on the blocked row in the account.
| Reason | Meaning |
|---|---|
invalid_email |
The address is not well formed. |
no_mx |
The domain has no mail server. |
temp_email |
The domain is a disposable or temporary inbox. |
sfs_domain |
The domain is on the StopForumSpam blocklist. |
free_email |
The domain is free webmail. Only when Block free email is on. |
network_bounced |
The address hard-bounced or was reported as spam with more than one PostShiba sender. |
machine_agent |
The browser looks scripted. Headless tools, curl, webdriver, or a form filled in under 300 ms. |
sfs_ip |
The IP is on the StopForumSpam blocklist. |
abuseipdb_listed |
The IP has an AbuseIPDB confidence score of 50 or higher. |
tor |
The IP is a Tor exit node. |
hosting_ip |
The IP belongs to a data center or hosting network. Only when Block hosting networks is on. |
Do not show these strings to the visitor. For sfs_ip, abuseipdb_listed, tor, and hosting_ip, the widget already tells the visitor to turn off their VPN and try again. For free_email, it asks them to use their business email address.
Let a trusted visitor through
Some real people can't turn off their VPN, like a traveller on a mobile eSIM. Add them to the site's Allowlist on the ShieldShiba page. An entry is an IP, an IP range such as 198.51.100.0/24, an email domain, or a full email address. A domain also covers its subdomains. A visitor who matches any entry skips every check and passes with the reason allowlisted.
On a blocked row under Latest checks, Allow IP and Allow domain add that row's IP or domain in one click. Mobile carriers change IPs often, so for an eSIM user, allow their email address or domain instead of the IP.
Check the token in Rails
Read the token from the form params and call verify before you create the user.
Log reasons on a failure if you want to see why a sign-up was blocked.
If you send a welcome email after User.create!, use a Send only key from Create an API key. The verify call itself needs no API key.