Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Web Security (OWASP Top 10:2025)

Web security (OWASP Top 10:2025) flashcards

Flashcards for web security: access control, injection, authentication, cryptography, APIs, SSO, LLM features, testing with ZAP, disclosure and review.

432 cards. Read the question, answer it in your head, then open the card to check.

  1. When does a test count as evidence that a fix works?

    Only when it fails against the weak version and then passes once the fix is in. A test that passes on both versions is still worth keeping, because it shows the fix did not lock the owner out, but it proves nothing about the fix itself.

    From the lesson Start here: learn web security safely and legally

  2. What four things make written permission to test a system protect you?

    It comes from someone who may grant it for that system, usually the owner or the person in charge; it is in writing; it lists which systems, which kinds of test and which time window are covered; and you keep a copy.

    From the lesson Start here: learn web security safely and legally

  3. Does a good reason, such as learning or meaning to report a bug, make testing someone else's system lawful?

    No. The UK Computer Misuse Act 1990 (section 1), the US Computer Fraud and Abuse Act (18 U.S.C. § 1030(a)(2)) and India's IT Act all turn on whether the owner allowed the access. "I was learning" and "I meant to report it" are reasons, not permission.

    From the lesson Start here: learn web security safely and legally

  4. What do sections 43(a) and 66 of India's Information Technology Act, 2000 say about accessing a computer without permission?

    Section 43(a) makes a person who accesses a computer, system or network without the permission of its owner or person in charge liable to pay compensation to the person affected. Section 66 makes the same act an offence when done dishonestly or fraudulently: up to three years in prison, a fine of up to five lakh rupees, or both.

    From the lesson Start here: learn web security safely and legally

  5. Does a security.txt file allow you to test a site?

    No. RFC 9116 defines it as a way to report a vulnerability (Contact and Expires are required), and section 5.5 says its presence or absence is neither permission nor refusal. A bounty or disclosure policy can grant permission, but only for the hosts, methods and conditions it lists.

    From the lesson Start here: learn web security safely and legally

  6. Which addresses, names and secrets keep a practice lab from reaching anyone else's system?

    Documentation addresses (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24 from RFC 5737; 2001:db8::/32 from RFC 3849), reserved names from RFC 2606 (the top-level names .test, .example, .invalid and .localhost, and the domains example.com, example.net and example.org), and secrets that start with FAKE-.

    From the lesson Start here: learn web security safely and legally

  7. A fixed check passes all of its tests. What can those tests still not show?

    That every route calls the check, that object ids cannot be listed or guessed elsewhere, or that the session really belongs to the user it names. Tests are evidence only for the cases they try, so write them from the rule, with more than one wrong user and more than one object.

    From the lesson Start here: learn web security safely and legally

  8. Which request headers can a page's script not set, and why does that not make them trustworthy?

    Forbidden request headers include Host, Origin, Cookie, Content-Length, the Sec-Fetch headers and any name starting with Sec- or Proxy-. A browser stops page script from setting them, but a script outside a browser writes them freely, so they are signals from honest browsers, never proof of who is calling.

    From the lesson HTTP, origins and the browser security model

  9. What is an origin, and what is a site?

    An origin is the scheme, host and port together; the path, the query and any user name play no part, and when no port is written the scheme's default applies (443 for https). A site is coarser: the scheme with the registrable domain, which is the public suffix plus one more label. A site depends on the public suffix list, so use origins for security decisions where you can.

    From the lesson HTTP, origins and the browser security model

  10. How do https://shop.example.com:8443 and http://shop.example.com compare with the page https://shop.example.com?

    The first has another port, so it is a different origin but the same site. The second has another scheme, which counts for both, so it is cross site. A sibling host such as api.example.com is the same site and a different origin.

    From the lesson HTTP, origins and the browser security model

  11. What does the same-origin policy block, and what does it leave alone?

    It blocks reading: script from one origin cannot read a response from another unless that origin allows it with CORS. Writes (links, redirects, form posts) and embeds (images, scripts, frames) are typically allowed, so the request is still sent and the server must decide whether to act on it.

    From the lesson HTTP, origins and the browser security model

  12. When is a cookie sent on a request from another site under SameSite=Strict, Lax and None?

    Strict: never. Lax: only on top-level navigations with a safe method, such as following a link. None (which needs Secure): on every request, unless the browser blocks third-party cookies; Firefox and Safari restrict them by default and Chrome does not, so a server cannot count on either.

    From the lesson HTTP, origins and the browser security model

  13. What do cookie scoping rules ignore, and what follows from it?

    Ports and, without Secure, the scheme. A cookie of https://shop.example.com also goes to port 8443 of that host, one without Secure also goes to http, and sibling hosts under example.com can replace each other's Domain cookies. A __Host- cookie is host-only, Secure and Path=/, so a sibling cannot overwrite it.

    From the lesson HTTP, origins and the browser security model

  14. How do you set a session cookie that reaches only the host that set it?

    Name it with the __Host- prefix and set Secure, HttpOnly, Path=/ and SameSite=Lax without Domain. It then travels only to that host over https, and no sibling subdomain can replace it.

    From the lesson HTTP, origins and the browser security model

  15. Why must every access check run on the server, even when the page hides the button?

    The browser's rules protect the person using the browser, not your server's other clients. In the lesson's sample a script with no cookie got 200 from the weak server for an export that the page had hidden. OWASP A01:2025 names access control that lives only in front-end code, and ASVS 5.0.0 requirement 8.3.1 asks for authorisation at a trusted service layer.

    From the lesson HTTP, origins and the browser security model

  16. What does each entry of the OWASP Top 10:2025 describe, and how were the entries chosen?

    A category, a group of related weaknesses (no more than 40 each), not a single bug. Data from tested applications ranked them, and a community survey promoted two more, A03 and A09, because some risks are hard to see in test data. Use the list to set priorities, not to name a bug.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  17. List the ten categories of the OWASP Top 10:2025 in order.

    A01 Broken Access Control, A02 Security Misconfiguration, A03 Software Supply Chain Failures, A04 Cryptographic Failures, A05 Injection, A06 Insecure Design, A07 Authentication Failures, A08 Software or Data Integrity Failures, A09 Security Logging and Alerting Failures, A10 Mishandling of Exceptional Conditions.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  18. Name three changes in the OWASP Top 10:2025 compared with 2021.

    Security Misconfiguration rose from fifth to second; the supply-chain category widened from outdated components to the dependencies, build systems and pipelines software is made with; and A10 is new (24 weaknesses about errors handled badly), while server-side request forgery moved into A01 Broken Access Control.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  19. How do a CWE, a CVE and a Top 10 category differ?

    A CWE names a kind of weakness that can appear in any product, such as CWE-639, a user-controlled key that bypasses authorisation. A CVE names one publicly disclosed flaw in one product and the versions it affects. A Top 10 category groups many weaknesses under one risk.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  20. How is MITRE's CWE Top 25 ranked, and why do 7 of its 25 weaknesses fall outside the Top 10:2025?

    It ranks single weaknesses by a danger score: how often a weakness appears in that year's CVE records, times their average severity. Seven fit no Top 10 category: six memory-safety weaknesses (out-of-bounds reads and writes, use-after-free, buffer overflows) and CWE-770, allocation of resources without limits. The Top 25 covers all software; the Top 10 is about web applications.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  21. Count the requirements of ASVS 5.0.0: how many are there at each level, and how do the levels relate?

    345 numbered requirements in 17 chapters (V1 Encoding and Sanitization to V17 WebRTC). Level 1 has 70 (about 20 %), level 2 has 253 (about 73 %) and level 3 is all 345. The levels are cumulative, and ASVS leaves the choice of level to each organisation, based on its own risks.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  22. How do you cite an ASVS requirement, and why with a version?

    Write it with its version, as in v5.0.0-8.2.2, because requirement numbers may change between versions. Searching the code base for that string then finds every test of the requirement.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  23. Which names make a finding something a developer, a tester and an auditor can all act on?

    The CWE says what is wrong, the Cheat Sheet Series says how to prevent it, the WSTG test (such as WSTG-ATHZ-04) says how to show it is fixed, and the ASVS requirement with its version says which promise of the application broke. Add the Top 10 category for the risk.

    From the lesson Reading the OWASP Top 10:2025, CWE and ASVS

  24. What does "deny by default" mean for the routes of an application, and what is the weak version?

    Every route declares who may use it, and a route that declares nothing is refused by the router. The weak version is a denylist ("block /admin and /internal"), which leaves every route nobody thought of open. It is OWASP's first advice for A01:2025, except for public resources.

    From the lesson Security principles every builder applies

  25. What does least privilege mean for a nightly job that reads two tables?

    It gets SELECT on those two tables and nothing more, not every right on every table. Extra rights mean that a bug in the job, or a stolen copy of its password, can change or delete data the job never needed to touch.

    From the lesson Security principles every builder applies

  26. What is complete mediation, and why is a role copied into the session at sign-in not a check?

    Every access to every object is checked for authority, on every request, against the current record. A role copied at sign-in only remembers what was true then: a user moved to another team keeps the old rights until the session ends. Reading the current role costs one lookup per request.

    From the lesson Security principles every builder applies

  27. The policy service times out while a route checks a refund. What should the code do?

    Refuse and log, which is failing closed. A catch block that sets allowed to True turns an outage into a yes for every request, exactly when nobody is checking. A refusal is an inconvenience support hears about; a wrongful yes is a loss nobody hears about until the money is gone.

    From the lesson Security principles every builder applies

  28. What is defence in depth, with the lesson's example?

    Independent controls stacked so that one failure does not leave the asset unprotected. The router checks the caller's role, and the data layer, on its own, returns only invoices of the caller's tenant, so a new route that skips the role check still returns nothing to another tenant's user.

    From the lesson Security principles every builder applies

  29. What is separation of duties, and where does A03:2025 mention it?

    A change needs a second person before it ships. Among the signs of a weak software supply chain, A03:2025 lists a setup in which one person can write a change and push it to production with nobody else looking.

    From the lesson Security principles every builder applies

  30. How do you make a security principle reviewable in a pull request?

    Write it as a triple: the principle, the control that applies it, and a test that fails when the control is missing, such as "a route with no policy is refused" for deny by default. A later change that breaks the principle then fails in the suite instead of in production.

    From the lesson Security principles every builder applies

  31. What four questions frame a threat model?

    What are we working on? What can go wrong? What are we going to do about it? Did we do a good enough job? Ask them of one feature, in one session, while the design is still cheap to change, and keep the result as a small text file next to the code.

    From the lesson Threat modelling a feature in 30 minutes

  32. Which five kinds of element does a data-flow diagram have, and where do most findings sit?

    External entities (people and systems you do not run), processes (code you run), data stores, data flows, and trust boundaries where the level of trust changes. Most findings sit on the flows that cross a trust boundary, where data arrives from somewhere you do not control or leaves for it.

    From the lesson Threat modelling a feature in 30 minutes

  33. What three questions do you ask of every flow that crosses a trust boundary?

    Is the sender authenticated, is the data validated, is it encrypted? Write the model as data and a program can list the answers still missing. "Not needed" is a valid answer when it comes with a reason.

    From the lesson Threat modelling a feature in 30 minutes

  34. What do the six letters of STRIDE threaten?

    Spoofing threatens authentication, tampering integrity, repudiation non-repudiation, information disclosure confidentiality, denial of service availability, and elevation of privilege authorisation.

    From the lesson Threat modelling a feature in 30 minutes

  35. Which STRIDE letters apply to which kind of element?

    Spoofing and repudiation to external entities; all six to processes; tampering, information disclosure and denial of service to data stores and data flows. On the fest model this turned 13 elements into 39 questions, 15 of them for the 5 flows that cross a boundary.

    From the lesson Threat modelling a feature in 30 minutes

  36. What is an abuse case, and what does each one produce?

    A way of using a feature that its implementer did not expect, found by imagining a user whose only goal is to extract maximum value. Each answer becomes an invariant, a rule the data must keep whatever the requests say, with a test that tries to break it. A rule that only the page enforces is not enforced.

    From the lesson Threat modelling a feature in 30 minutes

  37. What are the four responses to a threat, and what is written beside each?

    Mitigate (lower the likelihood or the impact), eliminate (remove the feature that causes it), transfer (let a contract or a provider carry the consequences) and accept (keep the risk knowingly). Write the response next to the threat with an owner and a test.

    From the lesson Threat modelling a feature in 30 minutes

  38. When is a feature's threat model done, and when do you open it again?

    It is done when every crossing flow is answered, every threat has a response, an owner and a test, and the model is saved in the repository. Come back whenever the flow of data, the access control or another security control of the feature changes (A06:2025).

    From the lesson Threat modelling a feature in 30 minutes

  39. How does authentication differ from authorisation?

    Authentication establishes who is making the request, usually once per session. Authorisation decides whether that caller may do this one thing to this resource, on the server, for every request. Broken authorisation lets the real user do what they were never allowed to, which is what A01:2025 covers.

    From the lesson Authorisation: deny by default, enforce centrally

  40. What should a router do with a route that has no policy?

    Treat it as a no. The fixed router in the lesson checks its route table when the app starts and refuses to start while any route lacks a policy, so the gap is found in the build instead of in production. It also allows a request only when the policy returns exactly true.

    From the lesson Authorisation: deny by default, enforce centrally

  41. Why implement access control once, in a central layer, instead of a check at the top of each handler?

    A check in every handler works until the first handler written without it, and nothing shows which one. Declaring the policy beside the route lets the router see that it is missing. OWASP advises implementing access control once and reusing it, in middleware or a filter.

    From the lesson Authorisation: deny by default, enforce centrally

  42. How do RBAC, ABAC and ReBAC differ?

    RBAC reads the caller's role (support may issue refunds) and cannot say which record. ABAC reads attributes of the user and the record, such as a draft status or a refund size. ReBAC follows links between people and records, such as membership of the team that owns a project. A sound start is roles plus ownership, with attributes added when roles multiply.

    From the lesson Authorisation: deny by default, enforce centrally

  43. When does an application answer a refused request with 401, 403 or 404?

    401, with a WWW-Authenticate header, when no valid credentials came, because signing in may change the answer. 403 when the user is signed in and may know the resource exists. 404 when its existence is itself private, such as another customer's invoice number. A route with no policy gets 403 and an alert. Decide once, in the router.

    From the lesson Authorisation: deny by default, enforce centrally

  44. What is an authorisation matrix test, and what extra check keeps it honest?

    Every role against every route, with the answer each cell should get, run against the application as each role. A matrix that only reads its own rows never sees a new route, so the test also reads the app's route table and fails when a route has no row.

    From the lesson Authorisation: deny by default, enforce centrally

  45. Why must the server not take the caller's role from a cookie or a header?

    The client wrote it. Editing a cookie to role=admin, or a script sending X-User-Role: admin, passes a weak check. The fixed check takes only the session id from the request and looks the role up in the server's own records.

    From the lesson Authorisation: deny by default, enforce centrally

  46. What three things together make an insecure direct object reference?

    An object, a reference to it that the user controls (in the path, query string, form, header or file name), and a missing object-level authorisation check. Ravi changing /notes/2 to /notes/5 reads Asha's note with his own customer rights. It is CWE-639 and API1 (BOLA) in the API Security Top 10.

    From the lesson IDOR and object-level authorisation (BOLA)

  47. What is the surest fix for IDOR, and what does it look like in SQL?

    Put the caller into the query: WHERE id = ? AND owner_id = ?, with the owner taken from the session. Another user's note is then simply not found, and no later line of code can leak what was never loaded. In a multi-tenant app the tenant belongs in the condition too.

    From the lesson IDOR and object-level authorisation (BOLA)

  48. Name the three ways to enforce object-level authorisation, best first.

    Scope the query with the owner or tenant; load the record and pass it to one shared function such as can(user, 'note:read', note) that every route calls, for rules richer than ownership; or enforce below the routes with a repository filter or database row-level security. In PostgreSQL the table's owner bypasses row security unless FORCE ROW LEVEL SECURITY is set.

    From the lesson IDOR and object-level authorisation (BOLA)

  49. Do random, hard-to-guess identifiers fix IDOR?

    No. They make guessing harder, but ids leak through shared links, logs, Referer headers, other API responses and browser history. They are defence in depth beside the check, never instead of it. A deliberate capability link needs a narrow scope, an expiry and a way to revoke it.

    From the lesson IDOR and object-level authorisation (BOLA)

  50. Where do object-level checks usually go missing after the read route is fixed?

    On update, delete, bulk and nested routes, exports and downloads, and jobs that take an id from a queue. A bulk read that compares only ids[0] returns every id that exists, and a nested route such as /orgs/1/projects/2 must also compare the project's organisation with the one in the path.

    From the lesson IDOR and object-level authorisation (BOLA)

  51. Why should a request for "not yours" and one for "not there" be answered alike?

    A 403 for another user's note and a 404 for a missing one lets a caller sort which ids exist by comparing answers. A scoped query returns 404 for both on its own. Make the two alike in status, body and, as far as you can, timing, and alert on one account asking for dozens of ids it cannot open.

    From the lesson IDOR and object-level authorisation (BOLA)

  52. What kind of test catches IDOR before release?

    A two-user test: create two users with their own records, sign in as one and try the other's references on every operation that takes one (read, update, delete, export, admin). Generate the tests from the table of routes, and a route added tomorrow is tried the day it appears.

    From the lesson IDOR and object-level authorisation (BOLA)

  53. Why does an admin function need its policy attached to the function and not to one path?

    The same function can be mounted at several addresses. A guard on /admin/users/export left /api/users/export open, and Asha got every user's record. Attach the policy to the function or its route group so that every path, including the next one someone adds, inherits it. This is BFLA, API5:2023.

    From the lesson Function- and property-level access control

  54. Why are a hidden Admin menu, an unlisted admin address and an isAdmin flag in the browser not access controls?

    Each changes only what a client shows or knows, and every client is in the user's hands. A single-page app ships its route table to every visitor, and a flag in local storage can be switched on. The functions behind need a server-side policy; the address may be public.

    From the lesson Function- and property-level access control

  55. Why must a policy run on the route the router matched and not on the raw request string?

    Routers accept more than a guard's list: Express treats /Admin/users and a trailing slash as the same route by default, runs GET routes for HEAD, and method-override can turn a POST into a DELETE. In the lesson only the exact string was refused; a policy on the matched route refused all four requests.

    From the lesson Function- and property-level access control

  56. What is broken object property level authorization (API3:2023), and what is the fix for responses?

    A permitted request that gets back, or may set, fields it should not: serialising the database row sends password hashes, reset tokens and internal flags. Build each response from an output allowlist of the fields this caller may see. ASVS 5.0.0 asks for field-level checks in 8.2.3 and for returning only the fields needed in 15.3.1.

    From the lesson Function- and property-level access control

  57. What happens to a response built from a denylist when a migration adds a column?

    The new column is sent by default. In the lesson the raw row sent Kiran all 10 of Asha's fields, the denylist 7, and each sent one more after the migration, while the allowlist sent exactly 2 (id and name) before and after.

    From the lesson Function- and property-level access control

  58. What extra check do related records requested with ?include= or a GraphQL query need?

    Each included object is another response and needs both checks again: may this caller include this relation at all, and which of its fields may they see. A serialiser that projects the invoice but copies invoice.customer whole leaks every field of the customer. Refuse a forbidden include like an unknown one, with 400.

    From the lesson Function- and property-level access control

  59. What is a contract test for responses, and why write the contract as an allowlist?

    It walks every key of a response, at every depth, per role and route, and fails on any path the role's contract does not allow. With an allowlist contract a new field fails the test until someone decides who may see it; the lesson's test found customer.passwordHash and customer.resetToken, and customer.dateOfBirth after a migration.

    From the lesson Function- and property-level access control

  60. How does a file name from a request leave its folder?

    A file name is a path: .. steps up a folder, and an absolute name starts somewhere else, so joining a base and a requested name can resolve outside the base. MITRE files this as CWE-22 (CWE-23 for the relative climb, CWE-36 for the absolute path), and OWASP maps it to A01:2025.

    From the lesson Path traversal and safe file paths

  61. In what order do the checks of a safe file route run?

    Refuse a NUL byte; resolve the name against the base folder; check where it landed, segment by segment; follow symbolic links to the real path and check again; only then open exactly that real path. Archives get the same check for every member before anything is written.

    From the lesson Path traversal and safe file paths

  62. Why does a string-prefix test fail as a containment check, and what does the safe check do?

    A neighbour such as /srv/files/public-old starts with the same characters as /srv/files/public. Resolve first, then compare whole segments: in Node, path.relative(base, full) for an inside path never starts with a .. segment and is never absolute or empty. A file named ..notes.txt is legitimate, so test the segment, not the characters.

    From the lesson Path traversal and safe file paths

  63. Why decode a file name exactly once, and why refuse a NUL byte yourself?

    A second decode after the check turns the checked name into a different one. A C string ends at the first zero byte, so a check and a file function can disagree about which file is meant; Node and Python raise errors, but your route should refuse first with the same 404 as any refusal. Never repair a name by deleting ../, because removal can join characters into a new sequence.

    From the lesson Path traversal and safe file paths

  64. Why is a check of the name alone not enough, and what closes the gap?

    A symbolic link inside the folder can point anywhere, so latest/keys.txt can be files/private/keys.txt. Compute the real path, which resolves . and .. and every link (fs.realpathSync in Node), check that it is inside, and open exactly that path. Operating-system permissions and Node's Permission Model are layers, not the check.

    From the lesson Path traversal and safe file paths

  65. What is Zip Slip, and how should an archive be unpacked?

    A member named ../escape.txt written by a careless loop lands outside the destination. Check the resolved path of every member before writing any and refuse the whole archive if one fails; a member-by-member refusal leaves half the archive on disk. ASVS 5.0.0 5.3.3 asks to ignore user-supplied path information, for example by storing members under names the server picks.

    From the lesson Path traversal and safe file paths

  66. What is the strongest defence against path traversal?

    Take no path from the user. The request names a record by id, the server finds the file it stored under a name it generated, and the display name goes only into Content-Disposition (ASVS 5.0.0 5.3.2 and 5.4.1). A path where an id is expected gets 404 because it is not an id.

    From the lesson Path traversal and safe file paths

  67. What makes a route an open redirect, and why does it matter although it breaks into nothing on its own?

    It sends the browser on to an address taken from the request (?next=, ?return_to=, /out?url=) without checking where it leads: CWE-601, A01:2025. Its harm is borrowed trust, since a link on your domain is believed by people and mail filters. RFC 9700 forbids OAuth clients and servers to expose open redirectors, because they can carry codes and tokens away.

    From the lesson Open redirects and safe URL handling

  68. Why does a check for a leading slash let //other.example/ and /\other.example/ through?

    The browser's URL parser (the WHATWG standard) reads two slashes as the start of a host and a backslash as a slash, and it removes tabs and newlines wherever they are. The check asked about the string; the browser answered about the URL. Compare what the parser makes of the value, never the value as text.

    From the lesson Open redirects and safe URL handling

  69. What is a parser differential, using the redirect example?

    Two pieces of code that read one input differently. Python's urlsplit reads /\other.example/ as a path with no host, so a check built on it calls the value local, while the browser sends the user to other.example. A check can be trusted only as far as it agrees with the code that acts on its answer.

    From the lesson Open redirects and safe URL handling

  70. How does a safe return-URL check work?

    Parse with new URL(next, BASE), where BASE is a constant of the app and never the Host header; compare whole origins (scheme, host and port); refuse a value with a user name; and redirect to url.href, the URL you checked, not a piece of it. Send every refusal to the same safe page, and log the value.

    From the lesson Open redirects and safe URL handling

  71. Why redirect to url.href and not to url.pathname after the check?

    /.//other.example is a path on the site, but its pathname is //other.example. Sent as pathname it becomes a protocol-relative URL that leaves the site, while url.href (https://app.example//other.example) stays. Redirect to the URL you validated, not to a changed copy of it.

    From the lesson Open redirects and safe URL handling

  72. What is the strongest design for redirects, and what do ASVS 5.0.0 3.7.2 and 3.7.3 add for links that leave the site?

    Let the request name a destination (next=orders) and look the path up on the server, so no address travels. For links to other sites, 3.7.2 asks for an allowlist of exact hosts compared after parsing, never a substring or suffix, and 3.7.3 (level 3) asks for a notice page for addresses the app does not control.

    From the lesson Open redirects and safe URL handling

  73. How should a link built from user data open another site?

    Keep only the schemes you need (https, http, mailto), read from the parsed URL, and add rel="noopener noreferrer". noopener leaves window.opener null, because the linked page could otherwise change your page's location (CWE-1022); noreferrer keeps the Referer off. A javascript: URL assigned to location or clicked runs script in your page.

    From the lesson Open redirects and safe URL handling

  74. What is CSRF, and why does the browser send the cookie?

    A page on another site makes the signed-in user's browser send a request to your app. The browser adds the session cookie because of where the request goes, not which page started it, so a server that trusts the cookie alone acts on a request its owner never meant (CWE-352, mapped to A01 Broken Access Control). The same-origin policy blocks the read, not the request.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  75. Which cross-site requests reach your server without a preflight?

    Simple requests: a GET, HEAD or POST that sets no header beyond a short safe list and, for a POST, uses a form content type (text/plain, multipart/form-data or application/x-www-form-urlencoded). A JSON body, a custom header or a PUT starts a preflight. So "we send no CORS headers" protects reads, not form posts or text/plain fetches.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  76. What does SameSite not protect you from?

    A sibling subdomain (SameSite is scoped to the registrable domain, so a user-content or forgotten subdomain can start requests that carry the cookie); a top-level GET under Lax, so never change state on GET; and browsers with another default for a cookie with no attribute. Set the attribute on every session cookie.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  77. How does a synchroniser token work?

    The server stores a random value in the user's session and puts it in each page, in a hidden field or a meta tag the page's script reads. The request sends it back in a field or header and the server compares it with the stored copy. Another site cannot read it. It never goes in a URL, and one per session is usual.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  78. How does a signed double-submit token work, and why is the naive double submit weak?

    The token is a MAC over the session id and a random nonce, followed by the nonce, in a cookie the page's script can read (no HttpOnly) and copied into a header. The server recomputes the MAC from this request's session id and the nonce and compares in constant time. Naive double submit only checks that cookie and header are equal, and a sibling subdomain can plant the same pair.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  79. How should a CSRF token be compared, and what must you remember in Node?

    With a constant-time function: hmac.compare_digest in Python, crypto.timingSafeEqual in Node. The Node function throws when the buffers differ in length, so give it buffers of equal length. A plain comparison returns at the first character that differs, so its running time can reveal how much of a guess was correct.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  80. What header check refuses cross-site requests, and what does it not prove?

    Safe methods pass. For the rest, only the Sec-Fetch-Site values same-origin and none are accepted, and every other value is refused (same-site too, unless you trust every sibling host). If it is missing, Origin must equal your own origin exactly. A missing or null value is no evidence, so the token decides. The headers describe what a browser saw, never who the caller is.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  81. Which two requests escape most CSRF work, and what fixes each?

    The sign-in form, where login CSRF signs the visitor into an account the other site controls, needs a token from a pre-session that is destroyed, with a new session id, after sign-in. The WebSocket handshake is a GET that carries cookies and an Origin nothing checks (cross-site WebSocket hijacking): check Origin against your own exact origins before the upgrade (ASVS 5.0.0 4.4.2) and add a token.

    From the lesson CSRF: tokens, SameSite and Fetch Metadata

  82. What does CORS change, and what did it never decide?

    It lets a server relax the same-origin policy for the origins it names, so a page there may read the response. It never decided who may send a request: a simple request reaches the server whatever the headers say, and curl, other servers and mobile apps ignore CORS. It is not access control, and every allowed origin is a party you trust.

    From the lesson CORS: what it protects and how it goes wrong

  83. The console says a request was blocked by CORS policy. Did the request fail?

    Not necessarily. For a simple request the server ran its code, and the response was withheld from the script. Look in the server's log before you conclude that the API did nothing.

    From the lesson CORS: what it protects and how it goes wrong

  84. Which headers does a preflight use, and what must the server answer?

    The browser sends an OPTIONS request, without cookies, with Origin, Access-Control-Request-Method and Access-Control-Request-Headers. The server answers with Access-Control-Allow-Origin, Allow-Methods and Allow-Headers (and Max-Age); the real request follows only if they permit it. A route that demands a session on OPTIONS refuses every preflight.

    From the lesson CORS: what it protects and how it goes wrong

  85. How should a server decide that an Origin is its own?

    Compare the whole Origin string with a list of whole origins and send back that origin exactly. A prefix, suffix, substring, unescaped regex dot, host-only comparison or reflected Origin each accepts something you did not mean, such as eshop.example, plain http or another port. A subdomain wildcard is as safe as your weakest subdomain.

    From the lesson CORS: what it protects and how it goes wrong

  86. What changes when a CORS request carries the user's cookie?

    The answer must name one origin, with no * in Allow-Origin, Allow-Methods, Allow-Headers or Expose-Headers, and Access-Control-Allow-Credentials must be exactly true. Whether the cookie goes at all also depends on SameSite and the browser's third-party cookie policy. Reflecting Origin makes the error vanish by trusting every site.

    From the lesson CORS: what it protects and how it goes wrong

  87. Why is Access-Control-Allow-Origin: null never right, and what does Vary: Origin do?

    The null origin identifies no site (sandboxed frames, files from disk, some form posts), and any site can make a document with a null origin, so allowing it lets every site in. A response that names one origin depends on the request's Origin; Vary: Origin makes a shared cache keep one copy per origin instead of handing the first origin's answer to the next.

    From the lesson CORS: what it protects and how it goes wrong

  88. Which designs avoid CORS risk, and what is the rule for a wildcard?

    Put the API under the page's own origin with a reverse proxy, or use a backend for the front end so the browser never holds the API token. Allow * only for public data with no cookie (ASVS 3.4.2). Use postMessage only when every handler discards messages from untrusted origins (ASVS 3.5.5). Otherwise keep an exact list that someone reviews.

    From the lesson CORS: what it protects and how it goes wrong

  89. What is SSRF, and which features are the usual places for it?

    Server-side request forgery: your server fetches an address that a user chose, from inside your network, where services that ask for no login trust its position. Link previews, webhooks, imports from a URL, image proxies, PDF makers and sign-in discovery documents are typical. It is CWE-918 and API7:2023, and OWASP folded it into A01 Broken Access Control in 2025.

    From the lesson SSRF and safe outbound requests

  90. If a fetch feature never shows the response, is it safe?

    No. The status code and the time a request took tell a user about the network behind your server. Do not return the raw body or headers of the upstream response either; a preview needs a title, so return a title.

    From the lesson SSRF and safe outbound requests

  91. Why must a URL guard judge the parsed host, and what pitfall remains?

    One address has many spellings (decimal, hex, octal, fewer than four parts, percent-encoded digits, IPv6 mapped forms), and the client decides with its own parser. Parse once with the parser the client uses and build the request from the parts you judged. When two parsers could disagree about a URL, refuse it.

    From the lesson SSRF and safe outbound requests

  92. Why is "not private" a poor address test?

    Shared carrier-grade NAT space (100.64.0.1) is neither private nor global, multicast 224.0.0.1 is global, and the NAT64 form of 127.0.0.1 is global too. Take out the IPv4 address inside any IPv6 form, then require an address that is global and neither multicast nor reserved. Prefer a list of allowed hosts, ports and schemes wherever the destinations are known.

    From the lesson SSRF and safe outbound requests

  93. Which addresses does OWASP's minimum refusal list name, and why the metadata address?

    Loopback, 0.0.0.0/8, the three private ranges of RFC 1918, 169.254.169.254 (the metadata address, in the IPv4 link-local range), IPv6 unique local fc00::/7 and link-local fe80::/10, and multicast. Cloud platforms serve instance metadata on that address, so a fetcher in the cloud must never reach it. The sheet calls a list of refused addresses bypass-prone.

    From the lesson SSRF and safe outbound requests

  94. What is DNS rebinding, and how does a fetcher defeat it?

    The owner of a name gives it a very short lifetime and answers differently on each lookup, so a guard that judges one answer and lets the client resolve again is fooled. Resolve once, keep every A and AAAA answer, judge all of them, and connect to the address you judged, while the original name still goes in the Host header and the TLS check.

    From the lesson SSRF and safe outbound requests

  95. How should a fetcher treat redirects, schemes and ports?

    A redirect is a new URL: follow it yourself, judge it from the start and stop after a few hops (ASVS 5.0.0 15.3.2). Allow http and https only, ports 80 and 443 unless a feature documents another, limit the size and time of the body, and never forward the caller's cookies.

    From the lesson SSRF and safe outbound requests

  96. What remains when the guard in the code has a mistake?

    Egress controls: a fetcher service that reaches the internet but nothing inside, an egress proxy as the only way out, or network rules that drop connections to internal ranges and the metadata address. ASVS 5.0.0 13.2.4 and 13.2.5 ask for an allowlist of the systems the app may contact.

    From the lesson SSRF and safe outbound requests

  97. What is a typical security misconfiguration, and how does a secure default differ from a secure configuration?

    A setting that kept the value it shipped with: debug mode left on, the install guide's admin login, directory listings, TRACE, open API docs or monitoring, version banners, a .git folder or backups on the server. A secure default is safe if nobody touches it, so a forgotten step costs a feature; a setting whose safe value must be switched on will be missing somewhere sooner or later.

    From the lesson Secure defaults: hardening apps and environments

  98. Name two documented defaults that reveal the stack, and the switch for each.

    nginx puts its version in the Server header and on error pages until server_tokens is switched off, and Express adds X-Powered-By: Express until the app calls app.disable('x-powered-by'). Neither is a bug; each is a value someone must change in every deployment.

    From the lesson Secure defaults: hardening apps and environments

  99. How should an error handler decide whether to show a stack trace?

    Show detail only when development is asked for explicitly, with two values that only a developer's machine sets. A test such as NODE_ENV !== 'production' treats a missing value, a typo like prod and every new environment as development. Send a short message with a reference to the server's log, and keep a leak check in the tests.

    From the lesson Secure defaults: hardening apps and environments

  100. How does a hardening checklist stay true over time?

    It runs as rules on the configuration (policy as code): each rule reads one setting, names its requirement and says what to change. Run the rules on every config change before merge, on each environment's final config before deploy, and on a schedule against the live system, which shows a value changed by hand the next morning.

    From the lesson Secure defaults: hardening apps and environments

  101. How may development, staging and production differ?

    Staging and production only in host names and references to their own secrets, and development only by a written list of exceptions. A setting tested in staging protects production only if production has it too: SameSite=None in production against Lax in staging means forms from other sites carry the cookie only in production.

    From the lesson Secure defaults: hardening apps and environments

  102. Where do credentials belong, and what happens to a key in a front-end variable?

    In a secret store, not in the config, the code or a bundle (ASVS 5.0.0 13.3.1 asks for a secrets manager at level 2). Anything a browser receives is public: Vite writes every variable named VITE_ into client code, so a VITE_PAYMENT_KEY reaches every visitor. Environment variables beat files in the repository but still leak into child processes and logs (CWE-526).

    From the lesson Secure defaults: hardening apps and environments

  103. What is an exposure probe, and why run them after every deploy?

    A request for something that must not be there, such as /.git/config, a debug page, an uploads listing, TRACE, an environment file or a database backup, expecting 404 (or 401 or 403 for docs and monitoring). It takes milliseconds and turns ASVS section 13.4 into a smoke test; a deployment hardened from memory failed eight of the lesson's nine probes.

    From the lesson Secure defaults: hardening apps and environments

  104. Who obeys a security header, and who ignores it?

    Only the browser that receives the response: the header asks it to treat the response a certain way for its user. A script, a mobile app's HTTP client or another server reads no header and obeys none, so headers add a layer for users in browsers and never replace a server-side check.

    From the lesson HTTP security headers: a baseline that holds

  105. Which seven headers make up the lesson's baseline?

    Strict-Transport-Security with max-age=31536000 and includeSubDomains; nosniff in X-Content-Type-Options; a Content-Security-Policy with frame-ancestors 'none', object-src 'none' and base-uri 'none'; strict-origin-when-cross-origin as the Referrer-Policy; same-origin for Cross-Origin-Opener-Policy; same-site for Cross-Origin-Resource-Policy; and Cache-Control: no-store on personal data.

    From the lesson HTTP security headers: a baseline that holds

  106. Does one header list fit every response?

    No. Pages need framing and opener rules, APIs with personal data need no-store, downloads need Content-Disposition: attachment, and everything needs HSTS and nosniff. OWASP's cheat sheet notes that most of these headers matter only for responses a browser renders or loads.

    From the lesson HTTP security headers: a baseline that holds

  107. How do you roll out HSTS safely?

    Check every subdomain first, then raise max-age in stages starting at 300 seconds, waiting out each stage's full value, up to one year with includeSubDomains (ASVS 5.0.0 3.4.1). Browsers ignore the header over plain HTTP, and only max-age=0 over HTTPS switches it off, so a year on day one can lock users out of a subdomain that still needs HTTP.

    From the lesson HTTP security headers: a baseline that holds

  108. What does the preload list add to HSTS, and what is the current advice?

    It is built into browsers, so it protects even the first visit. Its maintainers now recommend HSTS and do not recommend preloading, since current browsers already upgrade many plain visits and getting off the list takes browser updates and months. Add preload only after deciding to preload, never by default.

    From the lesson HTTP security headers: a baseline that holds

  109. Which old headers should go, and what should X-XSS-Protection be?

    X-XSS-Protection should be 0 or absent, because its filter can create XSS. Remove Expect-CT and Public-Key-Pins, and do not send X-Frame-Options with ALLOW-FROM: browsers drop the entire header when they see that value, so use frame-ancestors instead. Drop version banners in Server and X-Powered-By too.

    From the lesson HTTP security headers: a baseline that holds

  110. Why do error pages and downloads lose headers in nginx, and what is the fix?

    add_header without the always parameter adds a header only when the status is a success (200, 201, 204 or 206), a redirect (301, 302, 303, 307 or 308) or 304, so 404 and 500 pages go without; and a location block with its own add_header inherits none of the server block's, unless add_header_inherit merge (nginx 1.29.3 and later). Put always on every line and test one response of each kind after every deploy.

    From the lesson HTTP security headers: a baseline that holds

  111. What does each of Secure, HttpOnly, SameSite and no Domain stop, and what does each leave open?

    Secure stops the cookie going over plain HTTP (other ports and sibling hosts remain). HttpOnly stops page scripts reading it through document.cookie (requests a script sends still carry it). SameSite=Lax or Strict stops it riding on requests that other sites start, except that Lax still sends it on a top-level GET navigation (own-site and sibling requests remain too). No Domain keeps it host-only (cookies other hosts set for the parent domain still arrive). Path is not a security measure.

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  112. Why set SameSite explicitly when browsers have a default?

    The defaults differ: Chrome since 80 and Edge since 86 treat a cookie without SameSite as Lax, Firefox only behind a preference, Safari not at all. Even Chrome's default is softer than an explicit Lax, because a cookie under the default still goes with a cross-site POST in the first two minutes. OWASP asks for it on every session cookie, Strict where you can and Lax otherwise.

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  113. Which attributes suit a session cookie, a CSRF-token cookie, a preference cookie and an embedded widget's cookie?

    Session: HttpOnly and SameSite=Lax, with no lifetime of its own. CSRF token: SameSite=Strict and no HttpOnly, because the page's script reads it. Preference: readable, Lax, a year of Max-Age, nothing that identifies anyone. Widget: SameSite=None with Secure, and Partitioned. All use the __Host- prefix unless meant to be shared across hosts, and hold opaque identifiers, not data.

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  114. What does the __Host- cookie prefix require, and what attack does it stop?

    The browser enforces that the cookie is Secure, has Path=/ and no Domain, so a sibling subdomain cannot set one for the parent domain. That stops cookie tossing, where a sibling plants a cookie with your session's name and a longer path, which browsers list first. Also read only the __Host- name and refuse a request that repeats it. The __Secure- prefix only demands Secure.

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  115. What does the Partitioned attribute do for a widget embedded on other sites?

    It gives the third-party cookie (SameSite=None, Secure, preferably with __Host-) a separate jar for each top-level site. A chat widget then signs the user in once per shop, and nobody can follow them from site to site through it. MDN lists support in Chrome and Edge since 114, Firefox since 141 and Safari since 26.2.

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  116. Which cookies would a browser silently refuse to store?

    One over 4,096 bytes of name and value (RFC 6265bis), a __Host- cookie with a Domain or with a Path other than /, and SameSite=None without Secure (refused by Chrome, Edge and Firefox).

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  117. How do you read several Set-Cookie headers in server code, and why not split a joined string?

    Use getSetCookie(), which returns each header as sent. get('set-cookie') joins the headers with a comma, and the Expires date holds a comma, so splitting on commas cuts a date in half (RFC 6265 asks servers not to fold Set-Cookie headers). Audit each header against the rules of its purpose, on every kind of response that sets one.

    From the lesson Cookies done right: Secure, HttpOnly, SameSite

  118. What is clickjacking, and what does it need from your site?

    Another site shows your page in a frame, lined up under something harmless, so the user's genuine click acts on your page (CWE-1021). It needs only that your page may be framed. The server never sees that the click came through someone else's page, so the defence belongs in the response.

    From the lesson Clickjacking and framing controls

  119. How does the browser read frame-ancestors and X-Frame-Options together?

    An enforced frame-ancestors header checks every ancestor, parent up to the top, and overrides X-Frame-Options. It is ignored in a meta element, does not fall back to default-src, and a report-only policy decides nothing. X-Frame-Options has only DENY and SAMEORIGIN; a lone unknown value such as ALLOW-FROM counts as no header, so the page fails open.

    From the lesson Clickjacking and framing controls

  120. Which pages should refuse framing, and what is the default?

    Every page where a click or a few keystrokes does something that matters: paying, deleting, changing an email or password, an OAuth consent screen, signing in. Make "no page may be framed" the default, with frame-ancestors on every response (ASVS 5.0.0 3.4.6), and configure the few embeddable pages as exceptions.

    From the lesson Clickjacking and framing controls

  121. How do you let named partners embed a page safely?

    Serve the embeddable part from an origin of its own, keep frame-ancestors 'none' for the rest of the app, list partners by origin, and keep what the embedded page can do small. https://*.example.com does not match example.com itself, a bare scheme such as https: or * allows the whole web, and X-Frame-Options cannot list several origins.

    From the lesson Clickjacking and framing controls

  122. How does the sandbox attribute protect a page that embeds someone else's frame?

    With no tokens it applies every restriction: no scripts, forms, pop-ups or navigation of your page, and an origin of its own. Each token gives one power back, so grant the fewest the content needs. allow-scripts together with allow-same-origin lets the framed document remove its own sandbox, so never use that pair for content served from your own origin.

    From the lesson Clickjacking and framing controls

  123. Why are frame-busting scripts, SameSite cookies and confirmation dialogs not the defence?

    A framing page can switch scripts off in the frame with sandbox, so the buster never runs. SameSite does not cover same-site pages such as a sibling subdomain, or actions that need no login (MDN calls it a partial mitigation). Some sandboxed frames suppress dialogs. The defence is the header on every response, asserted by a test.

    From the lesson Clickjacking and framing controls

  124. What does a shared cache use to pick a stored response, and what protects a personal page?

    Its key: at minimum the request method and URL, which says nothing about the user. A session cookie does not make a response private, since Set-Cookie does not stop caching, so only the origin's Cache-Control decides whether a personal page may be kept.

    From the lesson Caching safely: cache keys, Vary and deception

  125. What do public, private, no-cache and no-store mean for a shared cache?

    public: may store, even for a request with Authorization. private: must not store, though the browser may. no-cache: may store but must revalidate before every reuse, so it does not mean "do not cache". no-store: must not store any part of it. s-maxage replaces max-age for shared caches.

    From the lesson Caching safely: cache keys, Vary and deception

  126. Which Cache-Control fits versioned files, shared pages, a user's own pages and sensitive responses?

    public with a year of max-age and immutable for versioned files; public and short for shared pages that change; private, no-cache for a user's own non-sensitive pages; no-store for everything sensitive and for any response you are unsure about (ASVS 5.0.0 14.3.2). no-store deletes nothing a cache already holds, so a policy change also needs a purge.

    From the lesson Caching safely: cache keys, Vary and deception

  127. Which three ways of answering an account page leaked it to the next user in the lesson's model?

    max-age=60 with a Set-Cookie; no Cache-Control at all, because a 200 with Last-Modified can get heuristic freshness, typically a tenth of the time since that date; and public on a response to a request with Authorization, which undoes the rule that protects such requests (RFC 9111 section 3.5).

    From the lesson Caching safely: cache keys, Vary and deception

  128. What does Vary do, and what does varying on too much cost?

    Vary lists the request headers that changed the answer, and a stored response is reused only for a request that sends the same values (Vary: * matches no request). Vary on exactly the headers the response depends on and normalise them at the edge; adding User-Agent took the lesson's cache from 8 keys to 309 and its hit ratio down to 74.2 %. Vary: Cookie is not an access rule.

    From the lesson Caching safely: cache keys, Vary and deception

  129. What is cache poisoning through an unkeyed input, and how do you prevent it?

    An input changes the response but not the cache key, a common one being X-Forwarded-Host used to build absolute URLs, so one odd request stores a harmful page for everyone with that key (RFC 9111 section 7.1). Build URLs from configuration, drop forwarded headers your own proxy did not write, never echo unkeyed request data into cacheable output, and test with a canary on a test-only query string.

    From the lesson Caching safely: cache keys, Vary and deception

  130. What is web cache deception, and what stops it?

    A cache stores anything that looks like a file (.css, .js), and a lenient route answers /account/profile/avatar.css with the signed-in user's page, so it is stored and then served to anyone who asks. Any one of three fixes breaks it: an edge that obeys the origin's no-store, strict routes that answer 404 for paths that do not exist, and caching only the expected content type (ASVS 5.0.0 14.2.5).

    From the lesson Caching safely: cache keys, Vary and deception

  131. What must an application cache, such as Redis or lru_cache, have in its key?

    The tenant and every attribute that decides access, with the permission check done on every request before any cached value is read. Caching the finished answer of a function that also checks permission runs the check only for the first caller.

    From the lesson Caching safely: cache keys, Vary and deception

  132. Why must the link in a password-reset email not be built from the Host header?

    Host is a value the client chose, so a request naming other.example puts that host, with the reset token, into the email the real user receives. Build every link, redirect and email from the origin in configuration, accept only the hosts you serve (the idea of Django's ALLOWED_HOSTS) and answer others with 400.

    From the lesson Request handling: Host, headers and smuggling

  133. How do you find the real client address behind proxies?

    Begin at the connection and read X-Forwarded-For (or Forwarded, RFC 7239) from right to left, skipping your own trusted proxies (known by their address ranges) and reading all lines as one list. The leftmost entry is the client's own text, and a hop count fails when a request reaches the balancer directly. Believe X-Forwarded-Host and X-Forwarded-Proto the same way (ASVS 5.0.0 4.1.3 and 15.3.4).

    From the lesson Request handling: Host, headers and smuggling

  134. What goes wrong when an edge rule and the app read a request target differently?

    A path the edge reads as public the app reads as admin: /Admin/users (the router ignores case), %2e%2e segments and backslashes (the URL standard resolves them), //admin/users (read as a host by new URL(target, base)). Turn each target into one canonical form once, refuse any that parsing would change with 400, and decide access in the app on the path it routes on.

    From the lesson Request handling: Host, headers and smuggling

  135. How should repeated parameters, header names with underscores and percent-escapes be handled?

    Refuse a repeated key where one value is expected, since get() returns the first and Object.fromEntries() the last. Drop or refuse header names with underscores, because CGI turns X-Forwarded-For and X_Forwarded_For into the same variable. Decode percent-escapes once, in one place, and refuse what still holds an escape for a dot, slash or backslash (%252e).

    From the lesson Request handling: Host, headers and smuggling

  136. What is request smuggling, and what stops it?

    Hiding one request inside another because two hops find different ends for the same HTTP/1.1 message, for example one trusts Content-Length and the next Transfer-Encoding: chunked (RFC 9112 section 6.3 says Transfer-Encoding wins). Refuse a message with both headers or two different lengths and close the connection, use one strict maintained parser at the edge with the same rules on every hop, and validate HTTP/2 fields before translating them. It is CWE-444.

    From the lesson Request handling: Host, headers and smuggling

  137. What does Node's HTTP server refuse by default, and what is left to the application?

    It refuses malformed messages (400, while insecureHTTPParser is off), a missing Host, and headers over 16 KiB (431): 9 of the lesson's 15 raw requests. Of the 6 that reached the handler the app had to refuse 4, such as two Host lines (Node keeps the first; RFC 9112 asks for 400) and a path inside Host. Do not switch on a lenient parser for one broken client.

    From the lesson Request handling: Host, headers and smuggling

  138. What is XXE, and what can a DOCTYPE make a parser do?

    A DOCTYPE may declare entities. An internal entity pastes text and can multiply it many times (entity expansion, CWE-776); an external entity names a file or URL that the parser opens or fetches and pastes into the data (XXE, CWE-611); an external DTD or parameter entities fetch more declarations. The results: files read from the server, requests made by the server, and a parser out of memory or time. OWASP counts these under A02 Security Misconfiguration, since they are parser settings.

    From the lesson XML parsing safely: XXE and entity expansion

  139. How do Python's standard XML parsers handle external entities by default?

    They sit on Expat, which opens no files and makes no connections itself, and SAX stopped processing general external entities by default in 3.7.1. In the lesson's test only SAX with feature_external_ges switched on read the canary file; ElementTree refused the entity, and minidom, pulldom and default SAX left it out silently. Expat versions below 2.7.2 may be open to entity expansion.

    From the lesson XML parsing safely: XXE and entity expansion

  140. What is the safest rule for data-only XML, and where do you enforce it?

    Refuse any document with a DOCTYPE, inside the parser (in Python a target whose doctype() raises), where every encoding is already decoded. Searching the bytes for <!DOCTYPE misses a UTF-16 document the parser reads fine. Prove it with a canary-file test, and keep size limits, also after decompression, as a second layer. ASVS 5.0.0 1.5.1 asks for a restrictive parser configuration.

    From the lesson XML parsing safely: XXE and entity expansion

  141. Which inputs are XML underneath?

    SVG images, DOCX, XLSX and PPTX packages (XML parts in a ZIP), Atom and RSS feeds, sitemaps, and SAML responses. Check every XML part by the same rules. SVG 1.1 files often carry a public DOCTYPE, which can be allowed if it is never fetched, while any internal subset, entity declaration or other DOCTYPE is refused. Leave XInclude and XSLT off.

    From the lesson XML parsing safely: XXE and entity expansion

  142. What matches "refuse the DTD" in other stacks and libraries?

    Java JAXP: set the feature disallow-doctype-decl. .NET: XmlReader prohibits DTDs by default. libxml2 2.9 and later: never pass XML_PARSE_NOENT or XML_PARSE_DTDLOAD for untrusted input. lxml stopped expanding external entities in 5.0 and does so again with resolve_entities=True. For Python, OWASP recommends defusedxml.

    From the lesson XML parsing safely: XXE and entity expansion

  143. When both ends are yours, why prefer JSON to XML?

    JSON has no DOCTYPE, entities or references to other files, so there is nothing to switch off. It still needs limits: a malicious JSON string may consume considerable CPU and memory, so limit the size you parse and validate the result.

    From the lesson XML parsing safely: XXE and entity expansion

  144. What does A03:2025 Software Supply Chain Failures cover, and why does testing data understate it?

    Failures or compromises anywhere in the chain that builds, ships or updates your software, whether the cause is a flawed library, a hostile one or a weak build system; it widened the 2021 category on vulnerable and outdated components. Only 11 CVE records map to its six CWEs, yet half of the community survey ranked it first, because most supply chain failures never become a CVE in your own code.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  145. Why is the lockfile your dependency inventory, and how do you build from it?

    package.json holds names and ranges; the lockfile holds every installed package with its exact version, source and integrity hash. In the lesson, 4 requested packages became 91 versions, 87 of them transitive. Commit the lockfile, build with npm ci (it stops when the two files disagree) and scan the lockfile, or an SBOM made from it, so the tree you scan is the tree you ship.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  146. What is an SBOM, and which formats and identifiers does it use?

    A software bill of materials: the inventory in a standard format that scanners and customers can read, with each component named by a package URL such as pkg:npm/express@5.1.0. CycloneDX (an OWASP project, ECMA-424) and SPDX (ISO/IEC 5962:2021) lead. npm sbom writes CycloneDX from the lockfile but left every supplier empty, so check a generated SBOM against the fields you must supply; CERT-In's guidelines list 21 minimum fields.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  147. What can an SBOM made from the repository not see?

    What a container image adds later. A source SBOM is one of six kinds that CERT-In's guidelines describe, one for each stage of the life cycle. Keep a complete SBOM for internal use and share a customised one with consumers.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  148. How do you decide whether a version is affected by an advisory written in OSV format?

    Each range is a list of events in version order: introduced is the first affected version and counts, fixed is the first version without the flaw and does not count, last_affected is the last known affected version and counts, and "0" stands for before all versions. A version is affected when it falls in any one range, and a flaw often has one range per release line. Compare by SemVer rules, not as text: as text, 8.10.0 sorts before 8.4.0.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  149. What four questions rank dependency findings, and what then?

    Is it being exploited (CISA's KEV catalogue; FIRST's EPSS, the probability of exploitation within 30 days)? Is the component exposed to the internet? Does your code reach the flaw? Is there a fix? Give each finding a deadline from a documented policy (ASVS 5.0.0 15.1.1, checked by 15.2.1) and record why any finding is set aside, for example in a VEX statement.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  150. Which fix suits a vulnerable dependency, depending on where the fix lies?

    Inside the range a parent declares: refresh the lockfile (npm update). A version you pinned yourself: edit your own entry. Outside the parent's range: overrides in package.json, tested and justified. Only in a new major version: upgrade or replace, with code changes. No fix yet: a mitigation. The cheapest dependency to fix is the one you removed.

    From the lesson Know your dependencies: inventory, SBOMs, audits

  151. Name four routes that put hostile code into a build.

    Typosquatting (a name one slip from a popular one, or one an AI assistant invented, called slopsquatting); dependency confusion (an installer that may fetch an internal name from a public registry); a hijacked maintainer account; and install scripts, which run code while installing. The 2025 npm worm combined stolen maintainer credentials with a post-install payload, as CISA's alert describes.

    From the lesson Malicious packages, typosquats and install scripts

  152. Why are install scripts dangerous, and how do you switch them off?

    preinstall, install and postinstall scripts (and prepare for git or local packages) run as whoever typed the command, with the developer's files and tokens or the CI job's secrets, before anyone reviews the code. Set ignore-scripts=true in .npmrc and run the few build steps you need by name. npm 12 blocks dependency scripts by default, and for pip the advice is --only-binary :all: with hash checking.

    From the lesson Malicious packages, typosquats and install scripts

  153. What do you look for first in the lockfile diff of a dependency update?

    An entry that gained hasInstallScript, a new resolved host or plain http, a missing integrity hash, a downgrade, or a whole new folder (a new publisher to check). npm ci refuses bytes that differ from the locked hash (EINTEGRITY), so CI installs the lockfile you committed and nothing else.

    From the lesson Malicious packages, typosquats and install scripts

  154. What is dependency confusion, and how do you prevent it?

    An installer that may search both a private and a public registry takes the best version match, so a public package with an internal name can win; pip searches every index with no priority. Give every name one source: for npm a scope tied to the private registry in .npmrc, for pip a single index serving both. Register placeholder names publicly and check that each resolved address in the lockfile points where you expect.

    From the lesson Malicious packages, typosquats and install scripts

  155. What do you check before a new package joins a project?

    That it exists for a reason (npm view on the exact name an assistant suggested), who publishes it and since when, whether it runs code at install, and where it was built (npm provenance, PyPI trusted publishers; neither proves the code harmless). Also whether it can wait: Dependabot holds updates for 3 days by default and npm's min-release-age installs only versions older than the days you set. A look-alike name filter only starts the review.

    From the lesson Malicious packages, typosquats and install scripts

  156. In what order do you respond when a package in your tree was hostile for a few hours?

    Find every copy, stop deploys, rotate every secret the installing machines or jobs held (not only the one the advisory names), rebuild from known-good versions, search the logs for what ran, and close the gap with a post-mortem that names the control which would have stopped it. CISA also advised phishing-resistant multi-factor authentication, branch protection, secret scanning and Dependabot security updates.

    From the lesson Malicious packages, typosquats and install scripts

  157. Why is a CI pipeline a target, and what did the tj-actions/changed-files incident show?

    The pipeline reads the code, installs dependencies and holds the tokens that publish and the keys that deploy. In 2025 the version tags of tj-actions/changed-files (CVE-2025-30066) were moved to a malicious commit that printed runner secrets into the workflow logs of every workflow naming the tag; CISA added it and reviewdog/action-setup (CVE-2025-30154) to its known-exploited catalogue.

    From the lesson Build pipelines and artifact integrity

  158. Which four rules does the lesson apply to a GitHub Actions workflow file?

    A token with least privilege (permissions: contents: read, widened per job); actions pinned to a full commit SHA; no event values inside run: scripts (pass them through an environment variable); and no untrusted code under pull_request_target or workflow_run, which carry the base repository's token and secrets.

    From the lesson Build pipelines and artifact integrity

  159. What is script injection in a workflow, and what is the fix?

    An expression such as ${{ github.event.pull_request.title }} in a run: step is expanded into the script's text before the shell starts, so a pull request's author decides part of the command. Pass the value through an environment variable, which the shell treats as data.

    From the lesson Build pipelines and artifact integrity

  160. Why pin an action to a full commit SHA and not to a tag?

    A tag can be moved or deleted, so every workflow naming it runs the new code with its secrets and without any change in your repository; a full-length SHA names one exact commit. Pinning freezes a choice rather than proving it good, so pair it with update pull requests such as Dependabot's and review each new SHA like a code change.

    From the lesson Build pipelines and artifact integrity

  161. What is build provenance, and what do SLSA build levels L1 to L3 mean?

    Provenance is the record of which builder ran, from which repository and ref, with which inputs, producing which file, named by digest. L1: it exists, made by the build platform (easy to forge). L2: a hosted platform signs it and consumers check it, which protects against tampering after the build. L3: a hardened, isolated platform keeps signing secrets out of reach of build steps, which protects against tampering during the build.

    From the lesson Build pipelines and artifact integrity

  162. What must a deploy step check before trusting a signed release, and what does keyless signing change?

    That the expected builder signed the provenance, that it names the digest of the exact file in hand, and that it was built from the source you release from. A signature from any key proves nothing alone: the lesson's signature-only check accepted 5 of 6 releases, one with a changed byte. Keyless signing with Sigstore uses a short-lived certificate bound to an OIDC identity, and the verifier names the identity and issuer it expects.

    From the lesson Build pipelines and artifact integrity

  163. How should a release move from build to production?

    Build once, with a read-only token and no deploy secret, then promote the same artifact (the same digest) from one environment to the next instead of rebuilding. The deploy job runs in an environment that waits for a person and holds no long-lived secret: with OIDC it receives a short-lived credential from the cloud provider, and only that job gets id-token: write.

    From the lesson Build pipelines and artifact integrity

  164. What is the order of response to a compromised action or a leaked CI secret?

    Find the runs in the advisory's window; rotate every secret those runs could read, not only the one named; search the logs for secrets, also in encoded forms (CISA warned of double base64); pin to a verified SHA of a fixed release or drop the action; review recent workflow changes, releases and artifacts; and add detection, such as alerts on changed workflow files and CODEOWNERS on .github/.

    From the lesson Build pipelines and artifact integrity

  165. What does TLS guarantee for one connection, and what does it not cover?

    The server is authenticated, data sent after the handshake is visible only to the two endpoints, and it cannot be changed without detection (RFC 8446). It does not hide the server's address or the host name in the first message unless both ends use Encrypted Client Hello, it does not hide the length of the data, and it does nothing for data before or after the connection.

    From the lesson Transport security: TLS, HSTS and mixed content

  166. Which TLS settings hold today?

    Versions: TLS 1.3, and 1.2 where clients need it (RFC 8996 deprecated 1.0 and 1.1; ASVS 5.0.0 12.1.1). Ciphers: AEAD suites such as AES-GCM and ChaCha20-Poly1305, never CBC, NULL, anonymous or export suites. Key exchange: ECDHE such as X25519, with a hybrid post-quantum group where supported, never static RSA. Certificates: publicly trusted, every host name listed, renewed by ACME, with expiry alerts and Certificate Transparency monitoring.

    From the lesson Transport security: TLS, HSTS and mixed content

  167. What is forward secrecy?

    Each connection uses fresh keys that are thrown away afterwards, so a server key stolen next year cannot decrypt traffic recorded today. TLS 1.3 made every public-key exchange forward secret by removing the static RSA and Diffie-Hellman suites.

    From the lesson Transport security: TLS, HSTS and mixed content

  168. Why is renewing TLS certificates by hand ending?

    A CA/Browser Forum ballot adopted in 2025 shortens the longest validity of a publicly trusted TLS certificate from 398 days to 47 days, in steps that end in 2029. ACME (RFC 8555) lets a server obtain and renew certificates without anyone touching them. Alert well before expiry, and watch Certificate Transparency logs for certificates you never asked for.

    From the lesson Transport security: TLS, HSTS and mixed content

  169. Why is the first plain-HTTP request the weak point, and what does HSTS do about it?

    A browser that has never visited sends http://shop.example/ in plain text, and someone on the path can rewrite the redirect to keep it on HTTP. After one HTTPS response with Strict-Transport-Security, the browser goes straight to HTTPS and ends the connection at any certificate error, with no click-through. Redirect on the same host, and send the header on every HTTPS response.

    From the lesson Transport security: TLS, HSTS and mixed content

  170. Which HSTS headers does a browser ignore, and what is max-age=0?

    It ignores the header over plain HTTP, reads only the first such header, requires max-age, and treats a directive that appears twice as an invalid header. max-age=0 is the off switch that removes the stored policy. For the preload list every redirect served over HTTPS must carry the header too, so a redirect from the base domain straight to www skips the response where it must be seen.

    From the lesson Transport security: TLS, HSTS and mixed content

  171. What is mixed content, and how do you fix it?

    Parts of an HTTPS page fetched over plain HTTP. Current browsers upgrade images, audio and video (except on an IP address) and block scripts, stylesheets, frames, objects and srcset images, so it mostly shows up as a broken page. Fix the link where it is written (https, or a relative address); upgrade-insecure-requests helps meanwhile; serve the file yourself or drop it; and mark every cookie Secure.

    From the lesson Transport security: TLS, HSTS and mixed content

  172. What do you do when a client must trust a private CA, and why not switch verification off?

    Give that one client the CA it should trust (ca in Node.js, verify="/path/to/ca.pem" in Requests, --cacert in curl) and leave every check on. rejectUnauthorized: false, verify=False, curl -k and NODE_TLS_REJECT_UNAUTHORIZED=0 connect to any server that answers, an impostor included. ASVS 5.0.0 asks for TLS and validating clients on internal connections too (12.3.1 to 12.3.4).

    From the lesson Transport security: TLS, HSTS and mixed content

  173. What four protection levels does the lesson use, and what do they decide?

    Public, internal, confidential and restricted. The level decides where a field may go: logs, third parties and screens. Restricted data (card numbers, passwords, session tokens, API keys) is never logged, never sent to third parties and never shown in full; confidential data (email, phone, address, date of birth) is logged masked only.

    From the lesson Protecting sensitive data: classify, minimise, mask

  174. What do ASVS 5.0.0 14.1.1 and 14.1.2 ask for, and what is the trap with encoded data?

    14.1.1: identify sensitive data and sort it into protection levels. 14.1.2: write rules for each level covering encryption, integrity, retention, logging and access to those logs. Data that is merely encoded, such as Base64 or the readable payload of a JWT, is still data in the clear and keeps the level of what it holds. Treat an unclassified field as confidential until someone decides.

    From the lesson Protecting sensitive data: classify, minimise, mask

  175. What is the cheapest protection for sensitive data?

    Not having it: collect less, keep less and show less, because data that is not kept cannot be stolen (A04:2025). What you do keep can still leave through URLs, logs, caches, browser storage, third parties, exports, backups and file metadata, so each copy needs a retention rule, which India's DPDP Act makes a legal duty.

    From the lesson Protecting sensitive data: classify, minimise, mask

  176. How do truncating, masking, tokenising and keyed hashing differ?

    Truncate: keep only part of a value, such as the last four card digits. Mask: keep the value but show it obscured, with an explicit action to reveal it (ASVS 14.2.6). Tokenise: replace it with a random token and keep the real value in a separate vault. Keyed hash: store an HMAC with a key held outside the database, when you only need to match equal values.

    From the lesson Protecting sensitive data: classify, minimise, mask

  177. Why does hashing a phone number with plain SHA-256 not protect it?

    The set of phone numbers is small. The lesson's program only had to hash the 100,000 numbers that start with the same five digits and compare, and found the original after 13,187 tries; against a keyed hash, 100,000 tries found nothing. A plain hash of phone numbers, PINs or dates of birth is a table anyone can rebuild.

    From the lesson Protecting sensitive data: classify, minimise, mask

  178. What five places does a reviewer check in every line that uses cryptography?

    Where random values come from; how data is encrypted; how a value is checked; the lifetime of keys and tokens; and whether you need the data at all. A04:2025 collects 32 weaknesses of this kind, and they look like working code: Math.random() making a reset token, MD5 in a password check, a fixed IV, an == between two MACs.

    From the lesson Spotting cryptographic failures in web code

  179. Which safe building block answers each of the five questions?

    Randomness: a CSPRNG, which draws unpredictable bytes from the operating system. Encryption: authenticated encryption, such as AES-GCM used through a high-level library, which hides data and also fails loudly when any part was changed. Checking: a MAC or signature compared in constant time. Lifetime: expiring tokens and rotated keys. Data: tokenisation, and above all not storing the data.

    From the lesson Spotting cryptographic failures in web code

  180. Why is a reset token made with Python's random module, seeded with the clock, weak?

    random is built for simulations. Seeded with the second it was made, such a token has only 86,400 possible values a day, about 16.4 bits, although it looks like 82.7 bits, and the same seed gives the same token every time. A token from secrets draws on the operating system and has 256 bits. No test that asks whether a token looks random can tell them apart.

    From the lesson Spotting cryptographic failures in web code

  181. Which of the five questions do you ask first about a new column of sensitive data?

    Whether the data should exist at all. Tokenisation replaces a value such as a card number with a random stand-in that a provider keeps, and the safest data is data that was never stored.

    From the lesson Spotting cryptographic failures in web code

  182. What is the short rule for secrets in a web app?

    Keep them out of code, images and bundles; hand them to the app at run time from a secrets manager or a short-lived identity; rotate them on a plan before anyone has a reason to; and scan code, history and logs for the ones that slip.

    From the lesson Secrets and keys: storage, rotation, scanning

  183. What is a secret in a web app?

    A value whose possession gives access, such as a database password, a payment-API token or a session signing key. Whoever holds one can act as your application from any machine at any hour until you cancel it, so secrets stay on the server and reach the code only when it runs.

    From the lesson Secrets and keys: storage, rotation, scanning

  184. How do a client key and a private key differ?

    A client key, such as a maps or analytics key, tells a provider which app is calling, and is meant to sit in the page, so you restrict it by origin, quota and scope. A private key signs, decrypts or authenticates (a session signing key, an API secret) and stays on the server, never in a browser.

    From the lesson Secrets and keys: storage, rotation, scanning

  185. Why does naming a variable VITE_ or NEXT_PUBLIC_ something put it in front of every visitor?

    Build tools put every variable with those prefixes into the JavaScript sent to the browser at build time, and Vite's documentation says such variables should hold nothing sensitive, such as API keys. Removing the prefix keeps the token out of the page too, so move the call to a route on your own server that adds the token there.

    From the lesson Secrets and keys: storage, rotation, scanning

  186. Why are passwords and secret tokens stored differently?

    People choose passwords from a short list of likely words and reuse them, so once a thief holds the table only the cost of each guess helps: a slow hash with its own salt for every record. A server draws a token from a CSPRNG at 128 bits or more, so there is nothing to guess and a fast hash is enough.

    From the lesson Passwords and secret tokens for web apps

  187. What does a per-record salt do for stored passwords?

    Without a salt, one pass over a list of likely passwords serves the whole table (12 hash calls in the lesson); with a salt per record and 2,000 rounds the same list cost 120,000 calls, ten thousand times as many. A salt also hides who shares a password: the plain table held four different values for five accounts, the salted table five.

    From the lesson Passwords and secret tokens for web apps

  188. How much randomness should a secret token, such as a reset, API or remember-me token, have?

    At least 128 bits from a CSPRNG. Because no list of likely tokens exists, the lesson's five random tokens stayed shut even under a plain SHA-256.

    From the lesson Passwords and secret tokens for web apps

  189. What must storage of server-chosen secret tokens achieve, given that nothing can be guessed?

    Make them hard to reuse and quick to check. Since the server picks them from a CSPRNG, the thief has nothing to guess, which is why storage can differ from the slow, salted hashing that passwords need.

    From the lesson Passwords and secret tokens for web apps

  190. What is SQL injection, and how does a parameterised query prevent it?

    Code pastes text from a request into an SQL query, so the database reads some of the text's characters as SQL (CWE-89, second in MITRE's 2025 CWE Top 25). A parameterised query sends fixed SQL text with a placeholder where each value goes, and the values separately, so the database has compiled the query before it sees any value and a bound value is never parsed, whatever it holds.

    From the lesson SQL injection and parameterised queries

  191. Why not fix an apostrophe by doubling the quotes yourself?

    It makes that one query work, but OWASP's cheat sheet marks escaping as strongly discouraged: the rules differ between databases and contexts, and one code path that forgets them is enough. Bind the value and there is nothing to remember. ASVS 5.0.0 1.2.4 asks for parameterised queries, an ORM or an equivalent protection for every database query.

    From the lesson SQL injection and parameterised queries

  192. What can a placeholder not stand for, and what do you do for a sort column?

    A placeholder is a value only: not a table or column name, a keyword such as DESC, or an operator. ORDER BY ? binds the text "price" as a value, so every row sorts by the same string and nothing sorts. Map each public sort name to a fixed SQL fragment and refuse the rest.

    From the lesson SQL injection and parameterised queries

  193. What are the recipes for LIKE patterns, IN lists and page sizes?

    LIKE: a bound % or _ still means any characters (a search for % matched 8 of 8 rows), so escape \, % and _ with a backslash and add ESCAPE '\'. IN: one placeholder per value, refusing an empty or oversized list. LIMIT: digits only, then a range such as 1 to 5, then bind, because SQLite reads a negative LIMIT as no limit.

    From the lesson SQL injection and parameterised queries

  194. What is second-order SQL injection, and where does the fix belong?

    A value stored safely, such as Neha D'Souza inserted with a bound value, comes back later and is pasted into a new query, for example by a monthly report, where its apostrophe breaks the SQL. Validating names at sign-up would not help, since the apostrophe belongs in the name. The fix is at every use: wherever a value enters SQL, bind it.

    From the lesson SQL injection and parameterised queries

  195. Does using an ORM make SQL injection impossible?

    An ORM protects the queries it builds; a string you hand its raw interface is yours. Django's documentation asks for care with its raw query methods, extra() and RawSQL, and Prisma's documentation warns that $queryRawUnsafe puts code at significant risk of SQL injection when it receives input.

    From the lesson SQL injection and parameterised queries

  196. Which three controls limit the damage of a query that was not bound?

    Narrow account rights (the app's account reads and writes rows but cannot change the schema, reporting is read-only, never an administrator account); generic error messages for the user with the detail in the log under a reference (ASVS 5.0.0 16.5.1); and a regression test per fix, such as a name with an apostrophe as a canary input. None of them replaces the bound value.

    From the lesson SQL injection and parameterised queries

  197. What is cross-site scripting, and what prevents it?

    A page writes text it received into its HTML as it is, so the browser parses the text as markup and a visitor's words can become elements, attributes or script that runs as the page's own code (CWE-79, first in MITRE's 2025 CWE Top 25). Output encoding prevents it: just before a value goes into the page, each character that means something in that place is replaced by a form the browser shows as text.

    From the lesson Cross-site scripting and output encoding

  198. What are the three kinds of XSS?

    Stored: the text is saved, as a comment or a profile, and served to every reader. Reflected: it arrives in a request, such as a search term in the URL, and the response writes it into the page at once. DOM-based: the page's own script takes text from the URL or a message and writes it with innerHTML instead of textContent. The fix is the same encoding at output.

    From the lesson Cross-site scripting and output encoding

  199. What can injected script do on your page?

    Anything the site's own code can: read and change the page and its local storage, and send requests with the visitor's credentials.

    From the lesson Cross-site scripting and output encoding

  200. Which five characters does HTML output encoding replace, and in what order?

    & first (as &amp;, because it starts every character reference), then < and > (as &lt; and &gt;), and " and ' (as &quot; and &#39;). Put every attribute value between quotes, because without them the value stops at the first space.

    From the lesson Cross-site scripting and output encoding

  201. When should you encode, and which places need their own rules?

    As the last step before a value enters the page, with the encoding of the place it lands, not when it is stored (ASVS 5.0.0 1.1.2): the same comment also goes into emails, JSON and exports. A URL in href needs its scheme checked, because HTML encoding leaves a link that runs script unchanged; script data travels as JSON in a data block with < escaped; and every framework has a switch that turns encoding off, which is where a review starts.

    From the lesson Cross-site scripting and output encoding

  202. How do you test output encoding?

    With a canary test: send text full of special characters through each output path and check the structure the browser would build. In the lesson, a tagline ending in an inch mark closed the title attribute in the weak card and added attributes of its own; the fixed card had the template's structure every time.

    From the lesson Cross-site scripting and output encoding

  203. What is the one mistake behind SQL injection, cross-site scripting and every other injection?

    Data from outside reaches an interpreter (any program that reads text and does what it says), and part of the data is read as instructions. A05:2025 has more CVEs than any other Top 10 category (62,445 across 37 CWEs). The cure is the same everywhere: keep data out of code.

    From the lesson Injection: keep data out of code

  204. Besides SQL, which interpreters can a pasted value reach?

    The Top 10 lists NoSQL, ORM, LDAP, expression languages and the operating system's command line; ASVS 5.0.0 adds spreadsheet formulas, regular expressions and template engines. HTML is one too: an inch mark ends an attribute. So are a CSV cell that starts with =, and a log line or HTTP header split by a line break.

    From the lesson Injection: keep data out of code

  205. In what order of preference do the defences against injection come?

    A safe API that gets the job done with no interpreter at all, such as a library call instead of a shell command; a parameterised interface that sends code and values apart; escaping with the interpreter's own rules, a last resort because one missed rule is enough; positive validation, which supports the others without replacing any; and a sink inventory of every place text is handed to an interpreter.

    From the lesson Injection: keep data out of code

  206. What ends a value or starts an instruction in common interpreters?

    A quote in SQL; < and quotes in HTML; = at the start of a spreadsheet cell; a line break in an HTTP header or a log. A file name typed on two lines and sent back in a header splits that header the same way.

    From the lesson Injection: keep data out of code

  207. When does an ORM stop protecting you from injection?

    An ORM binds every value it is given, but three things undo that by letting the request supply part of the query's structure: a raw SQL fragment built from text; a filter object copied from the request that lets the client choose columns and operators (query-builder injection, which needs no raw method at all); and, in NoSQL, an object in place of the string the code expected (operator injection).

    From the lesson ORM, NoSQL and query-builder injection

  208. Is moving to an ORM enough to be safe from A05:2025?

    No. An ORM is one of the Top 10:2025's preferred defences, yet the same page lists ORM injection among the forms of A05, and MITRE keeps CWE-564 for SQL injection through Hibernate. A query library protects the values it binds, and is unsafe for any structure a request may supply.

    From the lesson ORM, NoSQL and query-builder injection

  209. What is operator injection in a document query?

    The code expects a string such as a category name, but the request body sends an object holding an operator such as $in, which the database reads as an operator and not as a value, so one filter returns products from several categories. The fixed listing accepts only text, which can mean nothing but "equal to this", and answers anything else with 400.

    From the lesson ORM, NoSQL and query-builder injection

  210. What is the cure for ORM and NoSQL injection?

    An allowlist at the API: fields, operators and sort orders written in the code, and a type check on every value.

    From the lesson ORM, NoSQL and query-builder injection

  211. What is OS command injection, and how do you prevent it?

    A value pasted into a command line is read by a shell, which reads ; as the point where one command ends and the next begins, so a host name followed by a semicolon and a marker ran a second command nobody wrote (ninth in MITRE's 2025 CWE Top 25). Give the program its input as an argument list that no shell reads.

    From the lesson OS command and code injection

  212. In Node, what is the difference between exec and execFile for a host name followed by a semicolon?

    exec gives the whole string to a shell, which ran the second command and printed the marker on a second line. execFile starts the program itself and passes the host exactly as typed as an argument, so the semicolon is only a character in a name. Node warns against unsanitised input to exec, and to execFile and spawn when their shell option is on.

    From the lesson OS command and code injection

  213. Why can no list of forbidden characters make input safe for a shell?

    A shell also expands variables and wildcards, runs $(...) and backticks, redirects output with >, and joins commands with &&, ||, | and line breaks. Use a library call when one exists, and otherwise an argument list with no shell (ASVS 5.0.0 1.2.5 asks to parameterise operating system calls or encode for the command line).

    From the lesson OS command and code injection

  214. What is code injection (CWE-94), and how is the defence the same?

    The reader at the end is not a shell but something that compiles and runs text, such as eval, new Function, or a template engine given a template made from input. It is the same mistake with a different reader, so the defence is the same: do not build the text at all.

    From the lesson OS command and code injection

  215. What is DOM XSS, and why can no server filter catch it?

    The page's own script takes text from a source (the address, document.referrer, window.name, messages, web storage, server responses) and writes it through a sink such as innerHTML, outerHTML, insertAdjacentHTML, document.write, eval, a timer given a string, or an address assigned to href, src or location. The server never sees the part after the # sign, so no filter or log there can catch it.

    From the lesson DOM XSS, Trusted Types and HTML sanitizers

  216. What are the three habits that close DOM XSS?

    Write text with calls that cannot make markup (textContent makes a text node and no markup); make the browser refuse plain strings at the risky calls with Trusted Types, which accept only values made by a named policy; and pass the few pieces of HTML that people must supply through a maintained HTML sanitizer that rebuilds the markup from an allowlist of tags and attributes.

    From the lesson DOM XSS, Trusted Types and HTML sanitizers

  217. What are a source, a sink and a sink inventory?

    A source is a place where text can enter the page's script from outside its own code; a sink is a call that turns text into something the browser acts on. A sink inventory notes which variables hold text from a source and reports each place it reaches a sink, naming the safe call for the same job. A name-matching scan is only a first inventory, since real analysers follow data through functions and files.

    From the lesson DOM XSS, Trusted Types and HTML sanitizers

  218. Why use a maintained HTML sanitizer and not write your own?

    A sanitizer must parse the markup the way the browser does and rebuild it from an allowlist, and it is the kind of code that new browser behaviour breaks. Use a maintained one that you did not write.

    From the lesson DOM XSS, Trusted Types and HTML sanitizers

  219. What is a Content Security Policy, and what does a policy that holds mean?

    A response header that tells the browser which scripts, frames, forms and other resources a page may use; one that holds lets only the scripts the server marked run. Google's study of 1,680,867 hosts that sent a policy found that 99.34 % gave no real protection against XSS, and 75.81 % of the unique policies relied on script allowlists that can be bypassed.

    From the lesson Content Security Policy that actually holds

  220. What does CSP cover, and what is it not?

    Scripts (script-src and relatives), clickjacking (frame-ancestors), plain-HTTP subresources (upgrade-insecure-requests) and DOM sinks (Trusted Types). It is defence in depth: when output encoding fails, it restricts what an injected script is able to do. It does nothing about the flaw itself or about server-side flaws such as SQL injection, and it should not be the only defence against XSS.

    From the lesson Content Security Policy that actually holds

  221. What three sources make a script runnable under a strict CSP?

    A nonce: a random value generated afresh for each response, which appears both in the header and on every script tag the server trusts; a hash source, the SHA-256 hash of a script's exact text; and 'strict-dynamic', which lets a trusted script add further scripts while the browser ignores host lists.

    From the lesson Content Security Policy that actually holds

  222. Why does a host-list policy fail, and why is 'unsafe-inline' no repair?

    In the lesson a host list let in an injected tag pointing at a file on the allowed CDN while blocking the page's own inline script and the file its loader adds. Adding 'unsafe-inline' let in three scripts nobody meant to run, including the injected inline script and an onclick attribute. A nonce policy with 'strict-dynamic' judged all seven scripts correctly, and Report-Only mode lets such a policy reach a real site by reporting violations without blocking.

    From the lesson Content Security Policy that actually holds

  223. What is server-side template injection, and which three routes lead to it?

    Input ends up inside the source of a template, so the engine evaluates it (CWE-1336, a child of code injection). A name typed as {{ 7*7 }} that prints 49 proves the visitor's text was evaluated. OWASP's cheat sheet lists three ways in: the template's source is built from input, a template hands input to something that runs strings as code, or input chooses which template is loaded.

    From the lesson Safe templating and server-side template injection

  224. Why does autoescape not stop template injection?

    Autoescape only encodes what the placeholders print; an injected name was never a printed value, it was part of the template itself. In the lesson the weak page printed 49 and drew a name in bold markup even with autoescape on. Keep the template fixed in code and pass every outside value as data.

    From the lesson Safe templating and server-side template injection

  225. Why do testers use a harmless sum as a probe, and what must the probe cover?

    49 stands out from the text typed. A real application may speak several template syntaxes, so a probe tries the sum in every family its engines use; the lesson's engine understood only one of four.

    From the lesson Safe templating and server-side template injection

  226. What does safe templating keep?

    The template fixed in your code, with every outside value passed as data; autoescape on; a small render context, the set of names and objects the template can read; and the weakest engine that works for text other people write. A logic-less engine allows placeholders and sections but no expressions, and a sandbox narrows what the templates of a full engine may do.

    From the lesson Safe templating and server-side template injection

  227. What is the difference between a design flaw and an implementation defect?

    A design flaw is a control that is missing or wrong in the design, such as account recovery by secret questions or a limit that only the browser checks (CWE-602); its fix starts with a requirement or a different feature. An implementation defect is a correct design coded wrongly, such as the wrong comparison operator, and is fixed in the code. No careful coding adds a control that was never designed (A06:2025).

    From the lesson Secure design: requirements and abuse cases

  228. Why are secret questions a design flaw, and what replaces them?

    The answers, such as which school you attended, are known to classmates, relatives and anyone who reads an old profile, so no careful storage helps. ASVS 5.0.0 requirement 6.4.2 says secret questions must not exist, NIST SP 800-63B-4 does not allow a service to prompt for them, and the methods it names instead are repeated identity proofing, recovery contacts and saved recovery codes.

    From the lesson Secure design: requirements and abuse cases

  229. Which four kinds of security requirement does a feature such as a credit transfer need?

    A field rule (an amount of 1 to 500 whole credits); a combination (a recipient who is a student of the sender's own college); a business limit per user and for the system (no more than 20 transfers and 1,000 credits in a day from one sender); and failure behaviour (when the ledger or the fraud check cannot give an answer, refuse). ASVS 5.0.0 2.1.1 to 2.1.3 cover the first three.

    From the lesson Secure design: requirements and abuse cases

  230. Why must a security requirement carry a number?

    "Transfers must be limited" passes every build, while "at most 20 transfers a day per sender" fails a build that has no limit. Failure behaviour belongs on the list for the same reason: a fraud check that is skipped whenever its service times out is a control that fails open.

    From the lesson Secure design: requirements and abuse cases

  231. What makes an abuse case finished, and what keeps a register of them honest?

    A case is finished only when it has a control, a test that exists and an owner. Each case has an id, the feature, a risk rating, a countermeasure and a decision (address it, or accept it with a written reason). Ask about more than one kind of misuser per story: a dishonest user, a script, an insider such as a vendor's staff, and someone whose access should have ended.

    From the lesson Secure design: requirements and abuse cases

  232. What is a paved road, and what does A06:2025 recommend?

    A shared component that turns the safe way of doing something into the easiest one, such as a data layer that takes the college from the session and adds it to every query. A06:2025 recommends a library of secure design patterns and paved-road components, and segregation of tenants that holds through every tier, with row-level security as a second tier behind the paved road.

    From the lesson Secure design: requirements and abuse cases

  233. When does a misuse test earn its place?

    When it fails on a build that lacks its control, so run each against a weak build at least once, and call the server directly with what the form would refuse, since a misuser never has to use your form. In the lesson one weak build failed 5 of 8 tests and the other 3; a test for a rule that every build has proves nothing until you try a build without it.

    From the lesson Secure design: requirements and abuse cases

  234. What are business logic flaws, and why do validation and scanners miss them?

    They break the rules of the business, not the syntax of a request. A checkout that received two thalis at a price of 1 credit each charged 2 credits for 160 credits of food, though the item existed, the quantity was whole and the price was a number. A format check asks whether a value is well formed; a business rule asks whether it is right.

    From the lesson Business logic flaws and workflow abuse

  235. Name six common families of business logic flaw in a checkout.

    Price tampering (a price in the request is believed), quantity tampering (a negative quantity subtracts from the total), coupon stacking (one coupon used twice in an order), coupon replay (a once-per-student coupon works again the next day), step skipping (an order reaches paid or collected without the step before it), and abused limits (a feature with no cap, such as SMS codes sent on every request, costs money each time).

    From the lesson Business logic flaws and workflow abuse

  236. Which values must the server compute itself, and why is a signed hidden field not enough?

    Every value that decides money, authority or ownership: prices from its own catalogue, coupons from its own record of who used them, the student from the session. A signature shows that the server issued a value; recomputing shows that the value is still right. Client state is input, not truth (CWE-472; ASVS 5.0.0 2.2.1).

    From the lesson Business logic flaws and workflow abuse

  237. How does a state machine on the server stop workflow abuse?

    Each order has a state and a table lists the moves allowed from it, so any other move is refused whatever the app asks, and skipping or repeating a step has nowhere to go. CWE-841 names steps done out of order or left out, and ASVS 5.0.0 2.3.1 asks that each flow run its steps in the expected order.

    From the lesson Business logic flaws and workflow abuse

  238. Which three defences back up recomputing and the state machine?

    An invariant check after every operation, such as a ledger whose entries add up to zero; validation of business meaning, such as at most 10 of one item; and monitoring of business events, such as coupons per device, with an alert when a count runs far above normal.

    From the lesson Business logic flaws and workflow abuse

  239. What are TOCTOU and a double-spend?

    Time-of-check to time-of-use (CWE-367) is code that checks the state of something, then uses it, while the state changes in between; it is a child of the general race condition CWE-362, where two operations share a resource without proper synchronisation. A double-spend is the money version: the same balance, coupon or ticket spent twice because two requests passed the same check.

    From the lesson Race conditions, TOCTOU and double-spend

  240. Why can a single-threaded Node.js server have race conditions?

    Every await hands control back to the event loop, which runs other requests while this one waits for its database. In the lesson two withdrawals of 80 from a wallet of 100 credits, started together, ended at -60, while the fixed run paid one and ended at 20.

    From the lesson Race conditions, TOCTOU and double-spend

  241. Why is the fix for a race never a better check?

    Each request was correct by itself: it checked a balance that was true when it read it, and the rule broke only because the two ran together. The fix is a check that nothing can come between, which closes the gap.

    From the lesson Race conditions, TOCTOU and double-spend

  242. Which four controls close most races?

    A conditional update (checks and changes in one statement, and its row count says whether it happened); a unique constraint (the database refuses a second row for a rule such as once per student); a transaction with a row lock (the second request waits for the first); and an idempotency key (the server recognises a retried request and returns its first answer, which answers the same request sent twice).

    From the lesson Race conditions, TOCTOU and double-spend

  243. What three questions does every rate limit answer, and what does the server send when it refuses?

    What is counted, per which key, and over what window. The refusal is 429 Too Many Requests (RFC 6585), and a Retry-After header can tell the client when to try again. ASVS 5.0.0 2.4.1 requires anti-automation controls, and OWASP's API Top 10 names API4:2023, unrestricted resource consumption, and API6:2023, unrestricted access to sensitive business flows.

    From the lesson Rate limiting and anti-automation

  244. Why can a fixed window of 10 a minute let a script make 20 attempts in two seconds?

    Its count restarts from zero at the top of each minute, so 10 attempts just before the edge and 10 just after all pass: twice the limit. Nothing was a bug; choosing a window with an edge for a limit that had to hold over any 60 seconds was the design mistake.

    From the lesson Rate limiting and anti-automation

  245. Name rate-limiting and anti-automation answers beyond the fixed window.

    A sliding window counts the 60 seconds before each new request, so no edge doubles the limit. A token bucket refills a few tokens a second, and a short burst may spend the saved tokens. A concurrency limit caps costly requests at the same moment, a cost-based limit charges points by what a request costs, and a key of account and source together slows a script without locking out the account's real owner.

    From the lesson Rate limiting and anti-automation

  246. How do rate limiting and anti-automation differ?

    Rate limiting decides how many requests one key may make in a stretch of time. Anti-automation protects whole business flows, such as one-time codes and sign-ups, from scripts that keep to every per-request rule.

    From the lesson Rate limiting and anti-automation

  247. Why is an upload input you will serve back, and which parts can you not trust?

    The bytes, the file name and the Content-Type all come from the person sending the file, and OWASP's File Upload Cheat Sheet calls the content type trivial to spoof. Decide the type from the bytes against a short list of the formats the feature needs. Unrestricted upload of a dangerous file type is CWE-434, 12th in MITRE's 2025 CWE Top 25.

    From the lesson Secure file uploads and downloads

  248. What are the four decisions of secure file uploads?

    Accept: check the bytes against an allowlist of formats and a size limit before anything else. Store: keep files under names the server makes, in storage where nothing can run them. Serve: from a separate origin, with nosniff, a sandbox policy and, for documents, as attachments. Check inside: limit archives and images before unpacking them, rebuild images from their pixels, and scan files in quarantine first.

    From the lesson Secure file uploads and downloads

  249. What is a file signature, and why does it beat the label?

    Most formats begin with fixed bytes that name them, so the handler can read the first bytes and decide the type itself. In the lesson the fixed handler kept a JPEG that arrived labelled text/html, because the label decides nothing, and refused a PDF named .png.

    From the lesson Secure file uploads and downloads

  250. Why does none of the four upload decisions rely on the others being perfect?

    A file that slips past the first check still lands under a name the server made, is still served with headers that keep it from running, and still waits in quarantine until its scan is done.

    From the lesson Secure file uploads and downloads

  251. How do credential stuffing, password spraying and brute force differ?

    Stuffing tests username and password pairs taken from the breach of another site: each account once or twice, from many sources, with many names that have no account here. Spraying tests one weak password against a large number of accounts. Brute force tests many passwords against one account. A hybrid tries variations of leaked passwords, such as Winter2025 becoming Winter2026.

    From the lesson Login defences: stuffing, spraying, enumeration

  252. Which count sees which shape of automated sign-in traffic?

    Pairs from a breach: the share of names with no account, across the site. Spraying: failures on many accounts from one source. One-account guessing: failures on one account. People make 1 or 2 attempts on an account and about 1 % of their names are unknown, which is the normal shape. A control sees only the shape it counts.

    From the lesson Login defences: stuffing, spraying, enumeration

  253. Why is "five wrong passwords lock the account" a poor control?

    It counts every sender's failures against the owner: in the lesson's model a delay keyed by the account alone refused 7 owners who typed nothing wrong. Key the delay by account and source together and add a separate limit per source. NIST SP 800-63B-4 sets the upper bound at 100 consecutive failures on one account, and the Top 10 says to limit or delay failures without creating a denial of service.

    From the lesson Login defences: stuffing, spraying, enumeration

  254. What did each control stop in the lesson's model hour?

    A per-source limit cut the spray from 13 opened accounts to 4 but did nothing to the pairs, which sent only 4 attempts per source. Refusing common passwords at sign-up removed the spray's last 4. A code for unknown devices while names with no account spiked brought the pairs from 43 to 1. A second factor on every account brought every sender to 0, at the cost of asking everyone.

    From the lesson Login defences: stuffing, spraying, enumeration

  255. How do sign-in, sign-up and reset avoid user enumeration?

    Give every address the same answer and the same work: same status, redirect, cookie, words and timing (the number of password hashes). Move the difference to the inbox: sign-up says a link has been emailed to the address provided, and for an address that already has an account it mails a notice in place of the link. ASVS 5.0.0 6.3.8 asks for this at level 3. Compare the whole answer in a test, not the text on the screen.

    From the lesson Login defences: stuffing, spraying, enumeration

  256. How do you check a new password against breached ones without sending it anywhere?

    With k-anonymity and the Pwned Passwords range API: hash the password with SHA-1, send only the first five of the 40 hex characters, and compare your remaining 35 with the suffixes returned. Compare in one case, skip padding lines (count 0), call from your server and wait until the field is complete. ASVS 5.0.0 6.2.4 and 6.2.12 ask for the check at sign-up and every change, and a reset sets a new password too.

    From the lesson Login defences: stuffing, spraying, enumeration

  257. Which sign-in log rules catch what a single attempt cannot, and what do they not need?

    A source that fails on 10 different accounts within 10 minutes (the spray); a spike in the share of names with no account (the pairs: noisy, so step up rather than block); a success after many failures on one account; and a right password from an unknown device (precision 29 % in the model, so notify and do not block: ASVS 6.3.5 and 6.3.7). The rules never need the password, and ASVS 16.2.5 says never to log credentials.

    From the lesson Login defences: stuffing, spraying, enumeration

  258. Where do a second factor, a CAPTCHA and device recognition belong in a sign-in flow?

    A second factor is by far the best defence against most password attacks and can be required only for a new device or a risky action. A CAPTCHA is defence in depth, since tools break many of them, and success criterion 3.3.8 of WCAG 2.2 asks for another way through. Device recognition is a risk signal, never a substitute for authentication, because a client can fake its traits. Ship no default accounts (ASVS 6.3.2).

    From the lesson Login defences: stuffing, spraying, enumeration

  259. Why must account recovery be as strong as sign-in?

    Recovery is authentication by another door: a reset link trusts whoever reads the inbox, a code by SMS whoever holds the phone number, and a help-desk call a person's judgement. If any door replaces the password and the second factor on its own, the account is only as strong as that door. NIST SP 800-63B-4 lists saved recovery codes, codes to an address on file, recovery contacts and repeated identity proofing, and says recovery always notifies the account holder.

    From the lesson Recovery, MFA and passkeys: no weak links

  260. What do ASVS 5.0.0 6.4.2 and 6.4.3 require of recovery?

    6.4.2: no password hints and no secret questions, because knowledge-based answers cannot be made safe when other people can know them. 6.4.3: a reset never bypasses a second factor that is switched on.

    From the lesson Recovery, MFA and passkeys: no weak links

  261. What makes a second factor phishing-resistant, and which factors are not?

    Whether a page that looks like yours can use what the person gives it. NIST SP 800-63B-4 says passwords, codes sent out of band and one-time codes from an app lack it, and that WebAuthn resists phishing by binding the verifier's name. A code works wherever it is typed; a passkey works only for the site it was made for.

    From the lesson Recovery, MFA and passkeys: no weak links

  262. How does a TOTP code work?

    RFC 6238 defines it as an HMAC of the current 30-second step, computed from a key that an app shares with your server and cut down to digits. A six-digit code stays the same for the whole step and works wherever it is typed during that step, a lookalike page included.

    From the lesson Recovery, MFA and passkeys: no weak links

  263. How does a passkey work, and what are recovery codes?

    A passkey is a key pair made for one site: the private key stays on the person's device, and the browser offers it only to pages of the site's relying party ID. Recovery codes are the backup factor, saved at enrolment, and each one works once. NIST treats codes over the phone network as restricted, and SIM swaps move a phone number to another SIM card.

    From the lesson Recovery, MFA and passkeys: no weak links

  264. What keeps each way back into an account as strong as sign-in?

    Reset link by email: the second factor after the link, other sessions ended, a notice. Code by SMS: never the only factor, and a notice on every use. Recovery codes: shown once, stored hashed, each used once. Help desk: proof as strong as enrolment, a waiting period, notices. Secret questions: remove them.

    From the lesson Recovery, MFA and passkeys: no weak links

  265. Why is a session ID a bearer secret, and which four rules keep it trustworthy?

    The server believes whoever sends the ID, so it is as good as the password while the record exists. The ID cannot be guessed (ASVS 5.0.0 7.2.3: 128 bits or more, from a cryptographically secure generator); sign-in replaces it, so a known ID opens nothing (session fixation); time ends the session, with idle and absolute limits checked on the server's clock; and logout deletes the server's record.

    From the lesson Sessions: IDs, fixation, timeouts and logout

  266. Why does clearing the cookie at logout not end a session?

    It ends nothing on the server. In the lesson a copy of Asha's session ID taken from a log line still opened her account 145 minutes after logout in the weak app, while the fixed app, which deleted its record, answered 401. A logout, a disabled account and a sign out everywhere all delete the record.

    From the lesson Sessions: IDs, fixation, timeouts and logout

  267. Which three session failures does A07:2025 name?

    An ID reused after sign-in, an ID in the URL, and sessions that a logout or a period of inactivity does not end.

    From the lesson Sessions: IDs, fixation, timeouts and logout

  268. Where can the session record live, and why did the logout test separate two apps?

    In a table the server keeps, or inside a signed cookie that the server cannot take back. Both apps asked the browser to drop the cookie at logout, and only the one that deleted its record could refuse the copy of the ID.

    From the lesson Sessions: IDs, fixation, timeouts and logout

  269. Why must a service verify a JWT and not only decode it?

    A JWT is three base64url strings; the payload is encoded, not encrypted, so anyone can read the claims, and anyone can write a token with claims of their choice. In the lesson a decoder believed all four tokens, two of them forged, while a verifier accepted only the genuine one.

    From the lesson JWT validation and token storage

  270. Which seven parts of JWT validation can a test show are skipped?

    Signature (recomputed with a key you trust); algorithm (the token's alg must be on your own list, never none); key (found by kid in your own list, never a key inside the token); issuer (iss); audience (aud names this service); time (nbf and exp, with a small leeway for clocks); and type (typ, so an ID token cannot pass as an access token).

    From the lesson JWT validation and token storage

  271. Who can read a token kept in localStorage, in memory, in an HttpOnly cookie or in a backend for frontend?

    localStorage and sessionStorage: every script of the page. A variable in memory: lost at every reload. An HttpOnly cookie: hidden from scripts, and the browser sends it with requests on its own. A backend for frontend keeps the token on the server, so there is nothing in the browser to read. Each place has its own readers.

    From the lesson JWT validation and token storage

  272. Which kinds of bad token did the lesson's verifier refuse?

    An edited payload and a token signed with another key failed the signature check, and an expired token failed its exp; only the genuine token passed.

    From the lesson JWT validation and token storage

  273. What do OAuth 2.0 and OpenID Connect add, and what are the access token and the ID token?

    OAuth 2.0 lets an app act for a person at an API: the person signs in at an authorization server and the app receives an access token that the API accepts. OpenID Connect adds sign-in on top and also returns an ID token, a signed statement of who signed in.

    From the lesson OAuth 2.0 and OpenID Connect: done right

  274. Which three random values tie the authorization code flow together?

    The state links the callback to the browser that made the request, the nonce binds the ID token to this sign-in, and the PKCE verifier binds the code to the app that asked for it.

    From the lesson OAuth 2.0 and OpenID Connect: done right

  275. Which OAuth grant suits a person signing in, and which does RFC 9700 rule out?

    Authorization code with PKCE: the app receives a code that works once and swaps it for tokens, proving with the verifier that it asked. Client credentials serves a service that acts on its own behalf, with no person signing in. Implicit puts tokens in the redirect URL and clients should not use it, and the resource owner password credentials grant collects the person's password in the app and must not be used (RFC 9700).

    From the lesson OAuth 2.0 and OpenID Connect: done right

  276. What does PKCE change for a stolen authorization code?

    In the lesson's run, a server that ignores PKCE handed out tokens for 4 of 5 requests, including a bare copy of the code, a copy with a made-up verifier and a request with no challenge; one that enforces it issued tokens only for the app's own exchange. A code works once on both. RFC 9700 asks every public client to use PKCE and recommends it for confidential clients too.

    From the lesson OAuth 2.0 and OpenID Connect: done right

  277. Why can a native loader such as pickle.loads be dangerous with untrusted bytes?

    A pickle is a short program for a small machine, and one instruction imports a function by name and calls it, so whoever can write the bytes decides what runs while the object is built. Python's documentation says the module is not secure and only trusted data should be unpickled. In the lesson a cookie that named a function made 1 of the 9 loads run it, and the output was a normal empty basket (CWE-502, 15th in the 2025 CWE Top 25).

    From the lesson Insecure deserialisation and safe data formats

  278. Which formats can name a class or a function in their bytes, and which cannot?

    Python pickle, PyYAML yaml.load with a full Loader, Java ObjectInputStream, PHP unserialize and .NET BinaryFormatter can; JSON cannot, since RFC 8259 values are objects, arrays, numbers, strings, false, null and true. The safe side is a different format, not a better setting: PHP's manual says not to pass untrusted input to unserialize whatever allowed_classes says, and BinaryFormatter cannot be secured by configuration. A name like jsonpickle misleads.

    From the lesson Insecure deserialisation and safe data formats

  279. How does a reviewer recognise a serialised value by its first bytes?

    A Java stream starts AC ED 00 05 (rO0 in Base64, rO0AB), a Python pickle gASV in Base64, .NET BinaryFormatter AAEAAAD/////, and PHP text starts with O: followed by a class name and length. A prefix is a clue and a missing one is not an all-clear: encryption or another Base64 layer hides it.

    From the lesson Insecure deserialisation and safe data formats

  280. Which two searches make a review for deserialisation complete?

    Search the code for the loaders (pickle.load, yaml.load(, ObjectInputStream, unserialize(, BinaryFormatter) and trace what reaches each; then search the values that leave your server, such as cookies, hidden fields and signed-looking parameters, for the prefixes. A hit on either side means the loader is the thing to replace.

    From the lesson Insecure deserialisation and safe data formats

  281. What does a safe replacement for a native loader check?

    It caps the size first, parses JSON, checks keys (refusing extra ones), types and ranges, and builds its own object from the checked fields. In Python true counts as a quantity of 1 because isinstance(True, int) is True. ASVS 5.0.0 15.3.5 asks for explicit type checks against type confusion, and 1.5.2 for an allowlist of types for untrusted deserialisation. Validating after pickle.loads is too late.

    From the lesson Insecure deserialisation and safe data formats

  282. When a native format has to stay, what narrows it, and why is a signature not enough?

    A type allowlist (a find_class override, Java's serialisation filter with limits on depth, references and bytes, PHP's allowed_classes) refuses names it was not given, but it is only as safe as what it allows. A signature refuses bytes your server did not write, so verify it before loading; yet a correctly signed cookie that named the canary ran it, because a signature proves who wrote the bytes, not that loading them is safe.

    From the lesson Insecure deserialisation and safe data formats

  283. Which two habits complete the defence against insecure deserialisation?

    Keep the runtime and libraries patched, because the code that does the harm lives in dependencies and new gadgets keep turning up. And log every refusal: the OWASP Logging Cheat Sheet lists deserialisation failures, and a burst of refusals on one cookie is a probe.

    From the lesson Insecure deserialisation and safe data formats

  284. What is mass assignment, and what is its single fix?

    A handler copies every field of the request onto a record (Object.assign(user, body)), so the client chooses which fields to write: a form that sent 2 fields let requests change 5 others in the lesson. It is CWE-915 in A08:2025 (autobinding in Spring MVC and ASP.NET MVC, object injection in PHP, API3:2023). The server's list of writable fields decides what a request can set, never the request.

    From the lesson Mass assignment and prototype pollution

  285. How do an allowlist, a DTO and a strict schema differ, and why not a denylist?

    An allowlist names the fields a caller may write and refuses the rest. A data transfer object is a type that holds only the fields one operation accepts. A strict schema checks the type of each field and rejects keys it does not know. A denylist leaves every field added later writable by default; ASVS 5.0.0 15.3.3 asks for limits on the allowed fields at level 2.

    From the lesson Mass assignment and prototype pollution

  286. What is prototype pollution?

    A write to Object.prototype, the shared fallback of plain JavaScript objects, after which every object seems to have the new property (CWE-1321, a child of CWE-915). A check that reads user.isAdmin through the prototype chain then passes for a user who never was an administrator.

    From the lesson Mass assignment and prototype pollution

  287. Does JSON.parse of a key named __proto__ pollute the prototype?

    No: it only makes an ordinary property with that name. Nothing is polluted until a helper such as a deep merge, a clone or a path setter treats the key as a place to walk.

    From the lesson Mass assignment and prototype pollution

  288. What fixes prototype pollution in the helpers that handle keys?

    A null-prototype object (Object.create(null)); a Map, which keeps keys as data with no inherited names; Object.hasOwn(obj, key) to read only own properties; a schema that rejects unknown keys; a key filter; the Node flag --disable-proto, which removes one route; and freezing Object.prototype so that later writes to it fail.

    From the lesson Mass assignment and prototype pollution

  289. What power does a third-party script tag give the vendor?

    The same power as your own code: it can read the page, read what a visitor types into a form and send requests as the page. When the file changes, because the vendor ships a new version or is breached, your page runs the new code the next time anyone loads it. OWASP's cheat sheet names three risks: lost control over changes to your page, arbitrary code in visitors' browsers, and sensitive information going to the vendor (CWE-829 and CWE-830).

    From the lesson Third-party scripts and Subresource Integrity

  290. What is Subresource Integrity, and what does it protect against?

    A tag names the hash of the file you inspected in its integrity attribute: an algorithm (sha256, sha384 or sha512), then a hyphen, then the Base64 form of the hash. The browser hashes the file it received and refuses to run it when the hash differs. It protects against a change after your review, and it does not make the first file safe.

    From the lesson Third-party scripts and Subresource Integrity

  291. How long are SRI hash values, and how sensitive are they to a change?

    A sha256 value is 44 Base64 characters, sha384 is 64 and sha512 is 88. Changing one character of a 41-byte script gave a sha384 value that shared nothing with the first, so under a tag that pins version 1.4.2 a browser that fetches 1.4.3 refuses the file.

    From the lesson Third-party scripts and Subresource Integrity

  292. What four answers exist for a script you cannot fully trust?

    Host a pinned copy, serving a version you inspected from your own origin; pin, loading a versioned CDN file under an integrity value; isolate, putting a widget in a sandboxed frame on another origin; or accept the script and limit what it can load and send with a Content Security Policy.

    From the lesson Third-party scripts and Subresource Integrity

  293. Why verify a webhook signature over the raw bytes you received?

    A signature covers exact bytes. Most frameworks parse JSON before the handler runs, and a handler that writes the object back out hands a different text to the check: in the lesson the re-serialising handler accepted 1 of 3 genuine deliveries (compact JSON and a raw UTF-8 name failed), while the raw-byte handler accepted all 3, and both refused all 4 forgeries.

    From the lesson Signed data, webhooks and safe updates

  294. What is a message authentication code on signed data, and what does a match prove?

    A value computed with a secret key held by the signer and by you alone. A match means the bytes are exactly those the key holder wrote; HMAC-SHA-256 is the usual choice of webhook providers. Compare in constant time, as hmac.compare_digest does (ASVS 5.0.0 11.2.4 asks for constant-time cryptographic operations at level 3).

    From the lesson Signed data, webhooks and safe updates

  295. What does a matching signature still leave open?

    Freshness, intended use and rollback. A timestamp inside the signed bytes limits replay, a stored delivery ID drops duplicates, two secrets accepted at once let a key rotate, and a pinned key with a version rule keeps an update from going backwards.

    From the lesson Signed data, webhooks and safe updates

  296. What do safe updates add to the same idea?

    They check a signature or a hash against something you already trust before anything is installed, so downloaded code and data get the same verification as a webhook.

    From the lesson Signed data, webhooks and safe updates

  297. What should a security log record?

    The pass or fail outcome of every security control, failures and successes both: sign-ins, refused access, refused input, session failures, changes of role or permission, access to sensitive records, high-value actions, and a control being switched off. A log of successful sign-ins alone cannot show guessing. OWASP publishes event names such as authn_login_fail, authz_fail and privilege_permissions_changed; add your own in the same style (ASVS 5.0.0 16.3.1 to 16.3.4).

    From the lesson Security logging: what to record, what never to

  298. What must every log entry say?

    When (UTC with an explicit Z, to the millisecond, clocks synchronised), who (an identifier such as user:asha, not a name), from where, what happened, to what, with what result, and a request ID that middleware sets once, which acts as a correlation ID. Write one JSON object per line, and keep a test that breaks the build if any field is missing (ASVS 16.2.1, 16.2.2 and 16.2.4).

    From the lesson Security logging: what to record, what never to

  299. What is log injection, and how do you prevent it?

    A value from a client written into a log so that it forges entries, breaks the format or attacks the tool that reads the log (CWE-117). In the lesson a user name holding a line break and a fake line made five events read back as six lines, one saying that admin signed in. Encode every value for the format that will read it: one JSON object per event, or quoted values with line breaks and control characters escaped, HTML encoding in a web viewer (ASVS 16.4.1), and a cap on length.

    From the lesson Security logging: what to record, what never to

  300. What must a log not contain?

    Source code, session IDs, access tokens, passwords, connection strings, keys, payment card and bank details, sensitive personal data and data people have not agreed to give (CWE-532). ASVS 5.0.0 16.2.5 sorts them by level: credentials and payment details never, other data such as a session token only hashed or masked. Log an identifier in place of a name.

    From the lesson Security logging: what to record, what never to

  301. Why log chosen fields rather than rely on redaction?

    Redaction sees characters, not meaning. In the lesson the filter kept 11 of 15 calls clean and leaked 4 (a code without a separator, a password typed in the user name box, a Base64 body, an email nobody wrote a pattern for), while a logger that writes only named fields kept all 15 clean. Choose the fields and keep redaction as the net beneath; never hand a logger a whole request or user object.

    From the lesson Security logging: what to record, what never to

  302. How can you follow a token through the log without storing it, and what is the limit?

    Log a fingerprint, which prints the same 8 characters for the same token in two events. The fingerprint of a 4-digit PIN, a code or a phone number is found by trying every possible value, so for values with few possibilities use a keyed hash whose key is not stored with the logs, or do not log the value.

    From the lesson Security logging: what to record, what never to

  303. How do you protect the log itself?

    Send it to a logically separate system, so that a breach of the app does not reach it (ASVS 5.0.0 16.4.2 and 16.4.3): a write-only account, a secure channel such as syslog over TLS, limited read access, and a SIEM that stores, searches and alerts. A hash chain gives order and points at an edit, but cutting off the last entries or recomputing every later hash passes the chain alone; a copy of the length and last hash kept elsewhere finds both. Alert when logging stops, and never sample security events away.

    From the lesson Security logging: what to record, what never to

  304. Which Indian log rules does the lesson name?

    The Directions that CERT-In issued under section 70B(6) of the IT Act tell the entities they name to enable logs of all their ICT systems, keep them securely inside India for a rolling 180 days and set clocks from NIC or NPL NTP servers. India's DPDP Rules, 2025 count logs that give visibility on access to personal data among the minimum safeguards of rule 6, kept for one year and in force eighteen months after publication. Whether they cover your service is a legal question.

    From the lesson Security logging: what to record, what never to

  305. What makes an alert something a person can act on?

    A rule that says when it fires, a severity, an owner who is expected to look, and a runbook that says what to do first, decided before it fires. A09:2025 lists how alerting fails: missing or ineffective thresholds and escalation, unread alerts, stale detection rules, so many false positives that real alerts are buried, an incomplete playbook, and penetration tests or DAST scans that raise no alert.

    From the lesson Alerting and first-hour incident response

  306. Which log signals suggest guessing, stuffing, takeover and an intruder?

    Many failed sign-ins on one account (authn_login_fail): guessing a password. One address failing across many accounts: credential stuffing. A success after several failures (authn_login_successafterfail): a takeover. A decoy touched: an intruder. Odd input is a suspicious event and not proof, so judge it by repetition, correlation and context.

    From the lesson Alerting and first-hour incident response

  307. What is a honeytoken, and why does it raise so few false alarms?

    A decoy that no legitimate process uses: a database record, a user or an API key that looks real. Normal business never touches it, so any access is an alert and no threshold has to separate attackers from customers. Skip jobs that read every record, such as a nightly export, by identity; a decoy sees only attackers who reach it, so it complements other rules.

    From the lesson Alerting and first-hour incident response

  308. What did the decoy rule and the 404-count rule each catch in the lesson's 3,243 requests?

    The 404 rule caught the scanner, raised two false alarms for search crawlers and missed the intruder, whose three requests were too few for any count. The decoy rule caught the intruder with no threshold and had one false alarm until the export job was skipped by identity; it never saw the scanner. The two rules cover different attackers.

    From the lesson Alerting and first-hour incident response

  309. How should decoys be made and placed?

    Believable, and with no rights, so a use is both an alert and harmless. Put them where a leak would put them, such as a configuration backup, and not where real code reads.

    From the lesson Alerting and first-hour incident response

  310. What are the five jobs of the first hour of incident response, and why in that order?

    Declare and assign, contain, keep the evidence, rotate secrets and sessions, and decide who is told. The order follows what cannot be undone: evidence is copied while it still exists, secrets are replaced from a clean place, and notices come last, when the facts are known. A09 points to NIST SP 800-61, whose Revision 3 places incident response inside risk management.

    From the lesson Alerting and first-hour incident response

  311. Which three failings does OWASP's A10:2025 name, and what controls answer them?

    The application does not prevent the unusual situation, does not notice it while it happens, or responds badly or not at all. Controls: strict validation and limits on size, count and time (ASVS 5.0.0 2.2.1); logging unexpected errors, counting repeats and alerting on a rate (16.3.4); refusing, answering generically and rolling back (16.5.1, 16.5.3). OWASP's test: any time the code is unsure of its next instruction, an exceptional condition has been mishandled.

    From the lesson Fail closed: error handling that does not leak

  312. What does it mean to fail closed, and what is the opposite?

    When a check cannot decide, the answer is no: allow only on an explicit yes. The opposite is to fail open (CWE-636). In the lesson the weak refund route allowed 5 of 5 undecided requests, fixing only the catch block still let 2 of 5 through, and the route that accepts only an object whose allow is the boolean true allowed none.

    From the lesson Fail closed: error handling that does not leak

  313. Why write the condition you accept and not the one you reject?

    answer.allow !== false reads a missing field or a proxy's error page as a yes, while answer.allow === true lets everything else fall through to the refusal. The same goes for limits: NaN > 5000 is false, so the limit never fires; write !(amount > 0 && amount <= limit), which refuses NaN, a missing value and a negative number in one line.

    From the lesson Fail closed: error handling that does not leak

  314. What does ASVS 5.0.0 16.5.2 ask for, and what may degrade when a dependency fails?

    That the application keeps operating securely when an external resource fails, for example with circuit breakers or graceful degradation. Degrade features, never checks: a check on who may act fails closed, a step that moves money fails closed and is retried with an idempotency key, and an optional box may be left out or served from its last answer.

    From the lesson Fail closed: error handling that does not leak

  315. What should an API send for an unexpected error, and what stays in the log?

    A problem document (RFC 9457, application/problem+json) with a generic title, the status and an instance ID, such as a generic 500 of type about:blank. The stack, query and connection string stay in the server log under the same correlation ID. One central handler builds every error response, routes throw instead of answering, and a leak check fails the build on any body holding a stack frame, query, connection string or path.

    From the lesson Fail closed: error handling that does not leak

  316. How should a log treat many identical errors?

    Neither flood nor drop them: write the first in full, then output repeats above a rate as statistics saying how often they happened and in what time span. In the lesson 143 events became 8 lines, one alert fired at the 50th occurrence, and the rare errors (a template with a missing field, a disk at 91 %, an unknown webhook event) stayed visible in full.

    From the lesson Fail closed: error handling that does not leak

  317. What does a last-resort handler do after an uncaught exception in Node.js?

    Node treats an unhandled promise rejection as an uncaught exception by default, and after an uncaught exception the application is in an undefined state. Log it, release resources synchronously, exit, and let a supervisor start a fresh process.

    From the lesson Fail closed: error handling that does not leak

  318. How should code treat missing, extra and null values?

    Decide each case before the language does: name and bound every field, refuse fields you did not name, and check what every lookup returned. CWE-234 is a missing parameter, CWE-235 an extra one, CWE-252 an unchecked return value and CWE-476 a null used as if it held something. Answer 400 when the body is not a JSON object, 422 when it breaks a rule, 404 when the order does not exist, and never repeat what the client sent.

    From the lesson Fail closed: error handling that does not leak

  319. What are a partial failure and an atomic operation?

    A partial failure stops an operation between its steps, so some happened and others did not: a transfer written as three separate statements left 60 and 0 when the connection dropped after the debit, and no audit row after the credit, which was broken in 2 of 5 runs. An atomic operation completes every step or leaves no trace (ASVS 5.0.0 2.3.3). OWASP's third A10:2025 scenario is an attacker interrupting a multi-step transaction.

    From the lesson Atomic operations and partial failure

  320. What does a database transaction do for a multi-step operation?

    The statements between the start and the COMMIT take effect together, and a ROLLBACK, or a lost connection before the commit, discards all of them; the fixed transfer ended in one of the two good states every time. In Python's sqlite3 it is one with db: block. Check your driver's transaction mode: Python 3.14 still defaults to legacy transaction control.

    From the lesson Atomic operations and partial failure

  321. What can a database transaction not cover?

    A reply lost after the commit, where the data is right but the caller sees an error and a retry would pay twice, and any operation that spans more than one system, such as a message broker, a payment provider or an email. Those need an outbox row, compensating actions, idempotency keys, cleanup and failure injection.

    From the lesson Atomic operations and partial failure

  322. What are an outbox row, a compensating action and an idempotency key?

    The business change and its outbox row commit together in one transaction, and the row is delivered afterwards, so the database and the broker cannot disagree. A compensating action undoes a step that already committed by doing a new step, such as a refund. An idempotency key lets a retried request return the first result and repeat nothing.

    From the lesson Atomic operations and partial failure

  323. What do cleanup in finally and failure injection add?

    Cleanup in finally releases connections, locks and files on every exit path. Failure injection makes each step fail on purpose and checks what the operation promised.

    From the lesson Atomic operations and partial failure

  324. What is resource exhaustion, and which CWE names its cause?

    Requests use up something the service shares: CPU time, memory, connections, disk or a paid quota. A bug, a retry loop or one large customer causes it as easily as an attacker does. CWE-770 is allocation of resources without limits or throttling, and OWASP's A10:2025 says nothing in information technology should be limitless.

    From the lesson Resource exhaustion, limits and ReDoS

  325. Why do limits matter most near capacity?

    A server slows down fast there. In the single-queue model with 10 ms of service, 90 arrivals a second gave an average request time of 100 ms, ten times the service time, and 99 arrivals a second gave 1,000 ms, a hundred times.

    From the lesson Resource exhaustion, limits and ReDoS

  326. Which limits does a plain Node.js server decide, and which does it leave to you?

    It has values for headers (60 s), a whole request (300 s), keep-alive (5 s) and header size (16 KiB). The socket timeout and the requests per connection are off, and the body has no setting at all, because the server hands your code a stream; a 1 MiB count that adds whole chunks stopped after 2 MiB.

    From the lesson Resource exhaustion, limits and ReDoS

  327. Name the six kinds of limit the lesson covers.

    A size limit (refuse a body, header or URL above a number of bytes before reading it); a shape limit (nesting depth, item counts, string lengths); a time limit; a concurrency limit (cap simultaneous requests of one kind and shed the rest with a 503); a ReDoS defence (rewrite the pattern, cap the input, a linear-time engine or a deadline in an isolated worker); and a decompression limit.

    From the lesson Resource exhaustion, limits and ReDoS

  328. List the ten risks of the OWASP API Security Top 10:2023.

    API1 Broken Object Level Authorization, API2 Broken Authentication, API3 Broken Object Property Level Authorization, API4 Unrestricted Resource Consumption, API5 Broken Function Level Authorization, API6 Unrestricted Access to Sensitive Business Flows, API7 Server Side Request Forgery, API8 Security Misconfiguration, API9 Improper Inventory Management and API10 Unsafe Consumption of APIs.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  329. Why does the 2023 list merge excessive data exposure and mass assignment into API3?

    Both have one root cause: nothing decides which properties a role may read or write. On the way in, a closed schema stops a caller writing a field the description does not list; on the way out, named fields stop a database row leaking a field that was never meant to leave. Both read one schema.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  330. Why treat an OpenAPI description as a security control and not only documentation?

    A reviewer, a test and a gateway can all read it, so it is a control once something enforces it. Make it precise enough for a program to review: a bound on every value (maximum, maxItems, maxLength), a closed schema for every body (additionalProperties: false), and a security entry and the refusal statuses for every operation. The lesson's first description had 16 gaps in 7 operations.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  331. Which statuses does a request gate answer for a bad body?

    415 for the wrong content type, 413 for a body above the size limit, 400 for text that is not JSON, and 422 for a rule the schema breaks, with the field and the rule in the message. The handler runs only for a body that passed all the checks, and a real server stops reading at the limit. In the lesson the gate refused 6 of 6 bad requests while the weak route accepted 5 and crashed on one.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  332. Does a body that passes the schema gate get through authorisation?

    No: a valid body is not an allowed action. The schema answers about shape, and the handler still decides owner, role and rules. A gate should also fail closed about itself, because a validator that skips keywords it does not know passes what it cannot check. In JSON Schema 2020-12, unevaluatedProperties: false sees the properties of every part of an allOf, where additionalProperties: false counts them as extra.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  333. What are shadow, zombie and deprecated APIs, and how do you find them?

    A shadow API answers and is not documented. A zombie API is an old version that still answers and that nobody documents. A deprecated route is an old version that is documented and on its way out, the healthy way to carry one. Compare the documented routes with those the running service answers, taken from its router, in CI: the lesson found 13 answering against 8 documented. An API catalog at /.well-known/api-catalog (RFC 9727) helps.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  334. How do you retire an old API version?

    In phases: the Deprecation header (RFC 9745) says that a route is deprecated and the Sunset header (RFC 8594) says when it will stop answering. For each host and version keep four answers: which environment it is, who may reach it, which version runs, and when it is retired. Keep a method allowlist with 405 for every other method (ASVS 5.0.0 4.1.4).

    From the lesson Reviewing a REST API against the OWASP API Top 10

  335. What is unsafe consumption of APIs (API10), and how do you treat a partner's answer?

    Trusting a partner's answer more than user input, though a partner can be wrong, slow, hacked or replaced by a redirect. Treat it as input: a deadline, no automatic redirect to a host you did not choose, a size limit, a checked status and content type, only a JSON object, and only the fields you need with their types and bounds. The weak client in the lesson sent the customer's address to a second host.

    From the lesson Reviewing a REST API against the OWASP API Top 10

  336. What changes after a WebSocket upgrade, and how can a server respond to a message?

    The socket starts as an ordinary HTTP request that asks to upgrade; after that there are no request lines, headers, cookies or status codes, and a message is only data. The server can ignore a message, send an error message of its own, or close the connection with a close code such as 1008 for a policy violation. The access log holds one line for the whole conversation.

    From the lesson WebSocket security: identity, messages and limits

  337. Where does a WebSocket server decide, and what does the handshake check?

    At the handshake, at the first message and at every message after it. The handshake is an HTTP request that can be judged as one: require wss (ASVS 5.0.0 4.4.1) and compare Origin exactly with a list of your own origins (4.4.2, RFC 6455 section 10.2). Libraries do not do it by default: Python's websockets checks Origin only with its origins option, and Node's ws leaves it to your code in the upgrade event.

    From the lesson WebSocket security: identity, messages and limits

  338. How does a server learn who is connecting, and who is the sender of a later message?

    The protocol has no authentication of its own, so the first message carries a one-time ticket that the page fetched over HTTPS. After that the sender of every message is the user bound to the connection and never a field of the message.

    From the lesson WebSocket security: identity, messages and limits

  339. Which four habits make a chat server safe message by message?

    The sender is the user bound to the connection; each message type has a closed shape, found with Object.hasOwn, so an unknown type or field, a missing field or a wrong type is refused; a room name is checked against the user's rooms from the server's own data; and an action that needs a role asks for the role the server holds. The weak server did 5 of 5 forbidden things for an ordinary member, the fixed one none.

    From the lesson WebSocket security: identity, messages and limits

  340. What must the server bound for each connection?

    What one connection can use: limits on message size, message rate and queues, with sockets closed when a session or a role changes. OWASP's WebSocket cheat sheet lists connection exhaustion and gaps in monitoring among the risks.

    From the lesson WebSocket security: identity, messages and limits

  341. Why does GraphQL move security decisions into the schema?

    A REST route has a price that the route fixes, but a GraphQL endpoint has one URL and the client writes the shape of the answer. The schema must therefore decide what a request may cost, who may read each field, what the endpoint shows a stranger and which HTTP requests may reach it. The client chooses the cost, so the server has to measure a request before it runs it.

    From the lesson GraphQL security: cost, authorisation and exposure

  342. How expensive can a short GraphQL document be?

    In the lesson a dashboard query cost 22 resolver calls, a nine-level cycle query of 94 characters cost 61,106 (every two more levels multiply the work by ten), and a shallow request with 100 aliases of one list cost 10,600. The fixed server measured both before running anything and refused them with a readable reason, while still answering the ordinary documents.

    From the lesson GraphQL security: cost, authorisation and exposure

  343. Name the six controls the GraphQL lesson builds on.

    Demand limits on depth, aliases, page size and cost, which refuse a document before any resolver runs; one authorisation policy that every resolver asks; introspection, field suggestions and error detail switched off in production; a budget for each account, not each request; refusing mutations by GET and bodies other than application/json; and trusted documents, so production runs only the documents your team built.

    From the lesson GraphQL security: cost, authorisation and exposure

  344. Why can a GraphQL schema let a short query explode in size?

    Fields can lead back to where they started, since an author has books and a book has an author. The schema allows that cycle and nothing in the language limits how many times a client follows it.

    From the lesson GraphQL security: cost, authorisation and exposure

  345. How does a SAML 2.0 browser sign-in work, and which bindings carry its messages?

    The service provider (your app) redirects the browser to the identity provider with a request, and the IdP answers with a signed assertion that the browser carries back; the two servers never talk during the sign-in. The request goes by the HTTP-Redirect binding (in the URL, deflated and base64 encoded) and the response by HTTP-POST (a hidden form field posted to the assertion consumer service). Neither binding says who the browser is.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  346. Why are unsolicited, IdP-initiated SAML responses off by default?

    They answer no request, so InResponseTo is absent and nothing ties the response to the browser that posts it: an outsider can post a response made for the outsider's own account into a victim's browser (login CSRF), and protection against replay rests on assertion IDs alone. OWASP's SAML cheat sheet calls the flow less secure by design. Answer a portal tile with a link to the app's own start address.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  347. What does SAML metadata pin for one connection, and what should the app refuse?

    The entityID (the name the IdP signs under, compared with every Issuer), the SingleSignOnService (where to send the request, by which binding), the KeyDescriptor use="signing" (the certificate that verifies its signatures) and validUntil and cacheDuration. Refuse another entityID, no or too distant validUntil, http endpoints, a file with only an encryption key, and a DOCTYPE. Keep both keys during a rollover, and never verify with a certificate that arrived in the message.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  348. Which eight checks does a verified SAML response still need?

    The Issuer is this connection's IdP; Destination is this ACS; Recipient is this ACS; the confirmation's NotOnOrAfter has not passed, within the skew; InResponseTo is a request this app sent, used once; NotBefore and NotOnOrAfter hold and every condition is understood; the audience includes this app's entityID; and the assertion ID is new. The signature proves who sent the response, the checks prove it is meant for this app, moment and sign-in.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  349. How much clock skew should the time checks allow?

    A few minutes: the SAML2Int profile asks deployments to allow three to five. The lesson allows three, 180 seconds, and accepted a response that expired 179 seconds ago while refusing one that expired 180. A longer allowance widens the window in which a stolen response works.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  350. How long must the replay memory keep an assertion ID, and what must the write be?

    For as long as the assertion could be accepted: its NotOnOrAfter plus the skew, which is 240 plus 180, or 420 seconds in the lesson, about 21,000 IDs at 50 sign-ins a second. With several instances it lives in a shared store, and the write must be one step that fails if the ID exists, because a read followed by a write lets two instances both pass. For unsolicited responses it is the only check left.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  351. Why should RelayState never hold the address to return to?

    It travels with the request and comes back unchanged, but it is not part of the signed assertion, the bindings limit it to 80 bytes, and nothing protects its pairing with a message. It is input from outside that can steer a redirect. Send a random handle and keep the wanted path on the server as one of your known routes, accept the handle once, for its request, within ten minutes, and send anything else to the home page, because a bad RelayState must not fail a verified sign-in.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  352. What belongs to the app after a SAML response passes every check?

    A new session ID at sign-in (ASVS 7.2.4); a lifetime that ends at the earlier of SessionNotOnOrAfter and the app's own maximum; and a logout that deletes the server-side session first, because single logout depends on a browser staying open and a message arriving. For a logout request in a URL, verify the signature over the raw octets as received, then inflate under a size cap.

    From the lesson SAML 2.0 SSO flows, bindings and metadata

  353. What is SAML signature wrapping?

    A gap between the element that a signature check verifies and the element that the application reads. An XML signature signs the element its Reference names by ID, wherever it sits, so a rearranged document can pass the check while the code reads another, unsigned assertion. In 2012 researchers found critical wrapping flaws in 11 of 14 SAML frameworks. The weakness is in the code after the check, not in the cryptography.

    From the lesson SAML signature wrapping and XML signature defences

  354. What one rule closes signature wrapping?

    The function that verifies the signature returns the verified element, and nothing else reads the original tree (SignXML's documentation: trust only the data that verify() returns). In the lesson the first draft signed in as the wrong name in 2 of 5 documents, and the consumer of the verified element never did, since the worst it can be given is an identity the identity provider really vouched for.

    From the lesson SAML signature wrapping and XML signature defences

  355. Why also refuse documents that can be read two ways?

    Reading only the verified element makes the outcome safe; refusing ambiguity, such as several assertions or a comment inside a name, makes the attempt visible in a log. The third consumer in the lesson refused the three documents with more than one reading and accepted only the ordinary one.

    From the lesson SAML signature wrapping and XML signature defences

  356. Which five further XML signature defences does the lesson name?

    Pin the key: trust only the key in the connection's metadata, never one in the message. An algorithm allowlist, such as rsa-sha256 only. An expected place: one Reference, to one assertion, in one position. A gate that refuses ambiguous documents before anything is trusted. And key rollover: publish a new signing key beside the old one, so that no sign-in fails and no unknown key is trusted.

    From the lesson SAML signature wrapping and XML signature defences

  357. What identifies an account in multi-tenant SSO, and what is the e-mail address?

    The tenant that owns the connection the response arrived on, plus the issuer and the subject inside that tenant. The address is an attribute that can change and a hint for routing, never the account. In the lesson, matching on the address put two different people into one account twice, split one person across two accounts and let a sign-in at one customer land in another's account; tenant, issuer and subject made none of these mistakes.

    From the lesson Multi-tenant SSO and account linking

  358. Where does the tenant of a login come from?

    It is a fact about the connection the response arrived on, not about the address. Domain routing sends a login to a tenant's provider only when the tenant has proved that it controls the domain of the address.

    From the lesson Multi-tenant SSO and account linking

  359. Which four parts of the multi-tenant SSO design follow from the same idea?

    Domain routing on a proved domain; SSO enforcement, which closes every other way in for a tenant that requires single sign-on; per-connection trust, with each tenant's own keys, entity ID and ACS address, so a response made for one tenant is useless at another; and role mapping, turning groups in a tenant's directory into application roles through a table that the tenant owns.

    From the lesson Multi-tenant SSO and account linking

  360. Why is an address never a reason to join accounts?

    An address can change, as Asha's did, and can be reassigned, so a newcomer may hold her old one. The tenant, issuer and subject design held the newcomer whose address belonged to an existing account. Matching on the subject alone is no better, since another provider may use the same subject (s-1) for someone else. The mistake has shipped: authentik once linked a provisioned user to any local account with the same user name (CVE-2026-72537).

    From the lesson Multi-tenant SSO and account linking

  361. What is SCIM, and which RFCs define it?

    The standard way for an identity provider to push users and groups to an application: RFC 7643 specifies the resources, and RFC 7644 specifies the REST protocol. Each customer sets up a provisioning connection to your service, and the protocol leaves multi-tenancy to you.

    From the lesson SCIM 2.0 endpoints that keep tenants apart

  362. Where must the tenant of a SCIM request come from?

    From the credential that authenticated the request (RFC 7644 says the service may infer the tenant from how the client authenticated), never from the URL. Begin every lookup in that tenant's rows. In the lesson a service that took the tenant from the URL and found users by ID alone let one customer reach another's users in 5 of 9 requests; the fixed service in none.

    From the lesson SCIM 2.0 endpoints that keep tenants apart

  363. What does the fixed SCIM service answer for another tenant's ID, and for a URL that names another tenant?

    404 for an ID of another tenant, exactly as for one that does not exist, and 403 for a URL that named another tenant. The weak service also leaked through a 409 that told Acme a Globex user existed.

    From the lesson SCIM 2.0 endpoints that keep tenants apart

  364. Which four parts of the SCIM design follow from taking the tenant from the credential?

    Credential hygiene: each connection its own token, stored as a hash, accepted on the SCIM routes alone, and swapped for a new one during a period when both work. Filter compilation: parse the filter into a tree, map attributes through an allowlist and bind every value. Mutability rules, so a PATCH cannot change an ID, an immutable value or a role. And limits on page sizes, bulk requests and request rates, with personal data kept out of URLs and logs.

    From the lesson SCIM 2.0 endpoints that keep tenants apart

  365. What is deprovisioning, and what does marking a user inactive stop?

    The work of ending a person's access when they leave or lose the right to it, one event in the life of an account: a joiner arrives, a mover changes team and a leaver goes. A SCIM request sets active to false, and RFC 7643 says the service provider decides what that means. In the lesson a flag on the user stopped only the new password sign-in, and all 9 credentials the person already held kept working.

    From the lesson Deprovisioning that ends access everywhere

  366. Which credentials can outlive a bare deactivation?

    A session; an API key; an access token and a refresh token; a grant to another app; a nightly job; an open connection; and a sign-in link or an invitation. A list of revocations left 4 of the 9 working: the access token (self-contained, so valid for its last 10 minutes), the open connection, the invitation and the sign-in link. ASVS 7.4.2 asks that all active sessions end when an account is disabled or deleted.

    From the lesson Deprovisioning that ends access everywhere

  367. How does an epoch end every credential with one write?

    A number on the user and on every credential: deactivation marks the person inactive and raises the epoch in one write, and every check compares the credential's epoch with the person's current one, so all 9 credentials were refused before anything was deleted. Clean-up after that can fail: when the grant service was down, the list of revocations left 6 of 9 working and the epoch design none.

    From the lesson Deprovisioning that ends access everywhere

  368. Which four more parts does the deprovisioning lesson add?

    Sources of leavers: how your service learns of a leaver when the provider reports nothing. Movers: keep roles in step with groups, and apply the change to a session that is open. Return and reuse: a reactivated person and a reused name start clean. And an audit trail that records each change without the personal data.

    From the lesson Deprovisioning that ends access everywhere

  369. Why is there no equivalent of a parameterised query for prompt injection?

    The system prompt, the user's message, a retrieved page, a tool result and the earlier turns are all put into one context window, and the model reads them as a single sequence of tokens: OWASP's 2026 list says models make no architectural distinction between instructions and data. The UK's NCSC calls this an inherently confusable deputy and expects the risk to be reduced, perhaps never removed.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  370. Which three properties of a deployment make prompt injection worse?

    Context pooling: nothing enforces a boundary between your prompt and a stranger's text. Memory persistence: an injection written into a vector store or memory is read again in every later session, so a write to memory is a privileged action. Agentic execution: the output drives tool calls, so the damage reaches whatever the tools can reach, and tool results come back into the window.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  371. Into which three trust levels does OWASP sort the text a model reads?

    Untrusted (anyone on the internet: public web pages, emails from unknown senders, search results); semi-trusted (a platform you trust, written by people you do not: issue titles, package readmes, third-party API responses); and trusted but writable (your own systems where an outsider may have left text: internal documents, tickets copied into a knowledge base). Teams forget the third.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  372. Which rules does a design review apply to the data-flow diagram of an LLM feature?

    Every flow into a tool needs a checked call; any tool that sends or changes something needs a person's confirmation; text bound for a renderer needs encoding; private data bound for a log needs redaction; a secret must not enter the context; and every flow that carries outsider text needs a limit on size and cost. The review asks what each flow may carry and where it may land, not whether the model would obey a planted sentence.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  373. List the OWASP Top 10 for LLM Applications 2026.

    LLM01 Prompt Injection, LLM02 Sensitive Information Disclosure, LLM03 Excessive Agency, LLM04 Supply Chain, LLM05 Data and Model Poisoning, LLM06 Unbounded Consumption, LLM07 Misinformation, LLM08 Hidden Context Exposure, LLM09 Vector and Embedding Weaknesses and LLM10 Improper Output Handling.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  374. How did the numbering change between the 2025 and 2026 editions, and how should a report cite a code?

    Only LLM01 and LLM02 name the same entry in both editions, so eight of the ten codes changed meaning: Excessive Agency climbed from sixth to third, Unbounded Consumption rose four places, Improper Output Handling fell from fifth to tenth, and System Prompt Leakage became Hidden Context Exposure. LLM06 is Excessive Agency in 2025 and Unbounded Consumption in 2026, so write the year with the code, as in LLM06:2026.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  375. When does the Agentic list apply as well as the LLM list?

    The LLM list owns the risk while the model is a component inside your application. Once the model is an actor, with tools it can call, memory it carries between sessions and consequences it sets in motion downstream, the risk moves to the OWASP Top 10 for Agentic Applications (agent goal hijack, tool misuse, identity and privilege abuse, and others). For an agent, read both lists.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  376. Why is the defence against prompt injection architectural, and what is the lethal trifecta?

    Nothing available today prevents prompt injection reliably, so assume the line will be crossed and limit what the model may do and what its output may reach. A study of twelve published defences found that adaptive attackers beat most of them more than 90 % of the time, so a filter is one layer. An agent that reads untrusted content, can reach sensitive data and can change state or communicate externally has the conditions for high-impact exploitation (Willison's lethal trifecta, Meta's Rule of Two): remove one leg, or put a person's confirmation in front of each action.

    From the lesson Threat model for LLM features (OWASP LLM Top 10)

  377. What is unsafe model output, and what rule fixes it?

    A reply that an application passes to a browser, a query, a shell, a file system, a tool or a terminal without treating it as untrusted (LLM10:2026 Improper Output Handling). What a model writes can be steered by what it read, so using it unchecked gives whoever steered it indirect access to the code that receives it. Treat the model like any other user: validate what it sends and encode what you show.

    From the lesson Prompt injection and unsafe model output

  378. Which control fits each place a model reply lands?

    HTML page: encode. Database query: parameterise. Tool call: validate against an allowlist and a schema, with the user taken from the session. File or shell: contain, with names kept in a folder and commands out of a shell. Image or link: never fetch by itself, so data stays out of an address. Terminal or log: strip control characters, shown as visible escapes.

    From the lesson Prompt injection and unsafe model output

  379. What are the two doors of prompt injection, and what does your code see through either?

    Direct: the user, or someone on the user's path, supplies the text in the message. Indirect: a stranger the user never meets supplies it in a web page, email, retrieved document, tool result or issue title. Either way your code sees only the reply. The chance that a model is argued into a particular reply is a question of probability that you cannot settle; what your page does with the reply is deterministic and testable.

    From the lesson Prompt injection and unsafe model output

  380. How can a Markdown image in a chat reply leak data without a click?

    The page renders the reply, the browser fetches the image, and the address ends in an order number, so the number has left the building. In the lesson the weak page let 5 of 8 scripted replies act (a script element, an event handler, an image fetched with the order number in its address, a link that runs script, a terminal control); the fixed page let none.

    From the lesson Prompt injection and unsafe model output

  381. How do you test a chat page's output handling without a live model?

    With a stand-in model that returns scripted replies, ordinary ones and ones shaped like trouble with harmless markers, a reserved host name and a made-up order number, and read the page's output for what a browser or terminal would do. The fixed page encoded each reply and showed control characters as visible escapes, at the cost that Markdown such as bold text shows as typed.

    From the lesson Prompt injection and unsafe model output

  382. Which three limits hold when someone bends a model's instructions?

    Agency limits what it can do: which tools, with what rights, and which actions wait for a person. RAG data access limits what it can read: documents are filtered by the asker's permissions before anything reaches the model. Cost limits bound what it can spend: tokens, tool calls, time and money for a run, a user and a day. All three are written in code outside the model.

  383. Where do OWASP's 2026 entries place excessive agency and weak RAG data access?

    Excessive Agency is LLM03:2026 and comes from excessive functionality, excessive permissions or excessive autonomy, letting damaging actions follow from an unexpected or manipulated reply. Weak RAG data access appears in LLM09:2026, where a similarity search runs across a shared index before any permission is applied.

  384. What is LLM06:2026 Unbounded Consumption, and what is cost asymmetry?

    Missing cost limits. Cost asymmetry means an attacker can trigger expensive computation at little cost to themselves, and a buggy loop does it by accident. The simplest limit is a cap on steps, decided in code before the model runs; the other limits need the same kind of decision.

  385. Why does an assistant loop cost more than linearly in its steps?

    Each call sends the whole context again, so the input grows by every reply and tool result that came before. In the lesson's made-up units, 5 steps cost 27.0, 10 steps cost 81.5, 40 steps 986.0 and 80 steps 3,732.0, which is 138 times the five-step run; a cap of 12 steps stops the same loop at 111.0.

  386. What does each kind of security test read, and what does it miss?

    SAST reads source code and misses deployed settings and intent. SCA reads the lockfile against advisories and misses whether your code reaches the flaw. Secret scanning reads files and history and misses secrets that look ordinary. DAST probes a running copy from outside and misses code the crawl never reaches and logic flaws. IAST watches a running copy from inside and misses what the tests do not run. Fuzzing and property tests feed generated inputs to a function and miss anything the invariants do not say.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  387. What do none of the security tools read?

    Intent: who may open an invoice, whether a coupon can be applied twice, whether the design lets one customer act as another. Those need a threat model, review and tests you write; A06:2025 asks for tests of critical flows against the threat model. The Web Security Testing Guide 4.2 lists twelve groups of tests, and no single tool covers all twelve.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  388. What are precision and recall for a static rule, and how do you find them?

    Precision is the share of its findings that are right, and recall is the share of the real problems it finds. You cannot know either from documentation, so measure them on labelled code. In the lesson a text search found 13 of 14 real problems at a precision of 62 %, and a syntax-tree rule found 12 of 14 at 86 %, missing run(cmd, shell=True) after from subprocess import run.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  389. Where in a pipeline does each kind of security test run?

    A secret scan before the commit and again on each push, since a key that gets into the history never leaves it. SAST and SCA on a pull request, where the diff is small. Scans of images and infrastructure files when those files change. At night, a passive baseline scan of a copy used for testing, and slower scans before a release.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  390. Which four habits keep security gates from drowning people?

    Gate on new findings of high severity and keep a baseline of the old ones; fail fast and in plain words, naming a file, a rule and a fix; review suppressions, each with a reason and an expiry; and measure the tools by how many of their findings were real and how long it takes to go from alert to fix.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  391. What makes a regression test for a security fix strong?

    It fails on the code before the fix and passes on the code after it, and has three parts: attacking inputs that fail on every weak version, ordinary inputs that fail on every over-strict one, and one shared fixture of harmless canary inputs reused for every target. In the lesson a half fix that refused only names starting with ../ still had 2 path problems, and a fix that refused every name with a dot had 3.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  392. How do property-based tests and fuzzing find what chosen examples miss?

    A property names a rule that all inputs must obey, many inputs are generated from a printed seed, and a shrinker cuts a failing input to the smallest that still fails. An encoder that forgot > failed on the first case, shrunk to >; a path function that refused names starting with .. held for 93 cases and failed on case 94, shrunk to /.. . The counterexample becomes the canary of the next regression test, and a property can only say what you state.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  393. What is the order of triage for a scanner finding?

    Reproduce it in a copy you own; decide whether it is a true positive, false positive or accepted risk, and name its CWE; fix the cause, because two alerts that share a cause need one fix; prove it with the regression test that failed first and a new scan; and suppress only a finding that is still false, with a reason, an owner and a date or release for review. A scanner can be quiet because it no longer reaches the page.

    From the lesson Security testing toolbox: SAST, DAST, SCA, secrets

  394. What does the ZAP baseline scan do, and why does it suit a pull-request pipeline?

    It runs ZAP's spider against a running copy for one minute by default, lets the passive rules read every response (headers, cookies, forms, scripts, comments) and reports with an exit code. It sends no attack and takes a few minutes at most. The spider follows links and posts forms with default values, so scan a copy you own.

    From the lesson OWASP ZAP baseline scans in CI

  395. Why can a fixed build still exit with code 2?

    Every alert counts as a warning unless the rules file says otherwise, informational ones included. The fixed build's report held only two informational alerts, about a recognised sign-in request and session cookie, and still exited with 2. The option -I, or two IGNORE lines in the rules file, brings the code to 0; a rule that raised nothing counts as a pass.

    From the lesson OWASP ZAP baseline scans in CI

  396. What do the four rule levels IGNORE, INFO, WARN and FAIL mean in a ZAP rules file?

    By default every rule is WARN, and a rule the file does not name counts as a warning. IGNORE records that the team decided a rule does not matter here, INFO lists a rule without counting it, and FAIL marks a rule that must not appear.

    From the lesson OWASP ZAP baseline scans in CI

  397. What do the baseline script's exit codes 0, 1, 2 and 3 mean?

    0: no FAIL, and no WARN or -I was given. 1: a rule at FAIL raised an alert, so stop. 2: a WARN and no FAIL, so stop or go on by choice. 3: any other failure, such as a rules file that would not load or a target that returned no pages. With -I the code 2 no longer occurs. A first gate: leave rules at WARN, scan with -I, and move a rule to FAIL once its alerts are gone.

    From the lesson OWASP ZAP baseline scans in CI

  398. What can a clean baseline scan not tell you?

    It cannot find a flaw that needs an attack to show itself: SQL injection, stored cross-site scripting, a missing access check on another customer's order, a broken business rule. Those need an active scan, an authenticated scan and tests you write. A clean result means only that no cheap mistake was found on the pages the crawl reached.

    From the lesson OWASP ZAP baseline scans in CI

  399. How does a ZAP active scan differ from the baseline scan?

    An active scan attacks: it sends requests built to provoke a flaw to every parameter it knows, so it runs only against a copy you own, with disposable data and bounds on time and threads. The baseline sends no attack. ZAP API scans import an OpenAPI, SOAP or GraphQL description and take a rules file of the same format, with the same exit codes.

    From the lesson ZAP API scans, authenticated scans and triage

  400. Why do authenticated scans matter, and why are they riskier?

    They reach the signed-in part of an application, where most of the data is, when ZAP carries a session. They are also where an active scan can do the most harm, because the attacks reach endpoints that create, change and delete data, so use a test user whose actions can do no damage, on a disposable copy.

    From the lesson ZAP API scans, authenticated scans and triage

  401. What is triage after a scan?

    Turning the alerts into decisions: each alert is reproduced, classified as a true or false positive, mapped to a CWE and to a Top 10 category, fixed, and given a regression test.

    From the lesson ZAP API scans, authenticated scans and triage

  402. What did the active scan of the vulnerable shop find, and what could it not know?

    15 alerts: three High (a SQL injection on the category parameter, and cross-site scripting on the q parameter of the search page, reported twice, as reflected and as DOM based), four Medium, five Low and three informational. None was about who may read what: the order endpoint gave any signed-in user any customer's order, which a test with two users finds at once. A scan finds what a payload can show; write tests for the rules that only your application knows.

    From the lesson ZAP API scans, authenticated scans and triage

  403. Which fields must a security.txt file have, and where does it live?

    Contact (at least once, as a mailto:, tel: or https: link, in order of preference) and Expires (exactly once, an RFC 3339 timestamp, less than a year ahead), as RFC 9116 defines it. It is served at /.well-known/security.txt over HTTPS as plain text and speaks for the host that serves it, not for subdomains. Optional fields include Policy, Acknowledgments, Preferred-Languages, Encryption (a link, never the key) and Canonical.

    From the lesson Receiving vulnerability reports well

  404. Why is a stale security.txt harmful, and how do you prevent it?

    RFC 9116 says data past its Expires should not be used, and no file may be better than one with old contacts, since a report sent to a dead address is a report lost. Lint the file on every change and once a week, because an Expires date passes without anyone touching the file. A typo in a field name is only a warning, since readers ignore fields they do not know.

    From the lesson Receiving vulnerability reports well

  405. What six parts does a one-page disclosure policy hold?

    Scope (with out-of-scope named); how to report; what you do and by when; what is not allowed; credit; and legal safety, a safe harbour. A safe harbour is a promise from you, so it binds only you: it cannot speak for a hosting provider or a customer, so have a lawyer read the wording. The numbers matter most, since a reporter told "within 2 business days" knows when to write again. Whether a researcher may test belongs in the policy, because the file settles nothing.

    From the lesson Receiving vulnerability reports well

  406. Through which steps does a report move, and what two rules save the most trouble?

    Acknowledge, reproduce, rate, fix with a test, let the reporter verify, release, and give credit, each with an owner and a date. Reproduce on a staging copy or on a local build, using invented data, never first on production, and acknowledge before you investigate, because the reporter cannot see your work, only your silence.

    From the lesson Receiving vulnerability reports well

  407. How are CVSS v4.0 scores labelled, and what should a score say about itself?

    A score from 0.0 to 10.0: Low 0.1 to 3.9, Medium 4.0 to 6.9, High 7.0 to 8.9, Critical from 9.0. FIRST asks that a score say which metric groups produced it: Base alone (CVSS-B), Base and Threat (CVSS-BT), Base and Environmental (CVSS-BE), or all three. A base score describes the flaw in the abstract, so add what only you know, such as which data it exposes and who can reach it.

    From the lesson Receiving vulnerability reports well

  408. What can a severity table with deadlines look like, and how are the days counted?

    One team's example, in business days to acknowledge and triage, calendar days to fix: Critical 1, 2 and 7; High 2, 5 and 30; Medium 2, 5 and 60; Low 3, 10 and 90. All are counted from the day the report arrived, so a critical report that arrives on a Friday is due an acknowledgement on Tuesday when Monday is closed. These are one team's numbers, not a standard; every table needs a row for each severity.

    From the lesson Receiving vulnerability reports well

  409. What must an advisory contain, and what is coordinated disclosure?

    The impact in a summary, the vulnerable versions, the fixed versions, caveats such as a configuration that must be on, workarounds and the CVE ID if one was assigned; where you can, a timeline, the credit (with the reporter's agreement) and technical detail, but no working exploit. Coordinated disclosure means the reporter and you keep the details private until a fix exists, then publish together, within the window your policy states (90 days is one example).

    From the lesson Receiving vulnerability reports well

  410. Where does a CVE ID come from, and when do you need one?

    From the CVE Numbering Authority whose scope covers your product; GitHub is a CNA for repositories it hosts, with a review that usually takes up to 72 hours, and it cannot assign when another CNA covers the project. A CNA of last resort covers the rest. You need an ID when other people run your software (a library, a self-hosted product, a plugin); a site only your team runs needs an advisory in your own channels. Request it early, since it does not publish the advisory.

    From the lesson Receiving vulnerability reports well

  411. What do you do when you find a flaw by accident, such as another student's marks on a portal?

    Stop at the first sign. One response that showed a stranger's record is an observation; a second, a third and a fortieth request to see how many records leak is a test that nobody allowed. Stay inside written permission, send the finding to its owner first and to a coordinator such as CERT-In if the owner is silent, and keep what you send to the least that shows the flaw.

    From the lesson Reporting a vulnerability: law, scope and CERT-In

  412. How does a programme's scope settle a planned test?

    Its rules put the line in writing: which hosts, a request rate and a limit on other people's records. In the lesson three tests were allowed (reading headers, using your own second account, scanning at the programme's limit of 5 requests a second) and five stopped at a rule: an unlisted staging host, a flood of requests, a call to a support agent, a payment provider's page, and 40 other customers' orders.

    From the lesson Reporting a vulnerability: law, scope and CERT-In

  413. Where does a finding go first, and when does a coordinator step in?

    To its owner: the address in its security.txt, the form in its policy, or its bounty programme, following that programme's rules (a GitHub project may take private reports from its Security tab once its maintainers switch the feature on). A coordinator is for the owner you cannot find or who does not answer: it locates the vendor and keeps the report private. Send one report to one place at a time and keep a copy of every message.

    From the lesson Reporting a vulnerability: law, scope and CERT-In

  414. How do you report to CERT-In, and what does it promise?

    Write to vdisclose@cert-in.org.in, encrypted with PGP if you wish, or use the form on its policy page, with the product and exact version, the vendor, a description with concise steps and evidence, and the impact, after checking that the flaw reproduces on the latest supported version. CERT-In acknowledges within 72 working hours and aims for 120 days from its first contact with the vendor. It promises no fixed deadline, no reward and no exemption from the law.

    From the lesson Reporting a vulnerability: law, scope and CERT-In

  415. What makes a report one a developer can reproduce?

    The product, the version, numbered steps and the minimal proof, the least evidence that shows the flaw is real. A finding that touches other people's data is handled by stopping, noting what you saw and telling the owner; silence is handled with a log of every attempt and the owner's stated time.

    From the lesson Reporting a vulnerability: law, scope and CERT-In

  416. What are the seven passes of the lesson's secure code review of a change?

    What does it touch? What does it read? Where does it end, in which sinks? Who may ask? What if it fails? What does it set up, in settings and packages? Would a test notice? Each pass is one question the author was not asking, and the answers are questions and findings, not a verdict. A review that reads a diff from top to bottom finds what the author was thinking about.

    From the lesson Secure code review: a repeatable method

  417. Why are deleted lines findings too?

    A diff shows what was typed, not what it undid, and readers skim the red. A removed check, test or configuration line is a finding until the author shows that the protection lives somewhere else. In the lesson a removed line held the rule that every route needed a signed-in user, and no scanner can report a line that is no longer there.

    From the lesson Secure code review: a repeatable method

  418. What is a source-to-sink trace?

    Following one input from where it enters the code (request data, uploads, environment variables, database rows, answers from other services, model output) to every sink where text becomes an action (a query, shell command, file path, page, redirect, fetch, deserialiser, template, log line, cryptographic call), asking at each hop what the code assumes and whether a check covers the form the sink receives. The better check is on the final path, resolved and compared with the folder (ASVS 5.0.0 5.3.2).

    From the lesson Secure code review: a repeatable method

  419. What is the threat-model delta a reviewer asks the author for?

    The new inputs, sinks and permissions, the removed controls, and where each check lives, because a diff cannot show that a route registered in another file is protected or that a protected-looking route is mounted before its middleware. Also read configuration changes (CORS, CSP, cookie flags), lockfile changes, removed or skipped tests, and pull requests that touch many files.

    From the lesson Secure code review: a repeatable method

  420. How do high-signal searches fit into a review?

    They find where to read, and reading decides. Search for hard-coded secrets, eval, exec and innerHTML, queries built by concatenation, shell=True, pickle.loads, yaml.load, verify=False, rejectUnauthorized: false and Object.assign with req.body. In the lesson 4 of 7 hits were flaws, 2 were fine and 1 depended on facts outside the file, and no rule reported that none of the 5 routes named a check.

    From the lesson Secure code review: a repeatable method

  421. What does a review finding need in order to get fixed?

    A place (file and line); a weakness (a CWE and the ASVS requirement with its version, such as v5.0.0-5.3.2); a rating with one sentence of why; a concrete fix; a test that fails now and passes after the fix; and a kind (must-fix, should-fix or question). One issue goes in one comment. "This looks unsafe, please fix" gives the author no place, reason or way to tell when it is fixed.

    From the lesson Secure code review: a repeatable method

  422. What should a review automate, and what should it leave to people?

    Automate the boring and repeated: secrets, known-bad calls, dependency risk and headers. Spend the reviewer's time on authorisation, business logic, design and the way components interact. Tools point to suspicious places and the core analysis relies on human judgment. Time-box each session and write down what was reviewed and what was not, so that nobody reads approved as checked everywhere.

    From the lesson Secure code review: a repeatable method

  423. How does the review clinic spend its time, and which two rules keep the plan honest?

    Six stages in 165 minutes, with the most time on following inputs and on fixes, because those find and close the most. Stop a stage when its time is up and write down what it did not reach, since an unfinished stage is information for the report. And fix nothing until the findings are ranked, because the minutes for fixes belong to the flaws that matter most.

    From the lesson Review clinic: find and fix planted flaws

  424. How does the clinic's matcher score a review?

    A finding is a line and a CWE. The matcher treats two CWEs as the same when they name one family of weakness, such as the two cookie flags, and accepts a line up to two away from the planted one. A hit earns 10 points, a false positive costs 5, and a duplicate of a flaw already found scores nothing; the planted flaws nobody found are the misses.

    From the lesson Review clinic: find and fix planted flaws

  425. Why does a long list of guesses do worse than a short list of facts?

    A false positive costs 5 points and a hit earns only 10. In the warm-up payments file a review found 3 of 5 planted flaws and scored 20: its two false positives took away 10 points, and it missed the password written to the log and the token decoded and never verified.

    From the lesson Review clinic: find and fix planted flaws

  426. What is a canary test, and what must it do on the vulnerable code and on the fixed code?

    A regression test for one flaw that sends a harmless input to the handler. It must fail on the vulnerable code, which shows that it notices the flaw, and pass on the fixed code and on the case that was always valid, so a fix that refuses everything cannot satisfy it. It stays in the suite and runs on every change.

    From the lesson Review clinic: find and fix planted flaws

  427. Why must you see a new test fail on the original code first?

    A test that passes on the vulnerable code tests nothing, and a test you never saw fail may not be looking at the flaw in the first place. Run the test on the original first, then make the fix and see it pass.

    From the lesson Review clinic: find and fix planted flaws

  428. What do the clinic's two apps hold?

    Twenty planted flaws, ten in a Node service and ten in a Python one, with at least one in every Top 10:2025 category from A01 to A10.

    From the lesson Review clinic: find and fix planted flaws

  429. Which nine habits make security routine on a small team?

    Nine: put a security section in every pull request; name code owners for risky files; run gates in CI; let a dependency bot work with a cooldown; review access and secrets every quarter; publish SECURITY.md and security.txt; keep a runbook and rehearse it with a tabletop exercise twice a year; update the threat model for each major feature; and track a few honest numbers. Each answers a failure that earlier lessons showed.

    From the lesson Making security routine on a small team

  430. What is a security routine, and how is it judged?

    The habits that keep running without anyone having to decide to run them, at rhythms from every change to twice a year. It is judged by what it blocks and by a short, honest list of what is still open. A06:2025 says secure design is neither an add-on nor a tool: it asks for a lifecycle with threat modelling, a paved road of safe defaults, tooling and post-incident reviews that improve the process.

    From the lesson Making security routine on a small team

  431. What do code owners do for risky files?

    A file in the repository that names, per path, who GitHub asks to review a change there, so a change to sign-in, payments or the pipeline does not merge without the person who knows it.

    From the lesson Making security routine on a small team

  432. What is a dependency cooldown?

    A delay between the release of a package version and the update that proposes it, so that a bad release can be noticed first and packages neither go stale nor get installed before anyone has looked at them.

    From the lesson Making security routine on a small team

Back to the Web Security (OWASP Top 10:2025) track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.