Web Security (OWASP Top 10:2025) Module 2
A01:2025 Broken Access Control interview questions
Interview questions on “A01:2025 Broken Access Control”: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher to mid
What is the difference between authentication and authorisation?
Answered in the lesson Authorisation: deny by default, enforce centrally
-
Fresher to mid
What is IDOR, and what is BOLA?
Answered in the lesson IDOR and object-level authorisation (BOLA)
-
Fresher to mid
What is the difference between object-level and function-level authorisation?
Answered in the lesson Function- and property-level access control
-
Fresher to mid
What is path traversal, and how do you prevent it?
-
Fresher to mid
What is an open redirect, and how do you prevent one?
-
Fresher to mid
What is CSRF, and how do you prevent it?
Answered in the lesson CSRF: tokens, SameSite and Fetch Metadata
-
Fresher to mid
What does CORS protect, and what does it not?
Answered in the lesson CORS: what it protects and how it goes wrong
-
Fresher to mid
What is SSRF, and how do you prevent it?
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Mid to senior
A teammate proposes moving all authorisation into the API gateway: it reads the role claim of each access token and allows or refuses by path prefix, such as /admin/* for admins only. The services behind it would do no checks. What do you think of the design, and what would you keep inside the services?
- What it tests
- Seeing the gateway as one layer rather than the decision, knowing what path-prefix rules cannot see, and keeping a deny-by-default policy layer in every service.
- First step
- Ask what the gateway can see. It has the token, the method and the path, but it cannot know who owns invoice 42, whether an order is still a draft, or which other paths reach the same handler. Path rules can answer the coarse question; everything that needs the record must be decided inside the service.
- Follow-ups
-
- The services sit on a private network that only the gateway can reach. Does that change your answer?
- How would you keep the gateway's rules and the services' rules from drifting apart?
- One service serves the same handler at /admin/users and at /internal/users. What happens?
From the lesson Authorisation: deny by default, enforce centrally
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to senior
You are starting a REST API with about 40 endpoints and three roles: customer, support and admin. How do you design authorisation so that no endpoint can ship without a decision, and how do you show that it holds?
- What it tests
- Designing one deny-by-default policy layer with policies as data, per-record rules, a single refusal convention and a matrix test that reads the route table.
- First step
- Start in the router: every endpoint registers with its policy, and the service refuses to start when one is missing, so the default is enforced by code rather than by memory. Then write the matrix, every caller against every method and path, and a test that reads the router's table, so an endpoint without a row fails the build.
- Follow-ups
-
- Where do per-record rules, such as a customer's own orders, go in this design?
- Which status code does a refusal get, and why decide it once?
- Product wants a fourth role next quarter. What changes?
From the lesson Authorisation: deny by default, enforce centrally
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Senior to staff
Your SaaS keeps 300 customer companies in one shared database, with a tenant_id column on every table. How do you make sure that no query can return another tenant's rows, even when a developer forgets the filter, and how would you prove it?
- What it tests
- Layering tenant isolation (scoped data access, database policies, connection roles), covering jobs and caches, and proving it with cross-tenant tests and monitoring rather than code review alone.
- First step
- Take the decision away from individual queries. The tenant comes from the session, never from the request, and the data-access layer adds it to every query it builds, so a handler cannot ask for rows without it. Then add a second, independent layer in the database that refuses rows of other tenants even to a query that skipped the first.
- Follow-ups
-
- Row-level security is on, but the app connects as the table's owner. What happens?
- How do background jobs and caches keep the tenant?
- Support staff must sometimes see every tenant. How do you allow that safely?
From the lesson IDOR and object-level authorisation (BOLA)
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
POST /exports takes a list of invoice ids and queues a job; a worker builds the file hours later and emails a link. How do you make sure the export contains only invoices the requester may see, and that the link reaches nobody else?
- What it tests
- Carrying the requester's identity into asynchronous work, checking at request time and again at run time, and treating the download link as a scoped, expiring permission.
- First step
- Notice that the worker runs without a request, so it has no session to check. The job must carry the requester's identity and tenant, and the worker loads each invoice through the same function the API uses, scoped to that requester, rather than by the bare ids in the queue message.
- Follow-ups
-
- The requester loses access to one customer between queueing and running. Which answer is right?
- What should the job record in its log?
- How do you test this?
From the lesson IDOR and object-level authorisation (BOLA)
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A migration adds a kycDocumentUrl column to the users table. A week later a customer reports that another user's profile in the API shows a link to that user's identity document. Walk through how this happened, and how you make sure that no future column can leak the same way.
- What it tests
- Recognising a serialiser that copies records, choosing allowlists over denylists, handling the incident, and adding contract tests that fail on any field nobody decided about.
- First step
- Find the serialiser: the profile route almost certainly returns the user record, or the record minus a few known secrets, so any new column flows to every caller the day it is added. Contain it first by removing the field from the response and expiring the document links, then fix the design so new fields are hidden by default.
- Follow-ups
-
- How do you work out whose documents were exposed, and to whom?
- The mobile team says an allowlist slows them down. What do you answer?
- Where else in the API would you look for the same field?
From the lesson Function- and property-level access control
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Senior to staff
Product wants support staff to be able to act as a customer to debug their account. How do you design this impersonation feature so that it cannot be misused quietly, and what can an impersonating agent never do?
- What it tests
- Treating impersonation as a privileged function with its own permission, scope and lifetime, keeping both identities in every decision and log, and limiting what an impersonated session may do.
- First step
- Treat it as the most powerful function in the product: it turns one person into another. Give it a permission of its own rather than the support role, check it on the function, require a ticket and a reason for each use, and keep the agent's identity next to the customer's in the session, so every later decision and log line knows both.
- Follow-ups
-
- Which actions stay blocked while impersonating?
- How does the customer learn that someone acted as them?
- How would you test the feature's limits?
From the lesson Function- and property-level access control
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Customers upload attachments, which the app saves under their original file names in one shared folder and serves back with GET /files?name=<file name>. What problems do you see with this design, and how would you redesign storage and download?
- What it tests
- Seeing path traversal, missing object-level checks, name collisions and unsafe serving in one design, and replacing user-supplied names with ids, server-generated names and safe response headers.
- First step
- List what the user controls: the stored name, its folder and the name used to fetch it. Each is a problem: a name is a path that can leave the folder, any customer can fetch any other customer's file by its name, two customers' files with one name collide, and a file served from a shared web folder may be shown or run as the browser sees fit.
- Follow-ups
-
- How do you migrate the files already stored under their original names?
- What headers do you send with a download, and why?
- Where should the files live, if not in the shared folder?
From the lesson Path traversal and safe file paths
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Senior to staff
Product wants customers to import a project by uploading a ZIP archive of up to 10,000 files. How do you design the import so that it can neither write outside its own folder nor take the service down?
- What it tests
- Checking every member before writing, ignoring stored paths where possible, limiting counts and sizes, isolating each import, and making the result appear all at once or not at all.
- First step
- Treat the archive as a list of untrusted names and sizes. Unpack into a fresh folder per import, check every member's resolved path, type and declared size before writing any, refuse links and special files, and set limits on the number of members, the total unpacked size and the compression ratio, so a small upload cannot fill a disk.
- Follow-ups
-
- How do you enforce the size limits when the archive's own size fields may be wrong?
- What does the customer see when one member is refused?
- Where does the import run, and with which rights?
From the lesson Path traversal and safe file paths
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Your OAuth authorisation server accepts any redirect_uri whose host ends with the domain a client registered. A security review flags it. What can go wrong, how should redirect URIs be matched, and what must the client's own site avoid?
- What it tests
- Seeing why suffix matching of redirect URIs fails, applying exact string matching as RFC 9700 requires, and treating an open redirect on the client's own domain as a way for codes to travel on.
- First step
- Ask who controls the hosts that match. A suffix match accepts every subdomain of the client's domain, forgotten and taken-over ones included, and the authorisation code goes wherever redirect_uri says. RFC 9700 asks for exact string matching against the registered URIs, with variable ports allowed only for loopback redirects of native apps.
- Follow-ups
-
- A client has 40 subdomains and wants one registration for all of them. What do you offer?
- The client's site has an open redirect on its own domain. Why does exact matching not protect it fully?
- How do you move existing clients from suffix matching to exact matching without breaking them?
From the lesson Open redirects and safe URL handling
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to senior
Marketing emails link to /out?url=<any address>, which records a click and redirects. Security wants the open redirect closed, and marketing does not want to lose campaign tracking. What do you build instead?
- What it tests
- Replacing raw addresses with link records the server keeps, keeping click counts, refusing unknown ids, and handling links in emails that were already sent.
- First step
- Separate the two jobs. Counting a click needs an id; choosing the destination does not need the request at all. Store each campaign link as a record with a random id and its destination, put /out/<id> in the emails, and let the route look the destination up, count the click and redirect, answering 404 for an unknown id.
- Follow-ups
-
- Emails already sent contain the old /out?url= links. What happens to them?
- Partners want to add links of their own. How do you allow that safely?
- How would you test that the route can no longer send users anywhere else?
From the lesson Open redirects and safe URL handling
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A reviewer says: "Our API accepts only JSON and our CORS rules allow only our own origin, so CSRF cannot happen here." Sessions are cookies. How do you test that claim, and what do you add whatever the result?
- What it tests
- Knowing that simple requests skip CORS, that the server and not the browser enforces a content type, and that tokens, cookie attributes and header checks do not depend on the claim.
- First step
- Ask what the server does with a body that is not JSON. A cross-site fetch() can send text/plain without a preflight, so test that from a page you own against a staging copy: if the route still parses the body and acts, the claim is false. Then list the other conditions: cookie attributes, GET handlers that change state, and the CORS rules for credentials.
- Follow-ups
-
- The route does reject other content types. Is the claim now true?
- The client already sends a custom header on every call. What does that give you, and what does it not?
- How do you keep this check from regressing?
From the lesson CSRF: tokens, SameSite and Fetch Metadata
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to staff
Your SaaS serves the app at app.example and lets each customer publish pages, with their own scripts, at name.app.example. The session cookie is SameSite=Strict and CSRF protection compares a cookie with a header. What is wrong, and what do you change?
- What it tests
- Seeing that a sibling host is same-site and can plant cookies, moving user content to a domain of its own, and choosing interim steps that need no migration.
- First step
- Ask which hosts can set cookies and start same-site requests. Every customer subdomain is the same site as the app, so Strict does not separate them, and a customer's page can write a cookie for the parent domain, which defeats a check that only compares cookie and header. List what a customer's script could do from there.
- Follow-ups
-
- Moving customer content to a new domain will take a quarter. What do you ship this week?
- Which cookie name and attributes make the session cookie hard to overwrite?
- How would you test the fix?
From the lesson CSRF: tokens, SameSite and Fetch Metadata
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
Your API echoes the request's Origin in Access-Control-Allow-Origin and sends Allow-Credentials true, because a developer once got a CORS error with a wildcard. A partner now asks you to add their site. What is wrong with the current setup, and how do you onboard partners safely?
- What it tests
- Seeing that reflecting Origin with credentials trusts every site, replacing it with an exact list of whole origins and Vary Origin, and giving partners a reviewed way in.
- First step
- Show the problem with a test before you argue. Send a request with an Origin you do not control, such as a lookalike host name on a reserved example domain, and read the answer. If your own origin comes back with credentials true, every site that a signed-in user visits can read that user's data. Then decide who really needs a cross-origin read.
- Follow-ups
-
- A partner has 40 customer sites on subdomains. Do you accept a wildcard for them?
- Some partners only need public data. What do you give them?
- How do you stop the list from growing without review?
From the lesson CORS: what it protects and how it goes wrong
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Senior to staff
Your CORS check is the regular expression ^https://[a-z0-9-]+\.shop\.example$, so that every team's subdomain works. A scan finds a subdomain whose DNS record points at a hosting service that nobody on your team owns any more. What can happen, and how do you redesign the check?
- What it tests
- Linking subdomain takeover to a rule that trusts every subdomain, replacing the pattern with whole origins, and finding stale DNS records as part of the fix.
- First step
- Treat the dangling record as live: whoever claims that name at the hosting service now runs a page on an origin that your rule accepts, and your API answers its credentialed requests. Repair or remove the record first, then find every other record that points at a service you no longer use.
- Follow-ups
-
- Hundreds of internal subdomains need access. What replaces the pattern?
- Does the SameSite attribute on the session cookie change the risk?
- How do you find dangling records before someone else does?
From the lesson CORS: what it protects and how it goes wrong
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Customers register webhook URLs, and a worker posts events to them. Design the delivery path so that a customer cannot make the worker call your internal services, and say what you log.
- What it tests
- Choosing between allowlists and judged addresses for user-chosen URLs, isolating the worker with network rules, handling redirects and responses, and logging what the worker did.
- First step
- Name what the worker can reach that customers cannot: internal services without a login, the metadata address, other tenants' hosts. Separate the worker from them first, with network rules, and add the guard in the app second: it resolves once, judges every address and posts only to the address it judged.
- Follow-ups
-
- A customer's endpoint answers with a redirect to another host. Do you follow it?
- Customers want to use their own domains, with several IP addresses each. What changes?
- A customer asks for the worker's IP addresses so that they can allow them. What do you offer?
From the lesson SSRF and safe outbound requests
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Senior to staff
A teammate fixed a link-preview SSRF like this: resolve the host with the system resolver, reject private addresses, then pass the original URL to the HTTP library. A scan still reaches an internal service now and then. Where can it get through, and what do you change?
- What it tests
- Spotting the gap between the check and the connection, answers with several addresses, redirects and URL parsers, and closing it by pinning the connection or moving the fetch behind a proxy.
- First step
- List every place where the address can change between the check and the connection: a second lookup, an answer with several addresses of which the client picks another, a redirect to a new host, and a host spelled in a way that the check and the client read differently. The scan gets through one of these, not through a missing range.
- Follow-ups
-
- The library does not let you choose the address it connects to. What are your options?
- How do you test for a changing answer without a real DNS server?
- Which logs would have shown this earlier?
From the lesson SSRF and safe outbound requests
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
All Web Security (OWASP Top 10:2025) interview questions · The Web Security (OWASP Top 10:2025) track