Every check we run.One scan.
194 deterministic checks across security, AI exposure, payments, email, production readiness and SEO. Each is evidence-based — reported only when the condition is observed on your live site — and ships with a paste-ready fix.
Prefer to work through it as a pre-launch checklist? See the production readiness checklist.
All checks
Anthropic API Key Exposed
Your Anthropic API key is public, so anyone can make model calls billed to your account.
AWS Access Key Exposed
An AWS access key is exposed.
Cloudinary API Secret Exposed
A Cloudinary URL containing your API secret is public.
Database Connection String Exposed
A database connection string including its password is exposed.
Exposed environment file (.env)
This file is being served to anyone who requests it, and it holds the credentials your application runs on — database…
Exposed git credentials file
A .git-credentials file is publicly served.
Exposed SQL database dump
A SQL database dump is being served to anyone who requests it.
Firebase Realtime Database is publicly readable
Your Realtime Database answers read requests from anyone on the internet, with no authentication.
Firebase Storage bucket is publicly listable
Anyone can list the contents of your Storage bucket without signing in, which means every uploaded file — user docume…
GitHub Token Exposed
A GitHub token is exposed.
Groq API Key Exposed
A Groq API key is public.
Hugging Face Token Exposed
A Hugging Face access token is public.
Supabase Row Level Security is not enabled
This table answers unauthenticated read requests from anyone on the internet.
npm Access Token Exposed
An npm access token is public.
OpenAI API Key Exposed
Your OpenAI API key is public, so anyone can make model calls billed to your account.
Perplexity API Key Exposed
A Perplexity API key is public.
Private Key Exposed
A private key is exposed.
PyPI API Token Exposed
A PyPI API token is public, allowing an attacker to publish releases of your Python packages.
Replicate API Token Exposed
A Replicate API token is public.
Resend API Key Exposed
A Resend API key is public, letting anyone send email from your verified domain.
SendGrid API Key Exposed
A SendGrid API key is public, letting anyone send email AS your verified domain — passing your SPF and DKIM checks, s…
Slack API Token Exposed
A Slack API token is public.
Stripe Secret Key Exposed
A live secret key for your payment provider is readable in your public JavaScript.
Stripe Webhook Signing Secret Exposed
Your Stripe webhook signing secret is public.
Subdomain takeover
`{host}` still points at {vendor}, but the resource behind it is gone — {vendor} is serving its "nothing here" page.
Supabase Service Role Key Exposed
Your Supabase service_role key is public.
xAI API Key Exposed
An xAI (Grok) API key is public.
A redirect parameter sends visitors to any URL it is given
The {listed} parameter takes a destination and redirects to it without checking where it points.
A response sets a session cookie and allows shared caching
This page returns {listed} in a `Set-Cookie` header while its `Cache-Control` says `{cache_control}`, which permits a…
A sign-in form puts the password in the URL
A form on this page collects a password and submits it to {form_action} with `method="get"`, which puts the password…
A sign-in form sends passwords over an unencrypted connection
A form on this page collects a password and posts it to {form_action} — an explicit `http://` address, so the submiss…
Anyone can sign up with an email address they do not own
Your Supabase project allows public signups while email confirmation is turned off, so an account is active the momen…
Exposed .git Directory
Your .git directory is publicly served, which means your entire source code and its full commit history can be recons…
Exposed config file containing credentials
A configuration file holding credential fields (such as a password, secret, or database connection string) is publicl…
Exposed docker-compose file
Your docker-compose file is publicly readable.
Exposed internal/monitoring endpoint
An internal endpoint that should never be public is reachable without authentication and is returning real data.
Exposed version-control directory
A version-control metadata directory (Subversion, Mercurial, or Bazaar) is publicly served.
HTTP is not redirected to HTTPS
Your site is served over HTTPS, but a visitor who types the address without it still gets a plain-HTTP response.
Mapbox Secret Token Exposed
A Mapbox SECRET token (sk.) is in your client-side code.
Missing Content-Security-Policy header
Without a Content-Security-Policy, any script that reaches your page runs with full access to it — including anything…
Overly Permissive CORS with Credentials
This endpoint reflects any origin back in Access-Control-Allow-Origin while also allowing credentials.
Session Cookie Missing 'HttpOnly' Flag
This session cookie is readable by JavaScript, so any script that runs on your page can steal it — including one inje…
Session Cookie Missing 'Secure' Flag
This session cookie is sent over plain HTTP as well as HTTPS.
Slack Incoming Webhook URL Exposed
A Slack incoming webhook URL is public.
Stripe Restricted Key Exposed
A Stripe restricted key (rk_live_) is public.
TLS certificate does not validate
The certificate served for {host} does not validate ({reason}).
TLS certificate expiring
Your TLS certificate has expired.
CSP allows 'unsafe-eval'
A medium-severity security check ShipReady runs against your live site.
CSP allows 'unsafe-inline' scripts
A medium-severity security check ShipReady runs against your live site.
CSP script-src allows an overly permissive source
A medium-severity security check ShipReady runs against your live site.
Directory Listing Enabled
This directory returns an index of its contents instead of a page, so anyone can browse the files it holds rather tha…
Error page leaks a stack trace
Your error page returns a raw stack trace to visitors.
Exposed Debug or Config Endpoint
This endpoint is reachable without authentication and returns internal detail — environment configuration, routes, or…
GraphQL introspection is enabled in production
Your GraphQL API will describe its own schema to anyone who asks.
Insecure (http) resources loaded on a secure page
This page is served over https but loads one or more resources over plain http.
Missing or permissive X-Frame-Options header
Any site can load yours inside an invisible frame, overlay its own buttons, and capture the clicks your users think t…
Missing Strict-Transport-Security header
Strict-Transport-Security tells a browser to refuse plain HTTP for your domain, even before it makes the request.
Potential Secret or Private Token Exposed
A value that looks like a credential is assigned to a variable named as a secret, token, or password in code the brow…
Public Supabase Storage bucket
Anyone can list the contents of this Storage bucket without signing in, so every file it holds can be enumerated and…
Server still accepts a deprecated TLS version
Your server still completes connections over {listed}.
Session Cookie Missing 'SameSite' Attribute
Without SameSite, browsers attach this session cookie to requests made from other sites.
Session Cookie Uses 'SameSite=None' Without 'Secure'
This cookie asks to be sent on cross-site requests (SameSite=None) but is not marked Secure.
Third party script missing SRI
Your page loads JavaScript from {cdn} with no `integrity` attribute, so the browser runs whatever that URL returns wi…
Your API documentation is publicly reachable
{paths} serves {served} to anyone who asks, with no authentication.{console} What this exposes is not one endpoint b…
Exposed .DS_Store file
A macOS .DS_Store file is being served.
Exposed JavaScript Source Map
This source map is publicly readable, so your original source — including comments, internal file paths and any logic…
Invalid Referrer-Policy value
Your Referrer-Policy header is set to a value browsers do not recognise, so they ignore it and fall back to their def…
Missing or invalid X-Content-Type-Options header
Without nosniff, browsers guess at a file's type when the declared one looks wrong.
Missing Referrer-Policy header
Without a Referrer-Policy, browsers send your full URL — path, query string and all — to every external site your pag…
Response header discloses a software version
Your {header_name} header advertises an exact version ({value}).
Strict-Transport-Security is missing includeSubDomains
HTTPS is enforced for this hostname but not for its subdomains.
A stylesheet loads without an integrity check
Your page loads CSS from {cdn} with no `integrity` attribute, so the browser applies whatever that URL returns withou…
Weak Strict-Transport-Security max-age
Your HSTS header is present but expires soon, so the protection lapses for anyone who has not visited recently.
More than one DMARC record is published
`_dmarc.{domain_label}` publishes {duplicate_count} separate DMARC records.
Multiple SPF records published
`{org_domain}` publishes {value} separate SPF records.
MX record points to a hostname with no address
{scope} MX host{value} `{org_domain}` publishes resolve{value} to neither an A nor an AAAA record, so a sending serve…
SPF explicitly authorizes any server to send mail
The SPF record on `{org_domain}` ends in an `all` mechanism that resolves to a pass — either written as `+all`, or as…
The contact address on your site cannot receive mail
Your site publishes “{address}” as a way to reach you, and {cause} Anyone who writes to it gets a bounce, and you nev…
BIMI logo could not be fetched
The BIMI record at `default._bimi.{org_domain}` points to {logo_url}, but it could not be retrieved ({reason}).
BIMI record has no usable logo location
The BIMI record at `{name}` is missing an `l=` tag, or its value is not an HTTPS URL — BIMI requires the logo locatio…
DKIM key is published but revoked
The DKIM record at `{name}` exists but its `p=` tag is empty, which per RFC 6376 means the key has been explicitly re…
DKIM public key is not valid base64
The DKIM record at `{name}` has a `p=` tag that is not valid base64, so the public key it is supposed to hold cannot…
DMARC record has no usable policy
The DMARC record on `{domain_label}` {policy_problem}.
Domain sends email but cannot receive it
`{org_domain}` publishes an SPF record, so it sends mail — but it has no MX record, so nothing can deliver mail back…
Email configuration incomplete
`{org_domain}` is missing {value} of the records that make its email trustworthy: {listed}.
MTA-STS policy file could not be fetched
`{org_domain}` publishes an MTA-STS TXT record, so it has declared intent to use MTA-STS, but the policy file at {pol…
MTA-STS policy file is malformed
`{org_domain}` publishes an MTA-STS TXT record, so it has declared intent to use MTA-STS, but the policy file at {pol…
No DKIM signature configured
Your SPF record shows mail is sent through {provider}, but the DKIM key {provider} publishes at `{value}._domainkey.{…
No DMARC record found
`{org_domain}` publishes no DMARC policy, so receiving mail servers have no instruction on what to do with messages t…
No SPF record found
`{org_domain}` publishes no SPF record, so there is no list of servers authorised to send mail on its behalf.
SPF record contains an unrecognized term
The SPF record on `{org_domain}` contains {value} term{value} that match no valid SPF mechanism or modifier — most of…
SPF record exceeds the 10 DNS-lookup limit
The SPF record on `{org_domain}` contains {lookups} mechanisms that each cost a DNS lookup to evaluate (include, a, m…
SPF record says nothing about servers it does not list
The SPF record on `{org_domain}` {explanation}, so a server that matches none of the mechanisms in it gets the result…
BIMI logo does not look like an SVG
The BIMI record at `{name}` points to {logo_url}, which fetched successfully but its content does not look like an SV…
DKIM record declares an unrecognized key type
The DKIM record at `{name}` sets `k={value}`, which is not a key type any mail receiver recognizes (the registered va…
DMARC has no aggregate reporting address
The DMARC record on `{domain}` has no `rua=` tag, so receivers that support DMARC reporting have nowhere to send thei…
DMARC policy applies to only part of your mail (pct < 100)
The DMARC record on `{domain}` enforces `p={policy}` but with `pct={pct}`, so only {pct}% of messages that fail authe…
DMARC policy is set to 'none'
A DMARC record exists on `{domain_label}` but its policy is `p=none`, which only asks receivers to report failures —…
DMARC reports are sent to a domain that has not authorised them
The DMARC record on `{domain}` asks receivers to send its reports to {listed}, which is outside your own domain.
DMARC treats subdomains more leniently than the domain itself
The DMARC record on `{domain}` sets `p={policy}` for the domain but `sp={subdomain_policy}` for its subdomains, and s…
Eligible for BIMI but not configured
`{org_domain}` already enforces DMARC (p={dmarc_policy}), which is the hard prerequisite for BIMI — publishing a BIMI…
Eligible for MTA-STS but not configured
`{org_domain}` already enforces DMARC (p={dmarc_policy}), so the domain authenticates who is allowed to send as it —…
MX host has no reverse DNS (PTR) record
{scope} MX host{value} `{org_domain}` publishes {value} no PTR record for any of its addresses.
Your robots.txt tells search engines to stay out of the whole site
robots.txt contains a root `Disallow: /` that applies to {engines}, so {subject} instructed not to crawl any page on…
Your site tells search engines not to index it
This page carries a `noindex` directive in {source}, which instructs Google and every other search engine to leave it…
AI assistants are blocked from reading your site
Your robots.txt disallows {value} AI crawler{value}, so those assistants cannot read your pages and cannot cite you w…
Canonical URL points to a different domain
This page's canonical tag points to `{netloc}`, a different site.
Page declares more than one canonical URL
This page carries {value} canonical tags naming different URLs.
Page title tag is empty
This page has a `<title>` element with nothing in it.
Several pages share the same title
{count} of the pages we crawled serve an identical `<title>`.
Sitemap is published but lists no URLs
The sitemap at {sitemap_url} parses correctly but contains no entries, so it tells search engines and AI crawlers not…
Sitemap is served but cannot be parsed
Your site serves a sitemap at {sitemap_url}, but {reason}.
Sub-page canonicalises to the homepage
This page declares the homepage as its canonical URL, which tells search engines it is a duplicate of the homepage an…
Your CDN blocks AI crawlers before they reach your site
Requesting your homepage as an ordinary browser returns {status_code}, but requesting the same URL as GPTBot returns…
Article does not declare its author or publication date
This page presents itself as an article but declares no {value} in its markup.
Meta description is long enough to be truncated
This page's meta description is {value} characters.
No canonical URL declared
This page declares no canonical URL, so search engines have to guess which address is the real one when the same cont…
No mobile viewport declared
The page declares no viewport meta tag, so mobile browsers fall back to rendering it at desktop width and scaling it…
No social preview image
No og:image is declared, so any link to your site shared on Slack, X, LinkedIn, Discord or iMessage renders as a bare…
No structured data found
The page publishes no JSON-LD structured data, so search engines and AI assistants have to infer what your product is…
Page has no H1 heading
This page has no H1, so nothing in the markup states what it is about in one line.
Page title is long enough to be truncated in search results
This page's title is {value} characters.
Several pages share the same meta description
{count} of the pages we crawled serve an identical meta description.
Sitemap has not been updated in over a year
Every dated entry in the sitemap at {sitemap_url} is older than a year — the most recent `lastmod` is {value}.
A device-fingerprinting script is present
This page loads a device-fingerprinting library.
A form collecting personal data submits via GET
A form on this page uses method=GET and collects personal data (for example an email address).
No privacy policy link found
No link to a privacy policy was found on the homepage, and the conventional paths (/privacy, /privacy-policy) did not…
Session-replay or behaviour-recording script is present
This page loads {recorder}.
Tracking cookie is set before the consent banner can be answered
This page shows a consent mechanism, and an analytics or advertising tracking cookie was already set by the very firs…
Tracking cookie is set on the first response
An analytics or advertising tracking cookie is set by the server on the first response, before the visitor has intera…
Analytics or advertising tracker loads without a detected consent step
This page loads {trackers}, and this scan saw no consent banner, consent-management platform, or consent-mode signal…
Fonts are loaded from Google's servers
This page loads web fonts directly from Google's servers (fonts.googleapis.com / fonts.gstatic.com).
No terms of service link found
No link to a terms of service was found on the homepage, and the conventional paths (/terms, /terms-of-service) did n…
Third-party content is embedded on the page
This page embeds content that loads from a third party (for example a video, a map, or a chat widget).
Your privacy policy does not appear to name a service the site uses
This site loads {listed}, and the privacy policy at {policy_url} does not appear to mention it by name or by the comp…
Your privacy policy gives no way to contact you
The privacy policy at {policy_url} contains no email address, no mailto: link, and no link to a contact page, so a re…
A development build is being served to real visitors
A medium-severity production readiness check ShipReady runs against your live site.
Missing Basic HTML Metadata
Pages without a title, description or Open Graph image are rendered by search engines and social platforms from whate…
Page says it does not exist but returns a success status
This page returns HTTP 200 while its {where} reads “{text}”.
Placeholder template content is still live on the site
This page still shows {value}.
Production build points at localhost
Your published JavaScript contains {value}.
Production build references a staging or preview environment
Your published JavaScript references {value}, which is a non-production deployment rather than this site.
Shipped JavaScript logs sensitive data to the browser console
Your production JavaScript contains console logging that prints values named as credentials ({value}).
Unedited Scaffold Branding
Your page title is still the default your framework generated.
Missing Proper 404 Status Code
Requests for pages that do not exist return a success status instead of 404.
Missing robots.txt
Without robots.txt, crawlers work from defaults: they cannot find your sitemap, and you have no way to keep them out…
No sitemap is discoverable
A sitemap tells search engines which pages exist and when they changed, rather than leaving them to discover everythi…
The site has no browser-tab icon
The homepage declares no icon and /favicon.ico is not served, so browsers fall back to a blank placeholder in the tab…
AI assistant response text left in the page
This page contains text that reads like an assistant's reply about writing the page rather than the page itself.
Broken internal link
{count} {noun} on this site point at pages that do not load.
Legal page placeholder
This page is a legal document your visitors are asked to accept, and it still contains fields nobody filled in.
Pricing contradiction
Two pages state different prices for “{plan_name}”: {lower_price} on one and {higher_price} on the other.
Unrendered template variable on the page
This page shows template syntax where a real value should have been substituted, so a visitor reads the placeholder i…
A placeholder contact address is published on the site
The address “{address}” is at a domain that ships inside templates rather than one you own.
Dead link target
The “{label}” link on this page has no destination — its href is “{value}”, and there is no script attribute on it to…
Unremoved builder attribution
This site still carries {provider} attribution.
Outbound links lead to pages that are gone
{count} {noun} on this site point at pages on other sites that return 404 or 410.
Stale copyright year
The footer reads {latest} and it is {current}.
A JavaScript bundle is large enough to make the page feel slow
`{script_path}` is {script_size} {basis}, several times what a well-built entry bundle costs.
An image is large enough to be slowing the page down
`{path}` is {size}.
Real visitors wait too long to see your main content
Largest Contentful Paint measures how long it takes for the biggest thing on screen — usually your hero image or head…
The page is served without compression
The HTML document is sent with no Content-Encoding (gzip, Brotli, or similar), so every visitor downloads the full un…
The page is slow to respond when people tap or click
Interaction to Next Paint measures the delay between a visitor acting — a tap, a click, a keypress — and the screen c…
The page moves under people while it loads
Cumulative Layout Shift measures how much the page jumps around as it loads.
Build assets are served without caching
A hashed, build-immutable asset (its filename changes when its contents change) is served with no long-lived Cache-Co…
Images have no width and height
One or more images set neither a width nor a height attribute, so the browser does not know how much space to reserve…
Several scripts block the page from rendering
The document head loads three or more external scripts with neither async nor defer, so the browser must stop, downlo…
The page is reached through a chain of redirects
Loading this URL followed three or more redirects before arriving at the final page.
Embedded frames have no title
One or more visible <iframe> elements have no title attribute.
Form fields have no associated label
One or more form fields (input, select, or textarea) with an id have no matching <label>, and no aria-label, aria-lab…
Image buttons have no text alternative
One or more <input type="image"> buttons have no alt text.
Images have no text alternative
One or more images on this page have no alt attribute.
The page does not declare a language
The <html> element has no lang attribute.
The page prevents pinch-to-zoom
The viewport meta tag disables or caps zoom, so visitors cannot pinch to enlarge the page.
The page refreshes or redirects itself on a timer
A <meta http-equiv="refresh"> reloads or redirects this page after a delay.
Heading levels are skipped
The heading outline jumps a level (for example an h2 followed directly by an h4, with no h3 between).
Headings have no text
One or more headings (h2–h6) contain no text.
Secret published through a browser-exposed environment variable
`{name}` is compiled into JavaScript that every visitor downloads, so its value is public.
AI provider client is configured to run in the browser
Your client-side JavaScript creates an AI provider client with `dangerouslyAllowBrowser` enabled.
Exposed AI tooling config that can contain credentials
This {tool} file is publicly readable.
MCP server is reachable without authentication
An MCP server is responding at {url} to requests carrying no credentials (HTTP {status}).
AI system prompt is hardcoded in the browser bundle
Your client-side JavaScript contains the system prompt for an AI feature.
Exposed AI Tooling Config File
This {tool} file is publicly readable.
AI builder fingerprint exposed
A low-severity ai exposure check ShipReady runs against your live site.
AI widget missing SRI
Your page loads {vendor}'s AI widget from its CDN with no Subresource Integrity (`integrity`) attribute, so the brows…
AI endpoints are reachable from your client code
Your client-side JavaScript references first-party AI/LLM API routes, which means anyone who reads the bundle knows t…
A payment form submits over an unencrypted http:// connection
A form on this page collects {what} and posts them to {action} — an explicit `http://` address, so the submission is…
Card details are collected by your own page, not a hosted payment field
This page contains its own input fields for {value}, so the card number is typed into markup you serve rather than in…
Payment test mode key
Your published JavaScript contains {marker}, so payments on this site are being sent to {provider}'s test environment.
Working discount codes are compiled into the browser bundle
Your published JavaScript contains {value} discount code{value} with their values, in {where}.
A PayPal order is priced in the browser
This page creates the PayPal order in client-side JavaScript, with the amount written into `purchase_units` before th…
Both live and test Stripe keys are shipped to the browser
Your client bundle contains both a live (`pk_live_`) and a test (`pk_test_`) Stripe publishable key.
Checkout price is submitted from a hidden form field
A checkout form on this page carries the price in a hidden field named `{field}` and submits it to {endpoint}.
Checkout request sends an amount built in the browser
Client-side JavaScript on this page sends a request to `{endpoint}` carrying a `{field}` value in its body.
Run all 194 against your site
ShipReady scans up to ten pages and reports what it finds, with a paste-ready fix for each. Free, no signup.