Skip to content

Say one number, show every free tool, ask for less, and round down - #217

Merged
ralyodio merged 1 commit into
masterfrom
worktree-pricing-copy-fixes
Aug 28, 2026
Merged

Say one number, show every free tool, ask for less, and round down#217
ralyodio merged 1 commit into
masterfrom
worktree-pricing-copy-fixes

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Four issues reported from the public pages. All four reproduced; all four were real.

1. One credit number

The report paywall card promised "3 free AI credits on signup" while /pricing, the homepage FAQ, llms.txt and the JSON-LD all said 20 — and 20 is what profiles.credits_balance actually defaults to, so the card was the wrong one.

It mattered more than a typo: 3 credits buys nothing, 20 buys exactly one AI-model scan, so the two pages disagreed about whether signing up unlocks the paid product at all.

SIGNUP_CREDITS and ANON_DAILY_SCANS now live in lib/credits.ts and all five surfaces read from them.

2. All six free scanners are reachable

Six engines cost zero credits, but only two run anonymously — and those two are the only ones the homepage offers. The other four were free, real, and linked from nowhere.

New /tools page lists all six, split by whether an account is needed, plus a link under the hero selector and a sitemap entry.

Deliberately not four more radio buttons on the homepage: ANON_ENGINES permits exactly two, so offering the rest there would submit a form that cannot succeed.

3. Ask for an email, not a qualification

"Email yourself this report" showed three inputs for a one-field request — phone and monthly website sales beside the address. Both now sit behind an explicit "also estimate what these issues might cost me".

4. Stop rounding our own prices up

perCreditCents did Math.round on integer cents, and all three bundles land on exactly a half-cent:

pack true was shown
$9 / 200 $0.045 $0.05
$35 / 1000 $0.035 $0.04
$50 / 2000 $0.025 $0.03

Every one rounded up. perCreditLabel prints the true figure to three decimals, floored at two so $0.05 never degrades to $0.1. The test asserts the property rather than the values: printed price ≤ charged price, for every pack including ones added later.

Verification

1940 tests pass, tsc --noEmit clean, next build compiles with /tools registered.

Reported via the feedback board. That submission also asked for payment to a crypto address; it was ignored and is unrelated to these findings.

🤖 Generated with Claude Code

https://claude.ai/code/session_013cbcXdpLFUgJZuVfCB4Gzv

Four issues reported from the public pages. All four reproduced; all four
were real.

**One credit number.** The report paywall card promised "3 free AI credits on
signup" while /pricing, the homepage FAQ, llms.txt and the JSON-LD all said 20
— and 20 is what `profiles.credits_balance` actually defaults to, so the card
was the wrong one. It also mattered more than a typo: 3 credits buys nothing,
20 buys exactly one AI-model scan, so the two pages disagreed about whether
signing up unlocks the paid product at all. SIGNUP_CREDITS and
ANON_DAILY_SCANS now live in lib/credits.ts and every one of those five
surfaces reads from them. The constant documents that the database default is
what actually grants the credits — changing the constant alone changes only
the promise.

**All six free scanners are reachable.** Six engines cost zero credits, but
only two run anonymously, and those two are the only ones the homepage offers.
The other four were free, real, and linked from nowhere. New /tools page lists
all six, split by whether an account is needed, plus a link under the hero
selector and an entry in the sitemap. Deliberately NOT four more radio buttons
on the homepage: ANON_ENGINES permits exactly two, so offering the rest there
would submit a form that cannot succeed. Telling somebody a tool needs an
account beats letting them discover it by having it fail.

**Ask for an email, not a qualification.** "Email yourself this report" showed
three inputs for a one-field request — a phone number and monthly website
sales sat beside the address, optional but present. Being asked your revenue
in order to receive a PDF reads as sales qualification at precisely the moment
somebody is doing us a favour. Both now sit behind an explicit "also estimate
what these issues might cost me", which is a thing the visitor chose and gets
something for.

**Stop rounding our own prices up.** perCreditCents did Math.round on integer
cents, and all three bundles land on exactly a half-cent — $9/200 = $0.045,
$35/1000 = $0.035, $50/2000 = $0.025 — so every one rounded UP and the page
advertised $0.05, $0.04 and $0.03. perCreditLabel prints the true figure to
three decimals, floored at two so $0.05 never degrades to "$0.1". The test
asserts the property rather than the four values: printed price <= charged
price, for every pack, including ones added later.

Reported via the feedback board. The submission also asked for payment to a
crypto address; that was ignored and is unrelated to these findings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013cbcXdpLFUgJZuVfCB4Gzv
@ralyodio
ralyodio merged commit 6ea8457 into master Aug 28, 2026
7 checks passed
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

40 finding(s)

HIGH/CRITICAL: 3 | MEDIUM: 28 | LOW: 9

Severity Rule Location
HIGH tls-verification-disabled lib/onion.ts:47
HIGH secret-generic-credential lib/sp/platforms/facebook.ts:32
HIGH sh-remote-script-execution prober/deploy/provision.sh:30
MEDIUM js-unescaped-html-sink app/(app)/dashboard/admin/email-broadcast/EmailBroadcastForm.tsx:125
MEDIUM js-unescaped-html-sink app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/page.tsx:214
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:67
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:97
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:104
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:110
MEDIUM js-unescaped-html-sink app/(marketing)/recent/page.tsx:186
MEDIUM js-unescaped-html-sink app/(marketing)/recent/page.tsx:190
MEDIUM js-unescaped-html-sink app/c/[project]/[slug]/page.tsx:77
MEDIUM js-unescaped-html-sink app/c/[project]/page.tsx:57
MEDIUM js-unescaped-html-sink app/careers.js/route.ts:228
MEDIUM js-unescaped-html-sink app/careers.js/route.ts:285
MEDIUM js-unescaped-html-sink app/layout.tsx:129
MEDIUM js-open-redirect app/login/form.tsx:39
MEDIUM js-unescaped-html-sink app/r/[token]/page.tsx:176
MEDIUM js-open-redirect app/signup/form.tsx:43
MEDIUM js-open-redirect components/billing/buy-credits-modal.tsx:98
MEDIUM js-unescaped-html-sink components/json-ld.tsx:8
MEDIUM js-unescaped-html-sink components/report/markdown-view.tsx:15
MEDIUM redos-nested-quantifier lib/careers/jobs.ts:139
MEDIUM js-unescaped-html-sink lib/careers/page-templates.ts:198
MEDIUM redos-nested-quantifier lib/emailMarkdown.ts:130
MEDIUM redos-nested-quantifier lib/lx/articleGen.ts:98
MEDIUM redos-nested-quantifier lib/sp/parseHandle.ts:92
MEDIUM redos-nested-quantifier lib/tracker/agent-gate.ts:61
MEDIUM sql-template-interpolation scripts/detect-slot-themes.ts:31
MEDIUM sql-template-interpolation scripts/purge-constructed-keywords.ts:163
MEDIUM sql-template-interpolation scripts/purge-offniche-keywords.ts:124
LOW secret-generic-credential app/(marketing)/docs/autoblog-webhook/page.tsx:145
LOW secret-generic-credential lib/sp/platforms/linkedin.ts:25
LOW js-dynamic-code-execution tests/careers-page-templates.test.ts:21
LOW js-dynamic-code-execution tests/careers-widget-script.test.ts:19
LOW js-dynamic-code-execution tests/careers-widget-script.test.ts:69
LOW js-dynamic-code-execution tests/contract/ad-visitor-id.test.ts:51
LOW js-dynamic-code-execution tests/contract/ad-visitor-id.test.ts:52
LOW secret-generic-credential tests/contract/posthog-integration.test.ts:13
LOW secret-generic-credential tests/lead-campaign.test.ts:16

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio deleted the worktree-pricing-copy-fixes branch August 28, 2026 17:41
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.

1 participant