A security testing spec for a web application: what gets tested, in what order, and when it is ready for production

The checklist a site, its API and its infrastructure are tested against: authentication, authorisation, injection, file upload, business logic, data exposure, headers and TLS. Includes severity ratings and production gate conditions.

SecurityTestingAPI

A security test without a closed list decided in advance is a walkthrough. You test what comes to mind, miss what does not, and afterwards there is no way to say what was covered. This spec is the list we test against: what is in scope, how a finding is classified, and what has to close before anything ships.

The goal fits in one line: confirm there is no way to obtain unauthorised access to data or to an action in the system. Every section here is an attempt to break that line from a different direction.

What is in scope

The test covers the site on the client and on the server, the API across every endpoint, the user and permission model, login and logout, password reset, two-factor authentication where it exists, cookies and sessions, the database, file uploads, outgoing email and SMS, third-party integrations, payment mechanisms where they exist, the admin interface, server and cloud infrastructure, data exposure through errors, security headers and TLS, and the logging and audit mechanisms.

Anything not on that list was not tested, and the report has to say so explicitly.

Authentication

Testing at the authentication layer tries three things: getting in without valid credentials, obtaining valid credentials by force, and holding access after it should already have closed.

  • Login bypass
  • Brute force and credential stuffing
  • Rate limiting and account lockout
  • Password strength and the password reset flow
  • Token or one-time code prediction
  • One-time code reuse and expiration
  • Session fixation and session hijacking
  • Logging in from several devices at once
  • Session revocation after logout and after a password change
  • JWT validation and algorithm manipulation
  • Token leakage
  • Permission state after a user or role change

That last line is the one that fails most often. Downgrading a user who holds a signed, unexpired token changes nothing until the token expires, unless something revokes it immediately.

Authorisation

This is the most critical part of the test, and the part an automated scanner almost always misses. A scanner does not know which identifier belongs to which account.

  • Access to another user's resource
  • IDOR and BOLA
  • Substituting a resource identifier in a request: a user, account, document or any other entity
  • Moving from a regular user to an administrator
  • Privilege escalation
  • API access without authorisation, and admin actions reached through the API
  • Permission checks on every endpoint individually, not by sampling
  • Performing actions the interface does not offer, by calling the API directly

That last item is the principle: the interface is not a security mechanism. A hidden button, a disabled field and a menu that is not rendered are presentation decisions. Testing happens against the server, not against the screen.

Injection

  • SQL and NoSQL
  • Command and OS command
  • LDAP and XPath
  • Template injection
  • Header injection and CRLF
  • HTML injection

XSS

Foreign script execution is tested everywhere user input comes back out, including the places that are easy to forget: an outgoing email, a generated document, an uploaded file.

  • Reflected, stored and DOM
  • Text fields and URL parameters
  • Emails
  • Documents and invoices
  • File uploads
  • Content policy bypass (CSP bypass)

CSRF

Every state-changing action is tested against a request arriving from a foreign site: password change, profile change, document creation, deletion, permission change and financial actions. Alongside them, the SameSite setting on the cookies.

File upload

  • Uploading PHP, JS, HTML and SVG files
  • Double extension, MIME spoofing and Content-Type bypass
  • Path traversal through the filename
  • Zip bombs and malicious files
  • Files stored inside the web root
  • Direct access to a private file, and IDOR on files
  • XSS through SVG or HTML
  • Size limits and file type limits

Path traversal

Plain ../, a URL-encoded variant, and double encoding. The target is anything outside the web root: environment files, configuration files, logs, source code and backup files.

API

For every endpoint, individually: authentication, authorisation, input validation, rate limiting, parameter tampering, mass assignment, excessive data exposure, BOLA and IDOR, HTTP method tampering, API version disclosure, debug endpoints, exposed Swagger or OpenAPI, and GraphQL introspection where it exists.

Business logic

This category contains no code defects. The code does exactly what it was written to do, and the problem is what was written.

  • Performing an action more than once
  • Bypassing usage limits, user limits or business limits
  • Changing a price or a quantity
  • Reusing a transaction
  • Using a coupon beyond what is allowed
  • Creating a document without permission
  • Deleting a document that must not be deleted
  • Changing a document after it was issued
  • Race conditions and double spending

Race scenarios are tested with parallel requests, not sequential ones. One request after another almost always behaves correctly. Two at the same instant are what surfaces the problem.

Sensitive data exposure

Checked for exposure of passwords, API keys, tokens, secrets, customer details, financial data, personal data, database credentials, environment files, source maps, stack traces, internal IP addresses, and unnecessary fields in API responses.

Security headers

HSTS, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and Frame-Ancestors or X-Frame-Options. On the cookies: Secure, HttpOnly and SameSite.

HTTPS and TLS

HTTPS only, automatic redirect from HTTP, TLS configuration and certificate validity, TLS versions and weak ciphers, mixed content, and anything still travelling over HTTP.

Rate limiting and abuse

Rate limiting is tested on login, registration, password reset, the one-time code, SMS and email sending, the API, document creation, file uploads, and any action that is expensive in CPU or database time. Alongside it, the possibility of denial of service at the application layer, without large traffic volume.

Database

SQL injection, the privileges of the account the application connects with, exposure of the database to the internet, encryption, secrets management, least privilege, backups, direct database access, and encryption of sensitive fields.

Admin interface

Login bypass, privilege escalation, access to the admin API, role changes, creating an administrator, deleting a user, changing user data, exporting data, access to audit logs, and access through a direct URL without passing through the interface.

Third-party integrations

OAuth, Google or Microsoft sign-in, payment providers, email and SMS providers, webhooks, API keys, signature validation, replay attacks, and SSRF through the integration.

SSRF

Tested for whether a user can make the server issue a request to an address of their choosing: localhost, 127.0.0.1, private IP ranges, cloud metadata endpoints, and internal services.

Misconfiguration

Debug mode, default credentials, directory listing, backup files, test and development endpoints, open Swagger, verbose error messages, server version disclosure, unnecessary services, and the CORS configuration.

CORS is tested separately: the value of Access-Control-Allow-Origin, use of a wildcard, credentials combined with CORS, origin validation, the null origin, arbitrary origins, and API access from a foreign site.

Sessions

Expiration, idle timeout, token rotation, token invalidation, the Secure, HttpOnly and SameSite flags, session fixation and concurrent sessions.

Dependencies

npm packages and both server and client dependencies, known CVEs, outdated packages, and vulnerable transitive dependencies. A package with a Critical or High severity vulnerability closes before the next test round, not after it.

Client side

Secrets exposed in JavaScript, source maps, DOM XSS, what is kept in LocalStorage and SessionStorage, sensitive data in the browser, bypassing authorisation enforced only on the client, API request manipulation, and exposed environment variables.

Automated tooling

Before the manual test: OWASP ZAP, Burp Suite, Nuclei, dependency scanning, SAST, DAST, secret scanning and TLS scanning. Tools find what has a known signature, and do not find an authorisation flaw or a business logic flaw. They shorten the manual test rather than replacing it.

Manual penetration testing

The manual test attempts the full escalation chain:

Unauthenticated → Authenticated user → Other user → Privileged user → Admin

Every possible transition point is documented, including the ones that were blocked. Documenting a failed attempt is what makes the report useful on the next round.

Severity rating

Level Meaning
Critical System takeover, significant leakage or severe damage
High Significant exploitation of the system or of sensitive data
Medium Limited damage, or exploitation requiring specific conditions
Low A weakness with limited impact
Informational A hardening recommendation with no significant exploitation

What gets delivered

An executive summary, a list of every finding with a severity rating for each, the affected endpoint or URL, a description of the weakness, the conditions required to exploit it, a proof of concept, the impact, a remediation recommendation, evidence and screenshots. After remediation a retest runs, ending with a list of what closed and what stayed open.

Pass criteria

The system counts as ready when there are no Critical findings, no open High findings, and Medium findings have either been fixed or carry documented risk acceptance. On top of that: permissions were checked at the API level and not only in the interface, no secrets are exposed, there is no path to another user's data, authentication and session management behave correctly, rate limiting exists at the sensitive points, and HTTPS and the security headers are configured properly. The retest has run.

This list is the basis for the audit Slate went through. The security audit covers what was actually tested and what was found.