Last updated: August 17, 2026

Why this page exists

We ask people for an email address and a password, and we host pages that children's families will share. That is enough to owe you a straight account of how the thing is built and where it is weak. This page is that account. It is not a certification and it does not claim one.

1. The idea underneath it

The most reliable way to protect a piece of information is not to have it.

So the wish list does not have a surname field, an age field, an address field, a phone field or a photo of a person. It is not that we protect them well. They do not exist in the database, and the signup form actively rejects text that looks like any of them.

The same choice repeats everywhere:

  • We do not store your raw IP address on a list. We store a one way hash and cannot reverse it.
  • We do not store the name or email of anybody who claims a gift. We store a timestamp.
  • We do not store the price of any item you save.
  • We do not take a payment on this site, so there is no card number here to steal.
  • Our newsletter has no tracking pixel and no click wrapper, so there is no engagement profile to leak.

2. Who runs this

One person, with agent assistance, on one machine. There is no security team, no on call rotation and no second pair of eyes on a deployment. That narrows some risks, because the number of people with production access is one, and it removes others entirely, because there is no separation of duties and no independent review. We would rather write that sentence than imply an organisation that does not exist.

3. Accounts and passwords

  • Passwords are stored using WordPress's own one way hashing. We never see, log or store your actual password, and nobody here can tell you what it is.
  • Minimum length is 8 characters.
  • Password reset uses WordPress's standard single use, time limited link.
  • The reset endpoint returns the same message whether or not an address exists here, so it cannot be used to find out who has an account.
  • Sign in is rate limited to 12 attempts per 10 minutes from one address, and password resets to 5 per hour.
  • Account holders are subscribers with no admin access, are redirected out of the WordPress admin area entirely, and see no admin toolbar.

4. Transport and hosting

The site runs over HTTPS on Hostinger, behind their content delivery layer, on current PHP and current WordPress. Because that delivery layer sits in front, our code reads the forwarded address rather than the connecting one when it needs to rate limit, which is a detail that matters for accuracy.

5. Abuse limits, and the actual numbers

We publish these because a vague claim about rate limiting is worth nothing.

Action Limit
Signup attempts 20 per hour, per address
Sign in 12 per 10 minutes
Password reset 5 per hour
Slug availability checks 60 per hour
Creating another list 12 per hour
Saving a list 120 per hour
Claiming an item 40 per hour
Minting an extension token 10 per hour
Capturing an item from a shop 60 per hour
Lists created, per address 5 per day
Lists created, whole site 60 per day
Items per list 12
Lists per account 6

Signup also carries a honeypot field that must stay empty and a signed timing check that rejects a form submitted faster than a human can fill it or older than six hours.

6. Private lists are enforced on the server

A private list returns a not found page to anybody who is not its owner. It is not hidden with styling and it is not merely left out of a listing. The same request also switches off page caching for that address, so a private page cannot be handed to the next visitor by the cache, and it is excluded from our public trending aggregate.

7. Moderation, and why lists are not indexed at first

Every new list is live immediately, so it can be shared, and is marked no index so search engines do not list it. A human has to approve it before that changes, and approval requires the owner to have confirmed their email address. Any later edit that adds an item captured from a shop puts the list back into review and back to no index. A moderator can take any list off the web in one click.

Free text that visitors write, the intro note and the item notes, is stripped of email addresses, web addresses, @handles and phone shaped digit runs before it is stored. That filter runs on save, not on display, so what is in the database is already clean.

8. Tokens and the Chrome extension

The extension uses a token that is generated on your machine's request, shown to you exactly once, and stored on our side only as a hash. It authorises exactly two operations, adding one item to one of your own lists and reading the names of your own lists. It cannot sign in as you, cannot read your email address, cannot change your password, and cannot touch anybody else's list.

The token automatically expires 12 months after its last authenticated use, and you can revoke it yourself immediately at any time from the account screen. Generating a new one also invalidates the old one, and deleting the account invalidates it too.

The extension itself stores its token in local extension storage and deliberately does not sync it to your Google account, which is a decision made specifically so that a credential does not end up replicated to a third party's servers.

9. Third parties

Every third party on the site is a place data could go, so here they are: Hostinger for hosting, Titan for email, Google for analytics, tag management and advertising, Google Drive for backups, and Amazon and eBay when you click their links. The Cookie Policy says what each one does in the browser and the Privacy Policy says what each one receives. We periodically check this list against what is actually loading on the site rather than assume it stays accurate; the most recent check found and removed one script (Zoho PageSense) nobody currently here had installed or knew about.

Our wish list plugin makes no outbound network calls at all from our server. It does not fetch shop pages, it does not call an API, and it does not phone anything home.

10. Backups

The site backs up to Hostinger's servers daily, and copies those backups off site to Google Drive.

The off site copy failed for a stretch in early August, on an expired authorisation, and backups existed on the host but not off it during that window. That is fixed: off site delivery has been re-authorised and a successful upload is confirmed in the backup log, and we check that it keeps landing rather than assume it does. We are telling you about the outage anyway, because a security page that only mentions the good state is exactly the kind of claim this page exists to avoid.

Backups contain the whole database, which means an account record or a wish list can persist inside a backup for a period after it has been deleted from the live site.

11. What is not in place

The honest list, in the order we consider it important. This page gets rewritten when this list changes, and the point of publishing it is that it should get shorter: five items closed since the previous draft, listed at the end of this section.

  1. No security or firewall plugin is installed. No plugin fills this gap; two specific holes it would normally cover are closed directly instead, see the closed list below.
  2. No two factor authentication on the administrator account.
  3. No independent penetration test and no external audit. We have never had one and we are not going to imply that we have.
  4. No formal written incident response plan. What exists is one person, a backup and a host support line.
  5. No data processing agreements with our providers beyond their standard terms.
  6. SMTP credentials are stored in the site's own settings in plain text, which is how nearly every WordPress mail plugin works and is still worth stating.

Closed since the previous draft of this page:

  • XML-RPC is now fully disabled, not merely deprioritised. xmlrpc.php refuses the requests that matter (login, publishing, pingback) rather than sitting open.
  • Anonymous enumeration of user accounts through the REST API is blocked. /wp/v2/users requires you to be signed in; it used to answer anyone.
  • The off site backup gap above is fixed, not merely acknowledged.
  • Extension tokens now expire after 12 months of no use, with a self-serve revoke button.
  • Self-serve account deletion exists in the dashboard; deletion by email request also still works.
  • Automatic retention limits are live on hashed IPs (12 months), claim records (die with the list), extension tokens (12 months idle), and unsubscribed newsletter records (3 years, then reduced to a hash).

12. If something goes wrong

If personal information here is exposed, we will find out what happened, close it, and tell the people affected, in plain language, as promptly as we can and as the law requires.

13. Reporting a vulnerability

If you find a hole, please tell us before you tell anybody else. Write to info@nerfguns.net with enough detail to reproduce it. We will reply, we will credit you if you want the credit, and we will not threaten you. We do not run a paid bug bounty.

Postal address: 4001 S Pine St, #110542, Tacoma, WA 98411-9994

Please do not test using other people's accounts, do not run automated scanners against the site, and do not access, change or publish anybody's data to prove a point. Make a wish list and attack your own.

14. Review

This page gets rewritten when the list in section 11 changes, and the point of publishing the list is that it should get shorter.

Contact: info@nerfguns.net