How Scanylo works
Scanylo looks at your website the way a visitor would. This page sets out what we check, what we will not do and how the score is calculated, so you can judge the report yourself.
We only look. We never attack.
A check is allowed only if it reads something your server already shows to any visitor. We never send data meant to trigger a weakness, never change anything on your site, never guess hidden addresses from word lists, and never log in.
The rules our scanner follows
- A short, fixed list of well-known file addresses, fewer than 30, with one request each, using GET or HEAD.
- At most 4 requests at the same time to your site, and about 150 requests in total per check.
- Every request carries our name: Scanylo/1.0 (+https://scanylo.com/scanner).
- We respect robots.txt for everything except security checks of well-known files.
- We check a site only after the person asking confirms they own it or are authorised to check it, and we keep a record of that.
- We refuse government, military, banking and payment sites, and any domain on our do-not-scan list.
- Scanylo has no active tests. If we ever add any, they will require proof that you control the domain, enforced in the code and not just promised here.
What we check
Eight kinds of check run in parallel, with a two-minute limit for the whole scan.
- Security headers
- Instructions your site sends to browsers, such as which scripts to trust and whether to insist on a secure connection.
- Cookies
- Whether login and session cookies are protected.
- Secure connection
- Your certificate, old weak settings, and parts of a secure page loaded insecurely.
- Email and DNS
- Protection against fake emails in your name, and web addresses that point to services you no longer use.
- Technology
- What your site appears to be built with, from what it shows publicly.
- Vulnerability waves
- Whether what we can see matches a major vulnerability in the news.
- Exposed files
- A short list of files that should never be public, such as settings and backups.
- Error pages
- What your site reveals when something goes wrong.
Confirmed, Potential, Unknown
Every result has one of three states.
Confirmed means we saw it directly, for example a missing setting or a file we could download.
Potential means the signs point to a problem we cannot prove from the outside. The usual example is a software version number: many hosting providers fix security problems without changing the version number, so an old-looking version is only Potential, never a verdict.
Unknown means we could not see enough to say, for example because your site hides its version, a firewall blocked us, or a check ran out of time. Unknown is shown in the report on purpose. It is not a pass.
How the score works
The score runs from 0 to 100 and maps to a grade from A to F. It starts at 100 and goes down for each finding. Serious problems cost more than minor ones. Each group of checks can only take off a limited number of points, so one noisy area cannot drown out the rest.
Only Confirmed findings count at full weight. Potential findings count for less. Unknown results do not lower your score, but they are listed so you can see what was not checked.
Here is the exact formula. It is the same for every site and we do not adjust it by hand.
score = 100 − Σmodule min(35, Σ weight(severity) × factor(state)), floored at 0
Severity weights
| Critical | 30 |
| Serious | 15 |
| Moderate | 7 |
| Minor | 3 |
| Info | 0 |
State factors, cap, grades
| Confirmed | × 1.0 |
| Potential | × 0.5 |
| Unknown | × 0 |
| Cap per module | 35 |
| Grades | A ≥ 90, B ≥ 75, C ≥ 60, D ≥ 40, F |
Where AI is used, and where it is not
The checks are ordinary software. Software, not AI, decides what is a finding, how serious it is and whether it is Confirmed, Potential or Unknown.
AI is used only afterwards, to write the summary and the explanations in plain language from the list of findings. It cannot add a finding, remove one or change its severity. It can still phrase something badly, so treat the wording as a help and the findings list as the record.
What this cannot tell you
From the outside we cannot see your code, your plugins' inner workings, your passwords or what happens after a login. A clean report does not mean your site is secure, and a poor one does not mean it has been hacked. A firewall or CDN in front of your site can hide things from us or add settings that are not on your own server.
Scanylo is not a penetration test, an audit or a certification.
What we keep
Raw responses from your site are deleted after 7 days. Findings are kept for 90 days. If we find a secret such as a key in a public file, we store it redacted only. See the privacy policy for the details.
Details from the code
These lists are generated from the scanner itself, so they are always current.
The full list of well-known paths (28)
- /.env
- /.env.bak
- /.git/HEAD
- /.git/config
- /.svn/entries
- /.hg/requires
- /.DS_Store
- /backup.zip
- /backup.tar.gz
- /backup.sql
- /dump.sql
- /db.sql
- /database.sql
- /wp-config.php.bak
- /wp-config.php~
- /wp-config.php.save
- /config.php.bak
- /phpinfo.php
- /info.php
- /server-status
- /wp-content/debug.log
- /composer.json
- /package.json
- /adminer.php
- /phpmyadmin/
- /elmah.axd
- /trace.axd
- /.well-known/security.txt
Every finding id and its fixed severity (62)
| cookies.secure.missing | Moderate | Cookie set without the Secure flag |
| cookies.httponly.missing | Minor | Session-like cookie set without HttpOnly |
| cookies.samesite.missing | Minor | Cookie set without a SameSite attribute |
| dnsmail.spf.permissive | Serious | SPF record allows any sender (+all) |
| dnsmail.cname.dangling | Serious | Possibly dangling CNAME to a third-party service |
| dnsmail.spf.missing | Moderate | No SPF record |
| dnsmail.spf.multiple | Moderate | Multiple SPF records |
| dnsmail.dmarc.missing | Moderate | No DMARC record |
| dnsmail.spf.weak | Minor | SPF record ends with ?all |
| dnsmail.dmarc.p_none | Minor | DMARC policy is p=none |
| dnsmail.unknown.lookup | Info | DNS records could not be checked |
| errors.stack_trace | Serious | Error page shows a stack trace or debug output |
| errors.debug_page | Serious | Framework debug page enabled |
| errors.banner | Minor | Error page discloses server version |
| errors.soft_404 | Info | Missing pages answer with status 200 |
| errors.unknown.unreachable | Info | Error page could not be checked |
| exposed.env | Critical | .env file publicly readable |
| exposed.sql_dump | Critical | Database dump publicly readable |
| exposed.wp_config_backup | Critical | WordPress configuration backup publicly readable |
| exposed.config_backup | Critical | Configuration backup publicly readable |
| exposed.git | Serious | .git repository metadata publicly readable |
| exposed.vcs | Serious | Version control metadata publicly readable |
| exposed.backup_archive | Serious | Backup archive publicly readable |
| exposed.phpinfo | Serious | phpinfo() page publicly accessible |
| exposed.server_status | Moderate | Server status page publicly accessible |
| exposed.debug_log | Moderate | Debug log publicly readable |
| exposed.admin_tool | Moderate | Database admin tool publicly accessible |
| exposed.trace | Moderate | Diagnostic trace page publicly accessible |
| exposed.ds_store | Minor | .DS_Store file publicly readable |
| exposed.composer_json | Minor | composer.json publicly readable |
| exposed.package_json | Minor | package.json publicly readable |
| exposed.security_txt.missing | Info | No security.txt |
| exposed.unknown.budget | Info | Some well-known paths were not checked |
| fingerprint.version.disclosed | Minor | Software version disclosed |
| fingerprint.stack.detected | Info | Technology stack detected |
| fingerprint.unknown.nothing | Info | Technology stack could not be identified |
| headers.csp.missing | Moderate | No Content-Security-Policy header |
| headers.hsts.missing | Moderate | No Strict-Transport-Security header |
| headers.xfo.missing | Moderate | No clickjacking protection (X-Frame-Options or frame-ancestors) |
| headers.csp.weak | Minor | Content-Security-Policy allows inline scripts or any source |
| headers.hsts.weak | Minor | Strict-Transport-Security max-age below one year |
| headers.xcto.missing | Minor | No X-Content-Type-Options: nosniff |
| headers.referrer_policy.missing | Minor | No Referrer-Policy header |
| headers.server.version_disclosure | Minor | Server header discloses software version |
| headers.x_powered_by.disclosure | Minor | X-Powered-By header discloses technology |
| headers.aspnet.version | Minor | ASP.NET version headers present |
| headers.permissions_policy.missing | Info | No Permissions-Policy header |
| headers.unknown.unreachable | Info | Response headers could not be checked |
| tls.cert.expired | Critical | TLS certificate has expired |
| tls.https.unavailable | Serious | Site is not served over HTTPS |
| tls.cert.expiring | Serious | TLS certificate expires within 14 days |
| tls.cert.name_mismatch | Serious | TLS certificate does not match the host name |
| tls.cert.untrusted | Serious | TLS certificate chain is not trusted |
| tls.https.not_enforced | Moderate | HTTP does not redirect to HTTPS |
| tls.cert.expiring_soon | Moderate | TLS certificate expires within 30 days |
| tls.mixed_content | Moderate | Mixed content: insecure resources on a secure page |
| tls.protocol.legacy | Minor | Legacy TLS 1.0 or 1.1 offered |
| tls.hsts_preload.missing | Info | HSTS preload not configured |
| tls.unknown.handshake | Info | TLS could not be checked |
| wave.potential | Serious | Version below the patched release for an active wave |
| wave.unknown | Moderate | Version hidden, wave status cannot be confirmed |
| wave.patched | Info | Version at or above the patched release for an active wave |
Request limits: 4 concurrent requests per host, 150 requests per scan, 120 s deadline, user agent Scanylo/1.0 (+https://scanylo.com/scanner).