Checks

Every check has a stable ID. Your code branches on the ID, people read the text. Existing IDs never change; at most, new ones are added. There are currently 63, of which 16 cover secret keys in an app's JavaScript files.

What a finding looks like

A finding is a place where something is missing or stands out. Every finding in the response has this shape.

Finding
{
  "id": "code.secret.supabase_service_role",
  "sev": "warn",
  "critical": true,
  "label": "Supabase master key exposed (service_role, 1×)",
  "why": "With this key, any visitor can read, change and delete your entire database, bypassing all access rules. …"
}
FieldMeaning
idStable ID from the tables below. This is what your code branches on. Missing on locked findings.
sevwarn (warning, should be fixed) or info (notice, no rush).
labelShort title for people. May contain details, such as the name of a cookie.
whyOne or two sentences on what the finding means.
refsOnly on version.vulnerable: CVE or OSV identifiers, at most six.
sourceOnly on version.vulnerable: where the match comes from, for example OSV.dev.
standardsAPI only (/api/v1/scan): mapping to cwe, owasp (Top 10:2025), asvs (5.0), bsi (IT-Grundschutz) and law, see Mapping to standards.
criticalOnly on exposed secret keys in the JavaScript files: true. Each such finding deducts 40 points.
lockedOnly without a paid plan: true on locked findings. label is then empty, and id, why, refs and source are missing.

The REST API writes label and why in German unless you ask for English with lang=en, see Language. The MCP server answers in English by default. Branch on id, not on the text. A finding always means "potentially affected". It proves nothing, because we only read what any visitor sees. For keys, we name the type and where it was found and show the value only shortened, for example sk_live_…9f2A. We never output the full value.

Locked finding

Without a paid plan, only 2 findings come in full. The others keep their position in the list, but only with severity and locked: true. Check locked before your code branches on id. Full reports are available with Business, see Shortened reports.

Locked finding
{
  "sev": "info",
  "label": "",
  "locked": true
}

Encryption and certificate

Whether your site is reachable over an encrypted connection and the certificate is valid, the padlock in the browser. If either is missing, third parties can read along or visitors see a warning page. Findings appear in findings.https and findings.tls.

IDSeverityWhat is checkedStandardsHelp
https.missingWarningNo HTTPS
The site ends up unencrypted on http. Inputs such as passwords travel across the network in readable form, and the grade is always F.
CWE-319 · OWASP A04:2025 · ASVS V12.2.1 · BSI APP.3.2, TR-03116-4Explainer
https.no_redirectWarningNo redirect from http to https
The homepage answers over http:// with content instead of redirecting to https://. Anyone who opens the address that way browses unencrypted. With HSTS it is only a notice, because returning visitors are protected.
CWE-319 · OWASP A04:2025 · ASVS V4.1.2, V12.2.1 · BSI APP.3.2Explainer
tls.invalidWarningInvalid certificate
Browsers show a warning page instead of your site, for example because the certificate does not match the address.
CWE-295 · OWASP A07:2025 · ASVS V12.2.2 · BSI APP.3.2Explainer
tls.expiredWarningCertificate expired
The expiry date has passed. Browsers show a warning page instead of your site.
CWE-324 · OWASP A04:2025 · ASVS V12.2.2 · BSI APP.3.2Explainer
tls.expiringWarningCertificate expires soon
A warning under 14 days, a notice under 30 days. After expiry, visitors see a warning page.
CWE-324 · OWASP A04:2025 · ASVS V12.2.2 · BSI APP.3.2Explainer
tls.old_protocolWarningOutdated encryption
Our connection used TLS 1.0 or 1.1. Both are considered insecure; the German Federal Office for Information Security (BSI) requires at least TLS 1.2.
CWE-327 · OWASP A04:2025 · ASVS V12.1.1 · BSI CON.1, TR-03116-4Explainer

Browser security settings

House rules your server sends to the browser with every response, for example: do not run scripts from elsewhere. Without them, the browser also runs injected code. Findings appear in findings.headers.

IDSeverityWhat is checkedStandardsHelp
header.csp.missingWarningNo protection against injected scripts
Neither the Content-Security-Policy header nor an equivalent meta tag with script-src or default-src is set. If foreign code gets into the page, the browser runs it.
OWASP A02:2025 · ASVS V3.4.3 · BSI APP.3.1Explainer
header.csp.weakNoticeCSP barely stops injected scripts
The Content-Security-Policy is set but doesn't govern scripts, allows 'unsafe-inline' without a nonce or hash, or allows scripts from any address. Rated as in Google's CSP Evaluator. It then earns 10 points instead of 25.
OWASP A02:2025 · ASVS V3.4.3 · BSI APP.3.1Explainer
header.hsts.missingWarningEncryption not enforced permanently
The Strict-Transport-Security (HSTS) header is missing or set to max-age=0. On open networks, visitors can then be redirected to an unencrypted version.
CWE-319 · OWASP A04:2025 · ASVS V3.4.1 · BSI APP.3.2Explainer
header.frame.missingNoticeOther sites may embed your site
Neither X-Frame-Options nor frame-ancestors in the CSP is set. Users can be tricked into invisible clicks.
CWE-1021 · OWASP A06:2025 · ASVS V3.4.6 · BSI APP.3.1Explainer
header.xcto.missingNoticeBrowsers may guess file types
The X-Content-Type-Options header is missing. An uploaded file can then run as a script.
OWASP A02:2025 · ASVS V3.4.4 · BSI APP.3.1Explainer
header.referrer.missingNoticeFull addresses go to other sites
The Referrer-Policy header is missing. Clicking a link can pass on the full address, including any identifiers in it.
OWASP A02:2025 · ASVS V3.4.5 · BSI APP.3.1Explainer
header.permissions.missingNoticeCamera, microphone and location not blocked
The Permissions-Policy header is missing. Embedded third-party content may request these features.
OWASP A02:2025 · BSI APP.3.1Explainer
header.server.versionNoticeServer reveals its version
The Server header contains a version number. Anyone who knows a vulnerability in it finds the site faster.
CWE-497 · OWASP A01:2025 · ASVS V13.4.6 · BSI APP.3.2Explainer
header.poweredbyNoticeSite reveals its technology
The X-Powered-By header is set. It serves no purpose.
CWE-497 · OWASP A01:2025 · ASVS V13.4.6 · BSI APP.3.2Explainer

Protection against spoofed email

Whether a record at your domain provider defines who may send email in your name. Without it, fake invoices with your sender address get through more easily. Findings appear in findings.email.

IDSeverityWhat is checkedStandardsHelp
email.spf.missingWarningSenders not defined (SPF)
The domain has no TXT record with v=spf1. Mailboxes have a harder time spotting forgeries that use your sender address.
CWE-290 · OWASP A07:2025 · BSI APP.5.3Explainer
email.spf.allow_allWarningSPF allows any sender
The SPF record ends in +all. Any server may send in your name.
CWE-290 · OWASP A07:2025 · BSI APP.5.3Explainer
email.dmarc.missingWarningNo policy for spoofed email (DMARC)
There is no TXT record with v=DMARC1 under _dmarc. Spoofed email in your name gets delivered.
CWE-290 · OWASP A07:2025 · BSI APP.5.3Explainer
email.dmarc.noneNoticeDMARC only reports
The policy p=none reports forgeries but rejects none of them.
CWE-290 · OWASP A07:2025 · BSI APP.5.3Explainer
email.spf.too_many_lookupsWarningSPF with too many DNS lookups
Including nested records, the SPF record triggers more than 10 DNS lookups (RFC 7208). Many mailboxes then treat it as an error.
CWE-290 · OWASP A07:2025 · BSI APP.5.3Explainer
email.transport.unprotectedNoticeNo MTA-STS and no DANE
The domain receives email but does not require encrypted delivery. An attacker on the network can suppress encryption between mail servers.
CWE-319 · OWASP A04:2025 · BSI APP.5.3, TR-03108Explainer

Domain and DNS

Public records of your domain: whether a dangling redirect hands your address to strangers, who may issue certificates, whether DNSSEC is active and where security researchers can report vulnerabilities. Findings appear in findings.dns.

IDSeverityWhat is checkedStandardsHelp
dns.takeoverWarningAddress can be taken over
The address points via CNAME to a service such as GitHub Pages, Heroku, Amazon S3 or Shopify whose target no longer exists (recognized by the service's error page). Whoever creates it there serves their own content under your address.
OWASP A02:2025 · BSI APP.3.6Explainer
dns.caa.missingNoticeNo CAA record
Any certificate authority may issue a certificate for the domain.
OWASP A02:2025 · BSI APP.3.6, CON.1Explainer
dns.dnssec.missingNoticeNo DNSSEC
The domain is not signed, so DNS answers can be forged in transit. Checked through DNS-over-HTTPS at Cloudflare.
OWASP A02:2025 · BSI APP.3.6Explainer
dns.securitytxt.missingNoticeNo security.txt
There is no contact address for security reports at /.well-known/security.txt (RFC 9116).
BSI DER.2.1Explainer
dns.securitytxt.expiredNoticesecurity.txt expired
The Expires date is in the past.
BSI DER.2.1Explainer

Outdated software

Components of your site in versions with publicly known vulnerabilities. Findings appear in findings.versions.

IDSeverityWhat is checkedStandardsHelp
version.eolWarningSoftware without security updates
The vendor no longer ships updates for this version (source: endoflife.date). New vulnerabilities stay open.
CWE-1104 · OWASP A03:2025 · ASVS V15.2.1 · BSI OPS.1.1.3Explainer
version.vulnerableWarningSoftware with known vulnerabilities
The detected version has entries at OSV.dev or in our own list. We report it as "potentially affected".
CWE-1395 · OWASP A03:2025 · ASVS V15.2.1 · BSI OPS.1.1.3Explainer

Source code and JavaScript files

What any visitor can read in the source and JavaScript files of your app, for example keys for databases, AI services or payments. Findings appear in findings.exposure.

IDSeverityWhat is checkedStandardsHelp
code.secret_patternWarningPossible key under a telltale name
The HTML contains a value under a name such as client_secret, api_secret or access_token. Any visitor can copy it. We name the field and show the value only shortened, never in full. Keys with a known prefix (Stripe, AWS, OpenAI …) are reported under their own ID.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.supabase_service_roleWarningSupabase master key exposed
service_role key in the page source or JavaScript files. Anyone can use it to read, change and delete the entire database, bypassing all access rules.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1, V8.3.1 · BSI CON.10Explainer
code.secret.supabase_secret_keyWarningSecret Supabase key exposed
sb_secret key in the page source or JavaScript files. Anyone can use it to access the entire database.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1, V8.3.1 · BSI CON.10Explainer
code.secret.llm_keyWarningAI key exposed
Key for OpenRouter, Groq, xAI, Hugging Face, Replicate, Perplexity or ElevenLabs in the page source or JavaScript files. Anyone can use it to send requests billed to you.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.webhook_urlWarningWebhook URL exposed
Slack, Discord, Teams or Zapier webhook in the page source or JavaScript files. Anyone can use it to post messages to your channels, including fake instructions.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.llm.browser_directWarningAI call made directly from the browser
The app calls OpenAI or Anthropic without a server of its own. The key has to sit in the browser for that and can be read out.
CWE-798 · CWE-602 · OWASP A07:2025 · ASVS V13.3.1, V8.3.1 · BSI CON.10Explainer
code.env.public_secret_nameWarningSecret variable in public code
VITE_, NEXT_PUBLIC_ or REACT_APP_ variable with SECRET, PRIVATE or PASSWORD in its name. Its value ends up in every browser.
CWE-540 · OWASP A01:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.openaiWarningOpenAI key exposed
OpenAI API key in the page source or JavaScript files. Anyone can use it to send requests billed to you.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.anthropicWarningAnthropic key exposed
API key for Claude in the page source or JavaScript files. Anyone can use it to send requests billed to you.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.stripeWarningSecret Stripe key exposed
sk_live or rk_live key in the page source or JavaScript files. Depending on its permissions, it can issue refunds and retrieve customer data.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.awsWarningAWS access key exposed
AKIA or ASIA key in the page source or JavaScript files. Depending on its permissions, it reaches storage, servers and billing of your AWS account.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.githubWarningGitHub token exposed
GitHub access token in the page source or JavaScript files. Depending on its permissions, it can read or change your source code.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.slackWarningSlack token exposed
Slack token in the page source or JavaScript files. Depending on its permissions, it can read or send messages.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.sendgridWarningSendGrid key exposed
Email delivery key in the page source or JavaScript files. Anyone can use it to send email through your account.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.mail_apiWarningEmail delivery key exposed
Key for Resend, Brevo or Mailchimp in the page source or JavaScript files. Anyone can use it to send email through your account, for example phishing with your sender address, or to retrieve your contact lists.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.service_tokenWarningAccess token for an online service exposed
Token with a distinctive prefix or under a distinctive name, for example for the Supabase account, Shopify Admin, Google OAuth, Notion, Airtable, Telegram, GitLab, npm, webhook signatures (whsec_) and more than 100 other services from the gitleaks rule set, including Atlassian, Cloudflare, Datadog, Doppler, Heroku, Mailgun, Pulumi and Square. Depending on the service, it can read or change data or trigger actions in your name.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.twilioWarningTwilio key exposed
SMS and voice key in the page source or JavaScript files. Anyone can use it to send SMS at your expense.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.database_urlWarningDatabase credentials exposed
Connection URL with user and password in the page source or JavaScript files. Whoever has it can log in to the database directly.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.secret.private_keyWarningPrivate key exposed
Private key (PEM) in the page source or JavaScript files. Whoever has it can impersonate your service.
CWE-798 · CWE-540 · OWASP A07:2025 · ASVS V13.3.1 · BSI CON.10Explainer
code.supabase.rls_checkNoticeDatabase reachable directly from the browser
Supabase with a public key (anon or sb_publishable). The data is only protected by access rules (RLS) on every table. We cannot see from the outside whether they are active.
CWE-862 · OWASP A01:2025 · ASVS V8.3.1, V8.2.2 · BSI CON.10, APP.3.1Explainer
code.firebase.rules_checkNoticeFirebase reachable directly from the browser
The Firebase configuration is in the source. That is intended, but the data is only protected by Security Rules in Firestore, Realtime Database and Storage. We cannot see from the outside whether they hold.
CWE-862 · OWASP A01:2025 · ASVS V8.3.1, V8.2.2 · BSI CON.10, APP.3.1Explainer
code.sourcemap_bundleNoticeSource maps in the JavaScript files
Publicly served .map files that allow the original source code, including comments, to be reconstructed. We only report them when the file is actually served.
CWE-540 · OWASP A01:2025 · ASVS V13.4.7 · BSI CON.10Explainer
code.public_keyNoticeGoogle key in the source
In the HTML or JavaScript files, often intentional, for example for Maps. Firebase configurations are reported separately. Without a restriction to your domain, anyone can use it at your expense.
OWASP A02:2025 · BSI CON.10Explainer
code.mixed_contentWarningUnencrypted parts on an HTTPS page
Images, scripts or stylesheets load over http. On the same network they can be swapped out.
CWE-319 · OWASP A04:2025 · ASVS V12.2.1 · BSI APP.3.1Explainer
code.debug_outputWarningError message visible
Text that looks like a technical error message, such as a stack trace or a PHP warning. It often reveals paths and versions.
CWE-209 · OWASP A10:2025 · ASVS V16.5.1, V13.4.2 · BSI APP.3.1Explainer
code.sri.missingNoticeThird-party scripts without a fingerprint (SRI)
Scripts with a fixed version (for example from a CDN) without the integrity attribute. If that server is compromised, the modified code runs too. Services whose script changes all the time don't count, SRI doesn't work there.
CWE-353 · CWE-829 · OWASP A08:2025 · ASVS V3.6.1 · BSI APP.3.1Explainer
code.sourcemapNoticeSource code possibly readable (source map)
The HTML references a .map file.
CWE-540 · OWASP A01:2025 · ASVS V13.4.7 · BSI CON.10Explainer
code.sensitive_pathsNoticeReferences to sensitive files
Paths such as .env, .git or backup files appear in the HTML. We do not request them.
CWE-538 · OWASP A01:2025 · ASVS V13.4.1, V13.4.7 · BSI APP.3.2Explainer

Data protection (GDPR)

Common data protection mistakes that can be proven from the outside and often lead to legal warnings in Germany: Google Fonts from Google's servers, tracking before consent, embedded content and missing mandatory links. Not legal advice. Findings appear in findings.privacy.

IDSeverityWhat is checkedStandardsHelp
privacy.google_fontsWarningGoogle Fonts from Google's servers
Fonts from fonts.googleapis.com or fonts.gstatic.com, found in the HTML, stylesheets or JavaScript files. A warning on German-language sites; otherwise, or if the address only appears in JavaScript, a notice.
CWE-359 · BSI CON.2 · Art. 6(1) GDPRExplainer
privacy.tracking_cookiesWarningTracking cookies before consent
The server already sets analytics or advertising cookies such as _ga, _fbp or _gcl_au in its first response.
CWE-359 · BSI CON.2 · Section 25 TDDDG · Art. 6(1) GDPRExplainer
privacy.third_party_embedsNoticeEmbedded content without consent
YouTube, Google Maps or Vimeo sit directly in the page as an iframe and load on page view.
CWE-359 · BSI CON.2 · Section 25 TDDDG · Art. 6(1) GDPRExplainer

Cookies

Whether the cookies on your site are protected against eavesdropping and third-party scripts. Findings appear in findings.cookies.

IDSeverityWhat is checkedStandardsHelp
cookie.secure.missingNoticeCookie without Secure
A cookie whose name looks like a session or login may also be sent over unencrypted connections.
CWE-614 · OWASP A02:2025 · ASVS V3.3.1 · BSI APP.3.1Explainer
cookie.httponly.missingNoticeCookie without HttpOnly
A cookie whose name looks like a session or login is readable by scripts. Foreign code could use it to take over the account.
CWE-1004 · OWASP A02:2025 · ASVS V3.3.4 · BSI APP.3.1Explainer

Mapping to standards

Every check is mapped to recognized standards, so a finding can be placed in audits, for NIS2 or for auditors. The mapping is in the table above, next to every finding in the PDF report and in the API field standards. It is our classification, not a certification.

  • CWE (MITRE): the type of weakness. We only use IDs that MITRE allows for mapping. If none fits, the field stays empty.
  • OWASP Top 10:2025: the category follows from the official CWE list per category. Only for checks without a CWE do we classify ourselves, then almost always A02 (Security Misconfiguration).
  • OWASP ASVS 5.0.0: the requirement the finding violates, for example V3.4.1 for HSTS.
  • BSI IT-Grundschutz (Compendium Edition 2023, German Federal Office for Information Security): the module, for example APP.3.1 web applications and web services, plus the technical guidelines TR-03116-4 (TLS) and TR-03108 (email transport).
  • Law: for data protection, the provision, for example Section 25 TDDDG or Art. 13 GDPR. Not legal advice.

We only reference IDs and write the texts ourselves. OWASP publishes ASVS and the Top 10 under CC BY-SA 4.0, CWE comes from MITRE.

What we never do

The check stays on the surface. It loads the page and the JavaScript files the page includes itself, from the same domain only. It never does the following, no matter what the request says.

  • Probe hidden paths or request files such as .env
  • Load files your site does not include or fetch itself (except the public file /.well-known/security.txt), or read scripts from other domains
  • Look for open ports (port scan)
  • Submit forms or send attack payloads
  • Log in or use keys it finds
  • Show or store the full values of keys it finds
  • Check internal or private addresses

More in the help article What we don't check.

Is your app
watertight?

Hullwise finds the leaks before someone else does: exposed keys, database credentials and outdated software. Every finding comes with steps to fix it.

https://

Click a finding to mark it as fixed.

See pricingHow a scan works

Ship fast. Stay hullwise.