277 JavaScript Frontend Developer Interview Questions & Answers

133 top • 30 Amazon • 15 Apple • 29 Google • 18 Meta • 21 Microsoft • 20 Netflix • 11 NVIDIA

JavaScript Frontend Developer icon

Questions with Detailed ExplanationsWith Detailed Explanations

(Last Updated: August 28, 2026)

111. Tell me about a time you influenced a frontend decision without formal authority.BehavioralHard

Question Details

Describe a real situation where another team or senior stakeholder controlled the decision. Explain the user or engineering problem, the evidence and relationships you used, how you adapted your message to different concerns, where you compromised, what decision resulted, and how you maintained trust even if your preferred option was not fully adopted.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe a frontend decision where another team or senior stakeholder had final control, explain the user or engineering problem, show the evidence and relationships you used to influence the decision, explain how you adjusted your message for different concerns, describe where you compromised, and show how you maintained trust while helping the group reach a practical result.

Situation

In my last role, our team was building a new workflow in a JavaScript application. A senior stakeholder and another team preferred adding several interactions to one large page because they believed it would make the process feel faster. I was concerned that the page would become difficult to understand, harder to maintain, and more likely to create accessibility problems. I did not own the final product decision, so I needed to influence the direction through evidence and collaboration rather than authority.

Task

My responsibility was to represent the frontend engineering concerns while still respecting the business goal. I wanted to help the group choose an approach that was clear for users, practical for the delivery timeline, and easier for the team to support after release. I also wanted to avoid turning the discussion into a disagreement between engineering and product.

Action

I first built a small working example of the proposed page and another version that separated the most important steps more clearly. This gave us something concrete to discuss instead of debating personal preferences. I reviewed both versions with the designer and tested common keyboard and screen reader paths so I could explain the accessibility impact in simple terms. I also looked at the amount of frontend state each approach required. The larger page needed more conditions to control validation, loading states, and which sections were visible. I explained that this extra state would make future changes more difficult and could create more chances for inconsistent behavior. When I spoke with the senior stakeholder, I focused on the user flow and delivery risk instead of leading with technical details. With the engineering team, I explained the state management and maintenance concerns in more depth. I asked questions about why the larger page mattered to the stakeholder and learned that their main concern was avoiding unnecessary navigation. Based on that, I suggested a compromise. We could keep the experience inside one overall workflow while breaking the content into clear steps and preserving state between those steps. This kept the experience smooth without putting every interaction on the screen at once. I made it clear that I was not asking the group to accept my original idea exactly. My goal was to protect the important user and engineering needs while respecting the stakeholder's concern. After the group chose the compromise, I supported the decision fully and worked closely with the other team during implementation.

Result

The group adopted the stepped workflow rather than the original large page. It gave users a clearer path while still avoiding the navigation concern that had started the discussion. The frontend logic was also easier to reason about because each step had a smaller set of states and validation rules. More importantly, the discussion stayed collaborative. I learned that influencing without authority works best when I understand what each person is trying to protect, bring concrete evidence, adapt the message to the audience, and stay open to a solution that is better for the group even when it is not exactly my first choice.

Why Interviewers Ask This

Interviewers ask this question to understand whether a frontend developer can influence important technical and product decisions without relying on title or authority. A strong answer shows that the candidate can build trust, use evidence, understand different priorities, adapt communication for technical and nontechnical people, compromise when appropriate, and support the final decision professionally.

Interviewer may ask next
How did you handle resistance from the senior stakeholder when they preferred the original approach?

I avoided treating the discussion as a debate that I needed to win. I asked what problem the original approach was meant to solve and learned that the main concern was avoiding unnecessary navigation. Once I understood that, I could suggest a stepped workflow that protected that goal while also reducing complexity. Showing a working example helped because we could compare real behavior instead of arguing about opinions.

What would you do differently if you faced a similar situation now?

I would involve the stakeholder and designer even earlier, before the team became attached to one solution. I would still use a small prototype, but I would use it earlier to make the tradeoffs visible while the options were still open. That would make the conversation easier and reduce the chance that anyone feels that engineering is challenging a decision after it has already been made.

112. Tell me about a production frontend incident you helped resolve.BehavioralMedium

Question Details

Use a real incident that affected users, such as a broken release, severe JavaScript error, rendering failure, performance regression, or unavailable flow. Explain detection, impact, your role during triage, the evidence behind the mitigation and root cause, communication with stakeholders, recovery, and the preventive actions that followed.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe a production frontend incident that affected a real user flow, how you identified the impact, your responsibility during triage, the evidence you used to choose a safe mitigation, how you communicated with the team and stakeholders, how service was restored, and what changes you helped make to prevent the same problem from happening again.

Situation

In my last role, we released a frontend change to an important user flow. Soon after the release, our monitoring showed a sharp increase in client side JavaScript errors. Support also reported that some users could open the page but could not complete the final action. The backend services were healthy, so the evidence pointed to the new frontend release.

Task

I was one of the frontend developers responsible for the affected area. My immediate goal was to help restore the user flow safely, understand whether the new release caused the failure, and give the team clear information so we could make a fast decision without creating another problem.

Action

I first reproduced the issue using the same browser conditions shown in our error logs. I compared the failing release with the previous version and traced the error to a new component that expected a response field to always contain data. For some valid responses, that field was empty, which caused the component to throw an error before the user could finish the flow. I shared the evidence with the incident lead and recommended rolling back the frontend release because it was the fastest and lowest risk way to restore service. While the rollback was happening, I kept the product and support teams updated with what we knew, what we were still checking, and what users were experiencing. After recovery, I created a safer fix that handled the empty value instead of assuming the data was always present. I also added a test for that response case and worked with the team to improve our release checks so this type of client side failure would be easier to catch before production.

Result

The rollback restored the affected flow, and the corrected frontend change was released after we verified the failure case. The incident showed me that during production problems, restoring the user experience should come before trying to prove the full root cause. I also learned that frontend code must treat external data carefully, even when the normal response usually contains the expected value.

Why Interviewers Ask This

Interviewers ask this question to understand how a frontend developer behaves when real users are affected. They want to see calm troubleshooting, good judgment about mitigation, clear ownership, evidence based decisions, communication during an incident, and learning that leads to safer future releases.

Interviewer may ask next
Why did you recommend a rollback instead of fixing the code directly in production?

I recommended the rollback because we already had evidence that the new frontend release introduced the failure and the previous version was known to work. A rollback reduced user impact quickly and gave us time to create and test the real fix without the pressure of an active production incident.

What would you do differently if a similar incident happened again?

I would follow the same recovery first approach, but I would check the client side error data and recent release changes even earlier. I would also make sure important response edge cases are included in automated tests before release, especially when a component depends on data returned by another service.

113. Tell me about your path to becoming a JavaScript frontend developer.BehavioralEasy

Question Details

Give a concise account of the experiences that led you to frontend development, the kinds of browser applications or interfaces you have worked on, and the JavaScript skills you use most often. Connect your background to the role you are pursuing, distinguish your personal contribution from the team's work, and identify one area you are currently developing.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe how your interest in building browser interfaces developed through previous projects, what frontend responsibilities you took on, which JavaScript skills you used most often, how you worked with your team while owning your individual tasks, why those experiences led you toward a frontend role, and what frontend skill you are currently improving.

Situation

In my last role, I worked on web applications that had both backend services and browser based interfaces. I became more interested in the frontend work because I could see how small changes in the interface directly affected how easily people used the application. I started taking more responsibility for JavaScript features, reusable interface components, forms, and data shown in the browser.

Task

My responsibility was to build reliable frontend features from business requirements and make sure they worked well with the existing application. I also needed to coordinate with the rest of the team while being clear about the parts I personally owned. Over time, I wanted to strengthen my frontend skills and move toward a role where browser application development was my main focus.

Action

I focused on understanding the full path from a user action in the browser to the data returned by an API. I built JavaScript logic for interactive forms, validation, event handling, and updating page content when data changed. I worked with reusable components so common interface behavior did not need to be written again in several places. When connecting the interface to APIs, I handled loading states, errors, and empty results so the user received clear feedback instead of a confusing screen. I also used browser developer tools to inspect network requests, debug JavaScript problems, and check how the page behaved at different screen sizes. I discussed requirements and API behavior with teammates, but I was responsible for implementing and testing my assigned frontend work. These experiences showed me that I enjoy turning requirements into clear and usable browser experiences. I am now continuing to improve my knowledge of frontend performance, especially how JavaScript execution and rendering choices affect page responsiveness.

Result

This path gave me practical experience building and supporting browser interfaces and confirmed that frontend development is the area where I want to continue growing. I became more confident with JavaScript, component based interface work, API integration, debugging, and communication with other developers. I also learned that good frontend work is not only about making a feature function. It is about making the experience clear, reliable, and easy for the user.

Why Interviewers Ask This

Interviewers ask this question to understand whether the candidate has a clear reason for choosing frontend development and whether that interest is supported by real experience. A strong answer shows relevant JavaScript and browser application skills, clear ownership of personal contributions, awareness of teamwork, and a realistic plan for continued technical growth.

Interviewer may ask next
Which JavaScript skills from your previous work do you use most often?

I use JavaScript most often for handling user events, validating form input, managing interface state, working with API data, and updating components when data changes. I also use browser developer tools regularly to debug JavaScript behavior and inspect network requests. Those skills were important in the same frontend work that led me to focus more strongly on browser application development.

Why are you currently focusing on frontend performance?

As I built more interactive interfaces, I saw that a feature can be correct but still feel slow if JavaScript work or rendering is not handled carefully. I want to understand those performance problems earlier and make better implementation choices. I am improving this area by learning more about browser rendering, JavaScript execution, and how to measure performance before deciding what to optimize.

114. Tell me about a high-risk frontend redesign you led.BehavioralHard

Question Details

Use a real redesign that affected a critical user journey, shared architecture, or large portion of an application. Explain the reason for change, users and stakeholders, technical and delivery risks, alternatives, your leadership decisions, migration or rollout strategy, success and rollback measures, and the final outcome. Clarify both your direct work and how you enabled others.

Interview tip:

Use STAR to structure your answer: briefly explain the Situation and Task, make Action the most detailed part, and finish with the Result. For example, describe a redesign of a critical frontend journey where you identified technical and delivery risks, compared safer alternatives, aligned stakeholders, led the migration and rollout plan, defined success and rollback conditions, supported the team, and explained the final outcome.

Situation

In my last role, I led a redesign of a critical account management flow used across a large part of our frontend application. The existing flow had grown over time and mixed page logic, shared state, API calls, and validation in the same components. This made changes risky because one update could affect several related screens. Product and design also wanted a simpler user experience, but we could not stop normal feature delivery while rebuilding the flow.

Task

I was responsible for leading the frontend redesign while protecting the existing user journey. My goal was to improve the structure and user experience without creating a large release risk. I also needed to help the team move gradually, keep product, design, backend, and quality engineering aligned, and make sure we had a clear way to stop or reverse the rollout if serious problems appeared.

Action

I started by mapping the current flow from the user action to the API response so the team could see where state, validation, navigation, and shared components were connected. I then grouped the risks into user risk, technical risk, and delivery risk. The biggest technical risk was replacing too much shared code at once. I considered a full rewrite, but I rejected it because it would create a long period where the old and new systems could drift apart and would make rollback difficult. Instead, I chose an incremental migration. I separated reusable business rules from page components, introduced clearer component boundaries, and moved shared state into a smaller and more predictable structure. I personally designed the migration approach, built the first shared pieces, and reviewed the most sensitive changes. Other developers owned individual screens, and I gave them clear interfaces, examples, and review guidance so they could work independently without changing the overall design. I worked closely with design to confirm that the new interaction still handled loading, validation, empty states, and errors. I also coordinated with backend engineers so API behavior remained compatible during the transition. For rollout, I kept the old flow available while the new flow was introduced gradually. We defined success checks around correct completion, error behavior, and support feedback. We also agreed that if the new flow caused serious functional problems, we would disable it and return users to the previous version while we investigated. I kept stakeholders updated on what had moved, what was still risky, and which decisions could affect the release schedule. This helped us avoid surprising the wider team late in the project.

Result

We completed the redesign without requiring one large replacement release. The critical journey remained available during the migration, and the team was able to move screen by screen while keeping a clear rollback path. The new frontend structure was easier to understand and safer to change because shared behavior had clearer ownership and component boundaries. I also learned that leading a high risk redesign is not mainly about choosing a clever architecture. It is about reducing the size of each risky decision, making rollback practical, and giving other people enough structure to contribute safely.

Why Interviewers Ask This

Interviewers ask this question to understand how a frontend developer handles large changes where technical decisions can affect users, delivery, and other engineers. A strong answer shows practical risk management, clear leadership, good architectural judgment, communication across teams, ownership of rollout decisions, and the ability to improve a system without creating unnecessary disruption.

Interviewer may ask next
Why did you choose an incremental migration instead of a full rewrite?

I chose an incremental migration because the flow was critical and shared by several screens. A full rewrite would have created a large amount of change that had to work correctly at the same time. By moving one part at a time, we could test each change, keep the existing flow available, and reverse a problem without losing all of the redesign work.

What would you do differently if you led a similar redesign again?

I would define the migration contracts even earlier, especially the ownership of shared state, API behavior, and reusable components. We handled those areas well, but agreeing on them sooner would make parallel work easier. I would still keep the gradual rollout and rollback plan because those choices reduced both technical risk and pressure on the team.

115. What are reflected, stored, and DOM-based cross-site scripting?SecurityEasy

Question Details

Compare three browser attack paths using an untrusted search query reflected in HTML, a saved profile comment rendered for later visitors, and a URL fragment passed by client JavaScript to an HTML sink. For each case, identify the attacker-controlled input, the origin and user context, the DOM or parsing sink, the protected session or data, and where prevention must occur. Distinguish server response generation from client-side DOM execution.

Short Interview Answer (30-60 seconds)

Reflected XSS puts attacker input into the current server response, stored XSS saves it and later renders it for visitors, and DOM-based XSS is created by client JavaScript. Prevent them by keeping untrusted values as text, encoding for the output context, sanitizing only intentional HTML, and avoiding unsafe DOM sinks.

Detailed Explanation

This question asks how harmful content supplied by an attacker can reach another person's browser in three different ways. In one case, a search value is immediately sent back on the page. In another, a comment is saved and shown to later visitors. In the third, the page itself reads part of the address and inserts it into the page. For each path, explain who supplied the value, whose account is at risk, where the value becomes dangerous, what information or actions could be exposed, and where the application must stop the problem.

Useful Questions to Ask the Interviewer
  1. Should I assume the search query and saved comment are rendered by a trusted server, while the URL fragment is handled only by browser JavaScript?
  2. Should the saved profile comment allow plain text only, or is some user-authored HTML intentionally supported?
  3. Should I include defense-in-depth controls such as Content Security Policy and Trusted Types after explaining the primary prevention for each path?
What are reflected, stored, and DOM-based cross-site scripting? diagram
How to Explain It in an Interview

Cross-site scripting, or XSS, happens when attacker-controlled data is treated as executable browser content instead of ordinary data. The attacker's code then runs in the vulnerable application's origin. That means it can interact with the page using the same browser origin as the legitimate application and may read JavaScript-accessible data or perform actions available to the current user.

1. Reflected XSS

Suppose the application receives a search request such as ?q=.... The attacker controls the q value. A trusted server reads that value and builds an HTML response containing it. If the server places the value into an HTML, attribute, script, URL, or another executable context without the correct context-specific encoding, the browser parser can interpret attacker-controlled data as markup or code.

The attacker-controlled input is the search query. The origin is the vulnerable application's origin. The victim is typically a user who opens an attacker-crafted URL, possibly while authenticated. The parsing sink is the location in the generated response where attacker-controlled data reaches an HTML or related browser parser. Protected assets include private page data, authenticated capabilities, and JavaScript-readable credentials or tokens. A session cookie marked HttpOnly cannot be directly read by injected JavaScript, but XSS can still make same-origin requests or perform actions using the victim's authenticated browser session.

Prevention must occur when the server generates the response. Treat the search query as data and apply contextual output encoding for the exact destination. For normal visible text, render it as text rather than executable HTML. Input validation can reject values that violate business rules, but filtering suspicious characters is not a complete XSS defense.

2. Stored XSS

Suppose an attacker submits a profile comment. The attacker controls the comment. The trusted server saves it in persistent storage. Later, another visitor opens the profile and the stored value is rendered. If that value reaches an executable HTML context or unsafe client-side sink without safe handling, attacker-controlled content can execute in the visitor's browser.

The attacker-controlled input is the saved comment. The origin is the vulnerable application's origin. The victim is any later visitor whose browser renders the unsafe value. The sink may be a server-generated HTML position interpreted by the browser parser or a later client-side DOM operation that turns the stored value into HTML. Protected assets include each visitor's JavaScript-accessible data and authenticated capabilities.

If profile comments should be plain text, render them as text using contextual encoding, textContent, safe DOM APIs, or framework escaping. If the application intentionally supports limited rich HTML, sanitize that HTML with a well-maintained allowlist-based sanitizer before it reaches an HTML-capable sink. Sanitization is appropriate when HTML is intentionally allowed; it is not a universal replacement for context-specific output encoding.

Stored XSS describes persistence, not necessarily the final execution mechanism. For example, the server could safely return a stored comment in JSON, but client JavaScript could later introduce XSS by assigning that comment to innerHTML.

3. DOM-based XSS

Suppose the page reads location.hash, which contains the URL fragment after #. The attacker controls the fragment. URL fragments are normally handled in the browser and are not included in the HTTP request sent to the server. Client JavaScript reads the fragment and passes it to an unsafe sink such as innerHTML. The browser then parses that string as HTML, which can create attacker-controlled executable content.

The attacker-controlled input is the URL fragment. The origin is the vulnerable page's origin. The victim is the user who opens the crafted URL. The source is the browser-side value read from location.hash. The sink is the client-side DOM or HTML-parsing API that interprets the value as markup. Protected assets include page data, JavaScript-readable tokens, and authenticated actions available from that origin.

Prevention must occur in the client-side data flow. If the fragment is supposed to be displayed as text, use textContent, createTextNode, safe DOM APIs, or framework rendering that escapes text by default. Do not pass untrusted strings to innerHTML, outerHTML, insertAdjacentHTML, or similar HTML-parsing sinks. If application functionality genuinely requires HTML, sanitize the content with an appropriate HTML sanitizer before using the required HTML sink.

Server response generation versus client-side DOM execution

The important distinction is where attacker-controlled data becomes executable browser content. With reflected XSS, the server commonly puts unsafe attacker-controlled data directly into the current response. With stored XSS, attacker-controlled data is first persisted and later becomes unsafe when a server or client rendering path interprets it as executable content. With DOM-based XSS, client JavaScript itself reads an untrusted source and sends it into an unsafe DOM sink, so the original server response can be completely safe.

This is why the best analysis follows data from source to sink. The storage location alone does not determine the final execution mechanism. A stored value can later cause DOM-based XSS if browser JavaScript handles it unsafely.

Primary defenses

For plain text, keep untrusted values as text. On the server, use output encoding appropriate to the exact context. In browser JavaScript, prefer textContent, createTextNode, safe attribute APIs, and framework rendering that escapes values by default.

Avoid APIs that interpret untrusted strings as HTML. innerHTML, outerHTML, insertAdjacentHTML, and similar sinks should not receive untrusted content. Framework escape-bypass features require the same caution because they deliberately disable normal escaping.

When the product intentionally supports user-authored HTML, use a well-maintained sanitizer with a strict allowlist of permitted elements, attributes, and URL forms. Do not try to create a complete XSS defense by manually removing suspicious strings such as <script> because dangerous browser parsing behavior is broader than one tag or pattern.

Defense in depth

Content Security Policy, or CSP, can reduce the impact of an XSS mistake by restricting which scripts may execute. A strong nonce- or hash-based CSP is valuable, but CSP does not replace safe source-to-sink handling.

Trusted Types can add another browser-side protection layer by restricting selected dangerous DOM sinks so that ordinary strings cannot be passed to them without going through approved policies. Trusted Types is defense in depth and still requires correct application logic and carefully designed policies.

Sensitive session cookies should normally use HttpOnly, Secure, and an appropriate SameSite setting. HttpOnly prevents injected JavaScript from directly reading the cookie value. It does not make XSS harmless because malicious same-origin code may still perform authenticated actions from the victim's page.

CSRF is a different security problem. CSRF tricks a browser into making an unwanted authenticated request, while XSS executes attacker-controlled content in the application's origin. XSS can frequently defeat normal CSRF assumptions because the injected script is already running within the trusted origin.

CORS and the same-origin policy are also not primary XSS defenses. The same-origin policy limits cross-origin access, but successful XSS runs with the vulnerable application's own origin privileges. CORS controls whether selected cross-origin responses can be read by requesting origins; it does not make unsafe same-origin rendering safe.

The frontend must never contain server secrets or long-lived privileged credentials. Browser storage such as localStorage is readable by JavaScript running in the same origin, so successful XSS can expose sensitive values stored there. Prefer designs that minimize sensitive credentials available to frontend JavaScript.

Third-party scripts and dependencies can also increase XSS and supply-chain risk because scripts running in the page can receive significant application privileges. Minimize unnecessary third-party code, review dependencies, keep them updated, and use controls such as CSP and Subresource Integrity where appropriate. These controls support the primary XSS defenses rather than replacing them.

Clickjacking is separate from XSS and is not central to these three attack paths. If relevant to the application's broader security design, prevent unwanted framing with CSP frame-ancestors or equivalent framing protections.

Safe failure and verification

If untrusted content cannot be safely rendered, fail closed by displaying it as inert text or rejecting the unsupported rich-content operation rather than falling back to raw HTML. Security logging should record enough information to diagnose failed validation, sanitization, CSP violations, or unsafe rendering attempts, but it must not record session tokens, secrets, or unnecessary personal data.

Verify each control with automated and manual tests. Use harmless test strings containing HTML-significant characters and markup-like content, then confirm that they appear as inert data instead of being interpreted as executable content. Test the reflected search-query path, the stored-comment path for later visitors, and the client-side URL-fragment path separately. Review server templates for correct context-specific encoding, search frontend code for unsafe DOM sinks, test sanitizer configurations when HTML is intentionally allowed, and monitor CSP or Trusted Types reports during development and controlled rollout.

Technical Approach
  1. Identify each attacker-controlled source: the search query, stored profile comment, and URL fragment.
  2. Identify the origin and victim context for each path.
  3. Trace each value across server and browser trust boundaries to its final parsing or DOM sink.
  4. Decide whether the destination requires plain text or intentionally supported HTML.
  5. For plain text, use context-appropriate output encoding, textContent, safe DOM APIs, or framework escaping.
  6. For intentionally supported HTML, sanitize with a strict allowlist before the HTML sink.
  7. Remove unnecessary unsafe sinks such as innerHTML.
  8. Add defense-in-depth controls such as CSP, Trusted Types, secure cookies, and dependency controls where relevant.
  9. Define safe failure behavior so unsafe content becomes inert text or is rejected rather than rendered as raw HTML.
  10. Verify every source-to-sink path with tests and log failures without secrets.
Practical Insights

The normal runtime cost is small. Rendering a plain string safely takes work roughly proportional to the length of that string. HTML sanitization costs more because the sanitizer must parse and inspect the supplied markup, but user-generated comments are usually small enough for this to be practical. CSP and Trusted Types usually add little runtime cost, although their policies require configuration and testing. Memory usage for these defenses is normally proportional to the content being processed. The larger production cost is maintenance: developers must understand output contexts, avoid dangerous sinks, keep sanitizers and dependencies updated, and test new rendering paths.

Why Interviewers Ask This

This question tests whether the candidate can trace attacker-controlled data across server and browser trust boundaries, distinguish reflected, stored, and DOM-based XSS, identify the source and sink for each attack path, understand the victim's origin and session context, choose prevention at the correct layer, and explain defense in depth without treating input filtering as a complete solution.

Common interview mistakes

Common mistakes include saying all three XSS types are solved by validating input; treating stored XSS as dangerous only when the value is saved rather than when it reaches an executable sink; assuming DOM-based XSS must involve a server response; using innerHTML for data that should be text; using one generic escaping rule for HTML text, attributes, JavaScript, CSS, and URLs even though output handling is context-specific; sanitizing ordinary text when safe text rendering is simpler; using framework escape-bypass APIs without reviewing the trust boundary; assuming CSP alone fixes XSS; believing HttpOnly cookies make XSS harmless; confusing XSS with CSRF, CORS, or the same-origin policy; keeping long-lived sensitive tokens in JavaScript-readable browser storage without considering XSS exposure; and logging payloads together with secrets or session data.

Interview tip

Explain every case using the same pattern: attacker-controlled source, origin and victim context, sink, protected data or capability, and prevention point. Emphasize that reflected XSS commonly becomes unsafe during current server-response generation, stored XSS persists before later unsafe rendering, and DOM-based XSS becomes unsafe in client JavaScript. Finish with safe text rendering first, sanitization only for intentional HTML, and CSP plus Trusted Types as defense in depth.

Interviewer may ask next
Why is using textContent safer than innerHTML for an untrusted URL fragment?

textContent treats the supplied value as text. Characters such as < and > are displayed rather than parsed as markup. innerHTML asks the browser to parse a string as HTML, so attacker-controlled content can create dangerous elements or executable behavior. When the application only needs to display text, textContent removes the HTML-parsing sink and is the safer choice.

If a product intentionally allows formatted profile comments, how should stored XSS be prevented?

Do not rely on simple character filtering. Define the HTML elements, attributes, and URL forms the product actually needs, sanitize user-authored HTML with a well-maintained allowlist-based sanitizer, and allow only the sanitized result to reach the required HTML sink. Test sanitizer bypass cases and use CSP and Trusted Types as additional protection. If formatting is not actually required, use plain-text rendering instead.

116. What is the same-origin policy?SecurityEasy

Question Details

Define the same-origin policy as a browser security rule that limits how a document or script from one origin can read or interact with resources from another origin. Define an origin by scheme, host, and port; explain common allowed and blocked interactions; and distinguish the policy from CORS, CSP, CSRF protection, and authentication.

Short Interview Answer (30-60 seconds)

The same-origin policy is a browser security rule that limits one origin from reading or manipulating another origin's resources. An origin is the combination of scheme, host, and port. CORS can selectively allow cross-origin reads, but the trusted server must still enforce authentication and authorization.

Detailed Explanation

The practical idea is simple: a page from one website should not normally be able to read private information from another website that you also use. Without this protection, a harmful page could try to inspect information from your email, bank, or another signed-in site. The browser creates a boundary based on where each page came from. Some actions across that boundary are still possible, such as showing an image, following a link, or sending a form. But directly reading protected information from another site is usually stopped unless that site gives permission.

Useful Questions to Ask the Interviewer
  1. Would you like examples of both allowed and blocked cross-origin interactions?
  2. Should I also explain how CORS can permit selected cross-origin reads?
What is the same-origin policy? diagram
How to Explain It in an Interview

The same-origin policy, often called SOP, is a browser security rule that limits how a document or script from one origin can read or interact with resources from another origin.

An origin is defined by three parts:

  1. Scheme, such as https.
  2. Host, such as app.example.com.
  3. Port, such as 443.

Two URLs are same-origin when these three values match, using the effective port for the scheme. For example, https://app.example.com/page and https://app.example.com/profile are same-origin. http://app.example.com, https://api.example.com, and https://app.example.com:8443 are different origins because the scheme, host, or port differs.

The main security purpose is to stop JavaScript running on one origin from automatically reading sensitive information that belongs to another origin. For example, a malicious site should not be able to open a user's banking site in another context and freely inspect its DOM or read authenticated API responses.

The policy does not block every cross-origin action. Browsers intentionally allow several kinds of cross-origin use. A page can commonly navigate to another site, submit an HTML form, load an image, load certain stylesheets, or embed some resources. However, JavaScript is generally prevented from reading a cross-origin document's DOM or reading a cross-origin network response unless an applicable browser mechanism permits it.

A useful distinction is sending versus reading. A browser may allow a cross-origin request to be sent even when JavaScript is not allowed to read the response. For this reason, a server cannot rely on the same-origin policy to protect state-changing operations. The trusted server must independently enforce authorization and use appropriate CSRF protections when browser credentials can be sent automatically.

CORS, or Cross-Origin Resource Sharing, is different from SOP. SOP is the browser's default isolation rule. CORS is a mechanism in which a server returns HTTP response headers that tell the browser which origins may access a response from JavaScript. Depending on the request, the browser may first send a preflight request to check whether the method and headers are permitted. CORS does not authenticate the caller, does not decide what an authenticated user is authorized to access, and does not stop non-browser clients from sending requests directly to the server.

CSP, or Content Security Policy, is also different. CSP lets a site restrict which sources may provide scripts, styles, images, frames, and other content. It is commonly used to reduce risks such as cross-site scripting. CSP does not define whether two URLs have the same origin and does not replace SOP or server authorization.

CSRF protection solves another problem. Cross-Site Request Forgery occurs when a malicious site causes a user's browser to send an unwanted request to another site using credentials that the browser may include automatically. SOP can often prevent the malicious page from reading the response, but that does not guarantee the request was not sent or processed. Protections can include suitable SameSite cookie settings, CSRF tokens, and server-side Origin or Referer validation when appropriate.

Authentication answers, 'Who is this user or client?' Authorization answers, 'What is this authenticated identity allowed to do?' SOP and CORS answer neither question. The trusted server must enforce authorization for every protected operation and resource.

The main tradeoff is isolation versus legitimate integration. Strong origin isolation protects users, but modern applications often place the frontend and API on different origins. CORS provides a controlled way to permit required browser access. A good production configuration allows only the origins, methods, headers, and credential behavior that the application actually needs instead of granting broad access by default.

Safe failure means that when cross-origin reading is not permitted, frontend code should handle the browser's failure without exposing protected response data or sensitive diagnostic information. Applications should avoid logging cookies, authorization headers, access tokens, session identifiers, or secrets. Frontend code must never contain server secrets or long-lived private credentials.

To verify the control, test the application in a real browser. Use browser developer tools to compare same-origin and cross-origin requests, inspect relevant request and response headers, and confirm that an unapproved origin cannot read protected responses. Also test authenticated endpoints directly on the server to confirm that authorization is enforced independently of browser-origin controls.

Technical Approach
  1. Compare the scheme, host, and effective port of the page and target resource.
  2. If all three match, treat them as the same origin for SOP purposes.
  3. If they differ, identify the interaction type, such as navigation, resource loading, form submission, DOM access, or JavaScript response reading.
  4. Expect cross-origin DOM access and response reading to be restricted unless a specific browser mechanism permits them.
  5. If legitimate cross-origin API access is required, configure narrow server-side CORS rules.
  6. Independently enforce authentication, authorization, and relevant CSRF protections on the trusted server.
  7. Verify the behavior in an actual browser and confirm that unauthorized origins cannot read protected data.
Practical Insights

There is no useful Big-O time or memory complexity to calculate for the same-origin policy because it is a browser security rule, not an application algorithm. The browser performs origin checks as part of normal web security enforcement. The important costs are operational and maintenance costs. Teams must correctly manage frontend origins, API origins, CORS rules, credentials, cookies, development environments, and deployment changes. Rules that are too broad can expose data to unwanted origins, while rules that are too strict can break legitimate browser access. Automated and browser-level tests should cover expected production and development origins.

Why Interviewers Ask This

Interviewers want to know whether the candidate understands one of the browser's main security boundaries. A strong answer should correctly define an origin using scheme, host, and port, explain the difference between sending a cross-origin request and reading its response, give examples of allowed and blocked interactions, and distinguish the same-origin policy from CORS, CSP, CSRF protection, authentication, and server-side authorization.

Common interview mistakes

Common mistakes include saying that SOP blocks every cross-origin request. It often prevents JavaScript from reading data rather than preventing every request from being sent. Another mistake is defining an origin using only the domain and forgetting the scheme and port. Candidates also confuse CORS with authentication or authorization, assume CORS protects a server from direct non-browser clients, or claim SOP prevents CSRF. Another error is relying on browser restrictions instead of enforcing authorization on the trusted server. Finally, broad CORS rules should not be used without understanding exactly which origins need access and whether credentials are involved.

Interview tip

Start with one sentence: SOP prevents one origin from freely reading or manipulating another origin's data. Then define origin as scheme, host, and port. Give one allowed and one blocked example, explain the important difference between sending and reading a request, and finish by separating SOP from CORS, CSP, CSRF protection, authentication, and server-side authorization.

Interviewer may ask next
How is CORS different from the same-origin policy?

The same-origin policy is the browser's default restriction on cross-origin access. CORS is a mechanism that lets a server selectively tell the browser which other origins may read a response through JavaScript. Some CORS requests require a preflight check. CORS does not authenticate users, enforce authorization, or stop non-browser clients from sending requests. The trusted server must still enforce access control.

If the same-origin policy blocks reading a cross-origin response, why is CSRF protection still needed?

Because preventing JavaScript from reading a response does not necessarily prevent the browser from sending the request. A malicious page may be able to trigger a state-changing request while the browser automatically includes the user's credentials. Therefore, sensitive server actions still need appropriate CSRF defenses, such as SameSite cookies, CSRF tokens, or origin validation, together with server-side authorization.

117. What is cross-site scripting (XSS)?SecurityEasy

Question Details

Define cross-site scripting as a vulnerability in which untrusted data is interpreted as executable browser content in another user context. Explain reflected, stored, and DOM-based forms; sources and dangerous sinks; session and data impact; contextual output encoding; safe DOM APIs; sanitization for allowed HTML; and Content Security Policy as defense in depth.

Short Interview Answer (30-60 seconds)

XSS is a vulnerability where untrusted data becomes executable content in another user's browser context. It may be reflected, stored, or DOM-based. Prevent it with safe DOM APIs, contextual output encoding, careful sanitization when HTML is intentionally allowed, plus CSP and Trusted Types as additional defenses.

Detailed Explanation

Cross-site scripting happens when a website receives information from somewhere it should not fully trust and accidentally lets that information act like instructions. An attacker can prepare harmful content that runs when another person opens a page. The harmful content may then act as that person on the affected website. It could read information shown on the page, change what the person sees, or perform actions available to that person. The main goal is simple: outside information should stay ordinary information unless the site deliberately allows carefully cleaned rich content.

Useful Questions to Ask the Interviewer
  1. Do you want me to explain reflected, stored, and DOM-based XSS separately?
  2. Should I also cover browser defenses such as Content Security Policy and Trusted Types?
  3. Is intentionally allowed user HTML, such as rich-text content, part of the scenario?
What is cross-site scripting (XSS)? diagram
How to Explain It in an Interview

Cross-site scripting, or XSS, is a vulnerability in which untrusted data is interpreted as executable browser content in another user's security context instead of remaining harmless data. The practical security decision is to preserve the boundary between data and code.

Reflected XSS occurs when attacker-controlled input is included in content that is returned or rendered for a request and is then interpreted as active browser content. A common example is unsafe use of a query-string value in generated page content. Stored XSS occurs when attacker-controlled content is saved, such as in a comment or profile field, and later delivered to users. DOM-based XSS describes XSS caused by unsafe client-side DOM processing: JavaScript reads attacker-controlled data and passes it to a sink that interprets it as active content. DOM-based XSS describes where the unsafe processing occurs and can overlap with reflected or stored delivery patterns.

A useful way to reason about XSS is with sources and sinks. A source is where potentially untrusted data enters frontend logic. Examples include location.search, location.hash, form values, postMessage data, browser storage, and API responses containing user-controlled values. A sink is an API or operation that can interpret a value as HTML, JavaScript, a URL, CSS, or another active browser context. A classic dangerous HTML sink is innerHTML when it receives untrusted content.

For ordinary text, prefer APIs that preserve the value as text. For example, use textContent, document.createElement, append, or other DOM operations that do not parse an untrusted string as HTML. Modern frameworks normally escape interpolated text by default, so keep that protection enabled and treat raw-HTML escape hatches as security-sensitive operations.

When output encoding is required, it must match the destination context. HTML text, HTML attributes, JavaScript strings, CSS, and URLs have different parsing rules, so one generic encoding function is not safe for every destination. In frontend code, avoiding string-built executable markup and using safe DOM or framework APIs is usually easier to reason about than manually encoding complex output.

If the product intentionally allows user-authored HTML, such as rich-text formatting, normal text encoding would remove the intended markup. In that case, use a well-maintained HTML sanitizer with a strict allowlist appropriate to the application's needs. The sanitizer should remove or neutralize dangerous elements, attributes, URL schemes, and other executable content. Do not treat regular-expression filtering, simple character removal, or input validation alone as complete XSS protection.

XSS can compromise information and actions available to the affected page. An injected script may read sensitive DOM content, read JavaScript-accessible browser storage, modify the interface, send data elsewhere where browser policy permits, or make requests using the victim's authenticated browser context. If an authentication cookie is HttpOnly, injected JavaScript cannot directly read that cookie, which reduces cookie theft. However, the script may still issue same-origin requests that automatically include the cookie, so HttpOnly reduces impact but does not solve XSS.

Authentication and authorization are separate concerns. Authentication establishes who the user is. Authorization determines what that user is permitted to do. XSS may cause requests to be made as the authenticated user, but the trusted server must still enforce authorization for every protected operation. Frontend checks are useful for user experience but are not a trusted authorization boundary.

Content Security Policy, or CSP, is defense in depth. A strong policy can restrict the scripts and other resources a page may execute or load and can reduce the impact of some injection mistakes. It does not replace correct output handling because policies can contain gaps and XSS defenses should not depend on CSP alone. Where practical, prefer nonce- or hash-based script policies and avoid broad allowances such as unsafe-inline.

Trusted Types is another defense for DOM XSS. When enforced, it can restrict assignments to supported dangerous DOM injection sinks so that arbitrary strings cannot be assigned directly. Values for those sinks must instead come through approved Trusted Types policies. This makes dangerous DOM operations easier to control and detect. Trusted Types complements safe DOM construction, contextual encoding, and sanitization; it does not replace them.

Other browser security controls address related but different threats. The same-origin policy limits interactions between different origins. CORS determines when frontend JavaScript may read certain cross-origin responses; it is not an XSS defense. CSRF protections address unwanted authenticated requests initiated from another site; they do not neutralize script already running inside the trusted origin. Frame-ancestors in CSP or X-Frame-Options can reduce clickjacking. These controls are useful, but none substitutes for preventing XSS.

Cookies that carry sessions should use appropriate security attributes such as HttpOnly, Secure, and a suitable SameSite policy. Avoid storing long-lived bearer tokens in JavaScript-readable storage when a safer architecture is available because XSS can read values exposed to page JavaScript. Browser storage is not a place for server secrets. Never put server secrets, private signing keys, database credentials, or other long-lived server credentials into frontend code because anything delivered to the browser must be treated as accessible to the user and to code running in that page.

Third-party scripts and dependencies also affect the XSS threat model. A third-party script loaded into the page generally runs with significant access to the page's JavaScript environment and DOM. Minimize unnecessary third-party scripts, review what is loaded, keep dependencies maintained, use lockfiles and appropriate dependency-review practices, and apply CSP or related controls where practical. Supply-chain compromise is not the same vulnerability as XSS, but malicious JavaScript running in the origin can create similar consequences for users.

File previews also need careful handling when user-controlled files can contain active content. Do not assume every uploaded file is passive. Render untrusted formats using an approach appropriate to the file type, content type, and isolation requirements rather than injecting file contents directly into the application's DOM as HTML.

Privacy matters during both prevention and investigation. Security logging can record useful events such as blocked policy violations, sanitizer rejections, or dangerous-sink detections, but logs should avoid session tokens, credentials, sensitive page contents, or unnecessary personal data. Safe failure means that if content cannot be safely rendered, the application should display it as harmless text, omit it, or reject it rather than falling back to an unsafe rendering path.

To verify the protection, trace untrusted data from each source to its eventual sink. Test suspicious paths with harmless payloads that reveal whether markup or script would be interpreted without causing damage. Review raw-HTML framework features, dangerous DOM sinks, sanitizer configuration, and contextual encoding. Where enabled, inspect CSP and Trusted Types violation reports. Automated security tests can help, but manual review of trust boundaries remains important because XSS depends heavily on how data moves through the application.

Technical Approach
  1. Identify trust boundaries and list sources of untrusted data, including URLs, forms, messages, browser storage, uploaded content, third-party data, and API responses containing user-controlled values.
  2. Trace that data to sinks that can interpret HTML, JavaScript, URLs, CSS, or other active content.
  3. Prefer textContent, createElement, safe DOM operations, or normal framework escaping instead of parsing untrusted strings as HTML.
  4. When encoding is necessary, use output encoding specific to the exact destination context.
  5. If the product intentionally permits HTML, sanitize it with a maintained allowlist-based sanitizer and keep the HTML-capable rendering path narrow.
  6. Add CSP and, where practical, Trusted Types as defense in depth.
  7. Reduce impact with secure cookie settings, careful token handling, server-side authorization, and minimal third-party script privileges.
  8. Verify controls by reviewing dangerous sinks, testing trust boundaries with harmless security payloads, inspecting policy violations, and confirming that rejected content fails safely.
Practical Insights

Safe DOM APIs and normal framework escaping usually add almost no meaningful performance cost. Contextual output encoding also has small CPU and memory cost because it transforms strings before output. HTML sanitization costs more because the sanitizer must parse and inspect the supplied markup, and its cost generally grows with the amount and complexity of content being sanitized. CSP and Trusted Types have little direct runtime cost compared with normal page work, but they add configuration, testing, rollout, and maintenance effort. The main operational cost is ongoing engineering discipline: tracking trust boundaries, reviewing dangerous sinks, testing changes, maintaining sanitizer rules, and controlling third-party code and dependencies.

Why Interviewers Ask This

Interviewers want to know whether you understand how untrusted data can cross a browser trust boundary and become executable content. They also evaluate whether you can distinguish reflected, stored, and DOM-based XSS, identify dangerous sources and sinks, choose context-appropriate defenses, protect sessions and user data, and verify that browser-side controls are effective without treating input filtering, sanitization, or CSP as a complete standalone solution.

Common interview mistakes

Common mistakes include using innerHTML with untrusted strings; assuming input validation or character filtering alone prevents XSS; using one generic encoding method for HTML, attributes, URLs, JavaScript, and CSS; disabling framework escaping to render raw HTML without a justified and sanitized path; writing homemade sanitizers with regular expressions; assuming HttpOnly cookies make XSS harmless; relying on CSP as the primary fix; forgetting DOM-based sources such as location, postMessage, storage, or user-controlled API data; trusting data merely because it came from the application's own server; confusing CORS, CSRF protection, or the same-origin policy with XSS prevention; putting long-lived tokens or secrets in frontend-accessible locations; granting unnecessary trust to third-party scripts; failing to consider active content in file previews; logging secrets while investigating security events; and falling back to unsafe rendering when validation or sanitization fails.

Interview tip

Start with the trust boundary: untrusted data must remain data instead of becoming executable browser content. Then explain reflected, stored, and DOM-based XSS, identify sources and dangerous sinks, and give the defense order: safe DOM APIs or framework escaping first, contextual output encoding when required, sanitization only for intentionally allowed HTML, then CSP and Trusted Types as defense in depth. Mention that the trusted server still enforces authorization.

Interviewer may ask next
What is the difference between reflected, stored, and DOM-based XSS?

Reflected XSS commonly occurs when attacker-controlled input is included in a response or client-rendered result for a request and becomes executable content. Stored XSS occurs when attacker-controlled content is persisted and later rendered to users. DOM-based XSS means the unsafe transformation happens in client-side DOM logic: JavaScript reads untrusted data and sends it to an execution-capable sink. DOM-based describes where the vulnerability occurs, so a DOM-based flow may still receive its malicious value through a reflected or stored delivery path.

When should you sanitize HTML instead of output-encoding it?

Use safe text APIs or contextual output encoding when the value should not contain active markup. Use HTML sanitization only when the product intentionally allows a limited subset of HTML, such as rich-text formatting. A maintained allowlist-based sanitizer can preserve approved markup while removing or neutralizing dangerous elements, attributes, and URL schemes. Sanitization should be applied close to the HTML trust boundary, and the application should still use CSP or Trusted Types as additional defenses where appropriate rather than treating them as substitutes for safe rendering.

118. What is cross-site request forgery (CSRF)?SecurityEasy

Question Details

Define CSRF as tricking a browser into sending an unwanted state-changing request with credentials that the browser includes automatically. Explain the conditions needed for the attack, anti-CSRF tokens, SameSite cookies, origin checks, safe HTTP methods, and re-authentication for sensitive actions. Clarify why HTTPS, CORS, or using POST alone is not sufficient protection.

Short Interview Answer (30-60 seconds)

CSRF tricks a signed-in browser into sending an unwanted state-changing request with credentials the browser includes automatically, usually cookies. Defend with anti-CSRF tokens, SameSite cookies, Origin checks, safe HTTP methods, and re-authentication for sensitive actions. HTTPS, CORS, and POST alone are not sufficient.

Detailed Explanation

Cross-site request forgery happens when a harmful website causes your browser to perform an action on another website where you are already signed in. Your browser may automatically include the information that proves you are signed in, so the second website may think the request came from you. The attacker usually cannot read the private response, but they may still cause an unwanted change, such as changing account settings. Protection means making sure an important request was intentionally started through a flow the trusted website allows.

Useful Questions to Ask the Interviewer
  1. Is the application using cookie-based sessions or another credential that the browser sends automatically?
  2. Which state-changing operations are especially sensitive and should require re-authentication?
  3. Does the application need any legitimate cross-site flows that affect SameSite or Origin-checking rules?
What is cross-site request forgery (CSRF)? diagram
How to Explain It in an Interview

CSRF, or cross-site request forgery, is an attack where another site causes a user's browser to send an unwanted request to a trusted application. The important condition is that the browser automatically includes authentication credentials, most commonly session cookies.

For example, suppose a user is signed in to a banking site. If the bank accepts a state-changing request based only on the session cookie, a malicious page could cause the browser to submit a transfer request. The browser may attach the bank's session cookie automatically. Unless the bank performs additional checks, the server may see a valid authenticated session even though the user did not intentionally request the transfer.

Several conditions normally need to be true for a CSRF attack. First, the target endpoint must perform a meaningful state change. Second, the victim must have valid credentials that the browser will attach automatically. Third, the attacker must be able to construct a request the browser is allowed to send. Finally, the server must lack sufficient protection that proves the request came through an intended application flow.

Authentication and authorization are different. Authentication tells the server which user is signed in. Authorization decides whether that user is allowed to perform the requested action. The trusted server must always enforce authorization. CSRF protection adds another check: even if the user is authenticated and authorized, was this state-changing request submitted through a trusted flow?

A common defense is an anti-CSRF token. The trusted server creates an unpredictable token associated with the user's session or request context. The legitimate application sends that token with state-changing requests, for example in a hidden form field or a request header. The server verifies the token before making the change. A malicious cross-origin page generally cannot read the legitimate application's token because of the browser's same-origin policy. If the token is missing or invalid, the server must reject the request without changing state.

SameSite cookies provide an additional browser-level defense. SameSite=Strict prevents the cookie from being sent in most cross-site contexts. SameSite=Lax also blocks many cross-site uses, although cookies can still be sent in some top-level navigation cases, especially for safe methods such as GET. This is one reason GET and HEAD must never perform state-changing actions. SameSite=None allows cross-site cookie sending and requires Secure, so applications that need it must rely carefully on other CSRF controls as well. SameSite is strong defense in depth, but its setting must match legitimate application behavior.

The server can also validate the Origin header on state-changing requests. It should compare the header against an explicit allowlist of trusted origins, not perform a loose substring check. Referer may be used as a carefully considered fallback in some designs when Origin is unavailable. Applications must define safe behavior for missing headers because blindly accepting a missing Origin would weaken the control, while blindly rejecting it may break legitimate clients. Browser-based applications can usually use a strict policy for protected state-changing routes.

HTTP methods should follow their intended meaning. GET and HEAD should be safe and should not change server state. Creating, updating, or deleting data should use state-changing methods such as POST, PUT, PATCH, or DELETE. However, POST alone does not prevent CSRF. A malicious site can often submit a normal HTML form with a cross-site POST request, and the browser may still attach cookies automatically.

For especially sensitive operations, such as changing a password, changing a recovery method, adding a payment destination, or authorizing a financial transaction, the application can require recent re-authentication or another strong user-verification step. This limits the effect of both CSRF and a stolen authenticated session.

HTTPS is essential because it protects traffic against network interception and modification, but it does not prove that the user intended a request. A malicious HTTPS page can still cause a browser to send a request to another HTTPS site, so HTTPS alone does not stop CSRF.

CORS is also not a complete CSRF defense. CORS mainly controls whether JavaScript from another origin can read responses and whether certain non-simple cross-origin requests are allowed. Browsers can still send some cross-origin requests, including ordinary HTML form submissions, without the attacker receiving CORS permission to read the response. Therefore, blocking response access is not the same as preventing the state-changing request.

The same-origin policy has a similar limitation. It prevents many cross-origin reads, but it does not prevent every cross-origin request from being sent. CSRF specifically takes advantage of this difference between sending a request and reading its response.

CSRF risk is different when authentication uses a credential that an attacker-controlled page cannot make the browser attach automatically, such as a bearer token that the legitimate JavaScript application explicitly places in an Authorization header. That design can reduce classic CSRF exposure, although it introduces other concerns such as protecting the token from XSS and accidental exposure. The trusted server must still perform authentication and authorization correctly.

A secure design therefore combines controls based on the application's authentication model: keep state changes off safe methods, configure SameSite cookies appropriately, verify anti-CSRF tokens where required, validate trusted origins, enforce server-side authorization, and require re-authentication for especially sensitive actions. Failed validation must stop the operation before any state change occurs. Security logs may record useful request metadata and the reason for rejection, but they must not log session cookies, CSRF tokens, passwords, authorization credentials, or other secrets.

To verify the defenses, test protected state-changing endpoints from an unrelated origin. Confirm that requests with a missing or incorrect anti-CSRF token, an untrusted Origin, or another failed required check are rejected and cause no state change. Also test legitimate application flows, including any intentionally supported cross-site flows, so security controls do not break expected behavior.

Technical Approach
  1. Identify every endpoint that changes server-side state.
  2. Determine whether authentication credentials, especially cookies, are attached automatically by the browser.
  3. Ensure safe methods such as GET and HEAD are read-only.
  4. Configure session cookies with an appropriate SameSite policy and use Secure and HttpOnly where appropriate.
  5. Require and verify an unpredictable anti-CSRF token for protected state-changing requests when the authentication model needs it.
  6. Validate Origin against an explicit trusted-origin allowlist and define safe handling for missing headers.
  7. Enforce authentication and authorization independently on the trusted server.
  8. Require recent re-authentication or stronger verification for especially sensitive actions.
  9. Reject failed checks before changing state and log useful diagnostic information without secrets.
  10. Test both legitimate application flows and simulated cross-site attacks to verify the controls.
Practical Insights

CSRF defenses usually add very little processing cost. Token comparison and Origin checking take a small, nearly constant amount of work for each request. SameSite cookie enforcement is mainly handled by the browser. Server-managed token strategies may require a small amount of session data, while some token designs can avoid additional server storage. The main cost is maintenance: every relevant state-changing endpoint must use the correct controls, legitimate cross-site flows must be handled deliberately, and authentication or cookie changes must be security-tested.

Why Interviewers Ask This

Interviewers want to know whether the candidate understands how automatically included browser credentials can create a CSRF risk, which conditions make the attack possible, and which protections belong on the trusted server. They also evaluate whether the candidate can distinguish real CSRF defenses from incomplete measures such as HTTPS, CORS, or simply using POST.

Common interview mistakes

Common mistakes include believing HTTPS prevents CSRF, treating CORS or the same-origin policy as complete CSRF defenses, assuming POST is automatically safe, allowing GET requests to change data, checking authentication without independently enforcing authorization, relying only on SameSite without considering legitimate cross-site requirements, using predictable or unverified CSRF tokens, accepting loosely matched Origin values, or accepting missing validation data without a defined security policy. Another serious mistake is performing part of the state change before CSRF validation finishes instead of failing safely first.

Interview tip

Start with the condition that makes CSRF possible: the browser may send authentication credentials automatically. Then explain anti-CSRF tokens, SameSite cookies, Origin validation, safe HTTP methods, and re-authentication. Clearly state that HTTPS, CORS, and POST alone are insufficient, and emphasize that the trusted server must enforce authorization and fail before changing state.

Interviewer may ask next
Why is using POST instead of GET not enough to prevent CSRF?

POST is appropriate for many state-changing operations, but it is not a CSRF defense by itself. A malicious site can often create a normal HTML form that submits a cross-site POST request. If the browser automatically attaches the victim's session cookie and the server performs no additional CSRF validation, the request may succeed. POST should therefore be combined with controls such as anti-CSRF tokens, SameSite cookies, Origin validation, and server-side authorization.

Can SameSite cookies completely replace anti-CSRF tokens?

Not in every application. SameSite=Lax or SameSite=Strict can block many cross-site cookie uses and provide strong CSRF protection, but legitimate cross-site workflows may require a less restrictive policy. SameSite=None explicitly permits cross-site cookie sending, so additional controls become especially important. For protected state-changing requests, anti-CSRF tokens and Origin validation can provide defense in depth, while highly sensitive operations may also require recent re-authentication.

119. What is CORS?SecurityEasy

Question Details

Define Cross-Origin Resource Sharing as an HTTP-header mechanism through which a server can permit selected cross-origin browser reads that the same-origin policy would otherwise restrict. Explain simple requests, preflight requests, allowed origins, methods, headers, credentials, caching, and why CORS is neither authentication nor a way to stop non-browser clients from sending requests.

Short Interview Answer (30-60 seconds)

CORS is an HTTP-header mechanism that lets a server permit selected cross-origin browser reads that the same-origin policy would otherwise restrict. It controls allowed origins, methods, headers, and credentials. It is not authentication or authorization, and non-browser clients are not stopped by CORS.

Detailed Explanation

CORS is a browser rule that controls when a website opened from one place can read information returned by a different website or service. Browsers normally keep different places separated so one website cannot freely read another website's replies. The service receiving the request can choose which websites are allowed to read its reply. Some requests can be sent immediately, while others need an extra permission check first. The service can also decide whether requests using cookies or similar account information are allowed. This browser rule does not prove who a user is or decide what that user may access.

Useful Questions to Ask the Interviewer
  1. Should I explain both simple requests and preflighted requests?
  2. Should I include credentialed requests such as requests using cookies or HTTP authentication?
  3. Should I also explain what security checks must still happen on the server?
What is CORS? diagram
How to Explain It in an Interview

CORS stands for Cross-Origin Resource Sharing. It is an HTTP-header mechanism through which a server tells a browser which cross-origin responses browser JavaScript is allowed to read.

An origin is the combination of scheme, host, and port. For example, https://app.example.com and https://api.example.com are different origins because their hosts differ. Browsers normally enforce the same-origin policy, which restricts JavaScript from reading responses from another origin. CORS gives the server a controlled way to relax that restriction for selected origins.

For a cross-origin request that qualifies as a CORS simple request, the browser can send the request without a preflight. It includes an Origin header, for example Origin: https://app.example.com. If the server wants that origin to be able to read the response, it can return Access-Control-Allow-Origin: https://app.example.com. The browser checks the CORS response headers before exposing the response to JavaScript.

A request qualifies as simple only when it satisfies specific CORS safelist rules. Its method must be GET, HEAD, or POST, and any manually set request headers and, for POST, the Content-Type must meet the CORS safelist requirements. For example, a POST using application/json is not a simple request and normally requires preflight.

When a request requires preflight, the browser first sends an OPTIONS request. That preflight asks whether the server permits the intended cross-origin operation. It contains Origin and Access-Control-Request-Method, and it can also contain Access-Control-Request-Headers when the real request plans to use non-safelisted headers.

The server can answer with headers including Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers. The browser evaluates that response. If the preflight does not grant the required permission, the browser does not send the actual preflighted request.

Allowed origins should be configured deliberately. Access-Control-Allow-Origin: * allows any origin to access a CORS response when credentials mode is not include. For sensitive browser APIs, the server should normally allow only the origins that genuinely need access. If the server dynamically chooses an allowed origin from the request's Origin header, it must validate that value against a trusted allowlist. Blindly reflecting every supplied Origin defeats the purpose of restricting origins.

CORS can also govern methods and request headers. During preflight, Access-Control-Allow-Methods tells the browser which methods the server permits for the cross-origin request, and Access-Control-Allow-Headers tells it which requested non-safelisted headers are permitted. These are browser CORS permissions. They do not replace server-side authentication, authorization, input validation, or business rules.

Credentials need special care. For Fetch, credentials include cookies, TLS client certificates, and HTTP authentication credentials. A cross-origin Fetch request that needs credentials such as cookies commonly uses credentials: "include". For the browser to expose a credentialed cross-origin response, the server must return Access-Control-Allow-Credentials: true and must return a specific permitted origin in Access-Control-Allow-Origin; it cannot use * for that credentialed response.

CORS does not override cookie policy. Cookies are separately controlled by attributes such as Secure, HttpOnly, SameSite, Domain, and Path. Whether a cookie is actually sent therefore depends on cookie rules as well as the Fetch credentials mode. For cross-site cookie use, the cookie's SameSite policy is especially important.

Preflight permissions can be cached. A server may send Access-Control-Max-Age to tell the browser how long a successful preflight result may be reused, subject to browser-specific limits. This can reduce repeated OPTIONS requests and their extra latency. A long cache period can also delay the effect of a changed CORS policy until the cached permission expires.

When a server returns different Access-Control-Allow-Origin values depending on the request's Origin, it should send Vary: Origin. This tells HTTP caches that the response can vary according to the Origin request header and helps prevent cached CORS metadata for one origin from being incorrectly reused for another.

The most important security point is that CORS is not authentication. It does not prove who the user is. It is also not authorization. The trusted server must authenticate requests where required and enforce authorization for every protected resource and operation. A request coming from an allowed origin must not automatically be trusted.

CORS is also not a firewall. It does not generally prevent HTTP requests from reaching a server. CORS enforcement is mainly performed by browsers when scripts make cross-origin requests and try to access the results. Tools such as curl, backend services, native applications, and other non-browser clients do not become unable to call an API simply because its CORS policy would reject a browser origin. The server must therefore protect sensitive endpoints with real server-side security controls.

CORS should also not be confused with CSRF. CORS primarily governs cross-origin browser access to responses and introduces preflight checks for certain cross-origin requests. CSRF is an attack in which a victim's browser is induced to perform an unwanted authenticated action. Appropriate CSRF defenses can include SameSite cookies, anti-CSRF tokens, and server-side Origin or Referer validation where suitable. CORS alone is not a complete CSRF defense.

The practical rule is: allow only the browser origins that need cross-origin access, allow only necessary methods and headers, enable credentials only when needed, cache preflight results carefully, and keep authentication and authorization on the trusted server. Then verify the policy from both permitted and unpermitted origins.

Technical Approach
  1. Identify the frontend origin and API origin. If their scheme, host, or port differs, the browser request is cross-origin.
  2. Decide exactly which browser origins need access and maintain a strict server-side allowlist.
  3. Determine whether each request qualifies as a simple request or requires preflight because of its method, headers, or Content-Type.
  4. Return only the required CORS response headers for approved origins, methods, and headers.
  5. Enable credentialed cross-origin access only when necessary, use a specific allowed origin rather than *, and configure credentials consistently on the browser and server.
  6. Keep authentication, authorization, validation, and CSRF protections independent of CORS.
  7. Configure preflight caching carefully and send Vary: Origin when the response's allowed origin varies by request Origin.
  8. Test permitted and unpermitted origins, simple requests, preflighted requests, credentialed requests, and authorization failures.
Practical Insights

CORS itself usually adds little application CPU or memory work. A simple cross-origin request does not require an extra preflight network round trip. A preflighted request can add an OPTIONS request before the real request, increasing latency and server traffic. Successful preflight results can be cached to reduce that cost. The main operational cost is maintaining correct origin, method, header, credential, and cache policies across environments. CORS configuration also needs testing because a policy that is too strict can break legitimate browser clients, while a policy that is too broad can expose responses to unintended browser origins.

Why Interviewers Ask This

Interviewers want to know whether you understand the browser same-origin policy, how a server selectively relaxes it with CORS response headers, when preflight requests occur, how credentials and preflight caching affect the policy, and where the real security boundary exists. A strong answer also makes clear that CORS does not authenticate users, does not replace server-side authorization, and does not prevent non-browser HTTP clients from contacting an API.

Common interview mistakes

Common mistakes include saying CORS blocks all cross-origin network requests; confusing the same-origin policy with a rule that prevents all requests from being sent; treating Access-Control-Allow-Origin: * as appropriate for every API; blindly reflecting any Origin value; attempting to use wildcard Access-Control-Allow-Origin with credentialed requests whose credentials mode is include; forgetting that cookies have separate SameSite, Secure, HttpOnly, Domain, and Path rules; forgetting Vary: Origin when the allowed origin is selected dynamically; assuming a successful preflight authenticates or authorizes a user; treating CORS as a complete CSRF defense; and assuming CORS prevents curl, backend services, native applications, or other non-browser clients from contacting the API.

Interview tip

Start with the same-origin policy, then define CORS as the server-controlled HTTP-header mechanism that selectively permits cross-origin browser reads. Explain simple requests and preflight, then cover origins, methods, headers, credentials, and preflight caching. Finish by stating clearly that CORS is neither authentication nor authorization and that the trusted server must enforce access control.

Interviewer may ask next
What is a CORS preflight request, and when does the browser send one?

A CORS preflight is an OPTIONS request that the browser sends before a cross-origin request that does not qualify as a simple request. The preflight includes the request Origin and intended method and can list the non-safelisted headers the real request wants to send. The server replies with CORS headers describing what it permits. If the required permission is not granted, the browser does not send the actual preflighted request. Successful preflight results may be cached using Access-Control-Max-Age, subject to browser limits.

Why does allowing an origin with CORS not mean that users from that origin are authorized?

CORS and authorization solve different problems. CORS tells a browser whether JavaScript from an origin may access a cross-origin response. Authorization tells the trusted server whether a particular authenticated user or client is allowed to perform an operation on a resource. An allowed origin can serve many users with different permissions and can also contain compromised or third-party code. The server must therefore authenticate where required and enforce authorization on every protected operation regardless of the CORS result. Non-browser clients can also contact the server without browser CORS enforcement.

120. Why is `textContent` generally safer than `innerHTML` for untrusted text?SecurityEasy

Question Details

A message component receives a display name and comment from an API under the application's origin. Explain how assigning those strings to textContent differs from parsing them through innerHTML, which DOM sink creates executable markup risk, and when a reviewed sanitizer is required for intentionally allowed rich text. Include attribute, URL, and script-context boundaries rather than claiming one encoding works everywhere.

Short Interview Answer (30-60 seconds)

textContent treats untrusted input as plain text, so HTML-looking characters are displayed instead of parsed into elements. innerHTML parses strings as HTML and can create XSS risk. Use a reviewed sanitizer only when the application intentionally allows rich HTML.

Detailed Explanation

See the Code while reading this explanation.

The safest choice depends on what the page is supposed to show. If a name or comment should appear only as ordinary text, the browser should display those characters exactly as data instead of treating them as page instructions. Data coming from your own application service can still contain unexpected or harmful values, so its source alone does not make it safe. If users are intentionally allowed to submit formatted content, the application needs a carefully reviewed cleaning step before showing that formatting. Different places on a page also need different safety rules.

Useful Questions to Ask the Interviewer
  1. Should the display name and comment be plain text only, or is any rich HTML intentionally allowed?
  2. If rich text is allowed, which HTML elements, attributes, and URL schemes are permitted?
  3. Does the application already use a reviewed HTML sanitizer or a Trusted Types policy?
Why is `textContent` generally safer than `innerHTML` for untrusted text? diagram
How to Explain It in an Interview

I would start with the required output type. If the API values are only a display name and comment, I would assign them with textContent or create text nodes. textContent is a safe DOM construction choice for this case because the browser treats the value as text. For example, the string <img src=x onerror=alert(1)> appears as visible text instead of becoming an image element with an event handler.

innerHTML is different. It is an HTML-parsing DOM sink: assigning a string to it asks the browser's HTML parser to create DOM nodes from that string. If attacker-controlled or otherwise untrusted data reaches that sink, dangerous markup can become part of the document and may lead to cross-site scripting, or XSS. The important trust-boundary point is that data from an API under the application's own origin is not automatically safe. Stored user content, compromised backend data, or incorrectly validated data can still reach the frontend.

For plain text, I would therefore prefer textContent, document.createTextNode(), or framework rendering that escapes text by default. I would not use innerHTML merely because the data came from my own server.

If the product intentionally supports rich text, such as a limited set of links, emphasis, and lists, then textContent is not enough because it would display the markup literally. In that case, I would use a well-reviewed HTML sanitizer configured with a narrow allowlist and insert only the sanitizer's approved output. Sanitization is appropriate because some HTML is intentionally being preserved. Simple input filtering or a few regular expressions are not complete XSS defenses.

Safety is contextual. textContent solves the text-node case, but one encoding rule does not work everywhere. For normal non-event attributes, prefer specific DOM properties or carefully chosen DOM APIs and validate values according to what that attribute permits. Never place untrusted strings into inline event-handler attributes such as onclick. URL-bearing properties such as href and src need URL parsing plus allowed-scheme and, when required, allowed-destination checks because a URL can be dangerous even when it contains no HTML tags. Untrusted strings should not be turned into JavaScript code at all; avoid eval(), new Function(), inline script construction, and string-based event handlers.

Defense in depth can further reduce impact. A restrictive Content Security Policy can limit which scripts may execute if an XSS bug remains. Trusted Types, where supported and deployed, can restrict dangerous DOM injection sinks so arbitrary strings cannot casually reach them. If a site enforces Trusted Types for script-related sinks, rich HTML insertion must also follow the site's Trusted Types policy rather than assigning an ordinary string directly. CSP and Trusted Types support safe DOM construction; they do not make unsafe innerHTML assignments acceptable.

The safe failure behavior is simple: if rich content cannot be sanitized according to the approved policy, render it as plain text or reject that rich rendering instead of falling back to raw HTML. Security logging can record that sanitization or validation failed, but it should avoid storing secrets, authentication tokens, or unnecessary private content.

I would verify the control with tests containing HTML tags, event-handler attributes, malformed markup, suspicious URL schemes, and ordinary special characters. For plain-text fields, the test should confirm that attacker-controlled input produces only text and does not create attacker-controlled elements, event handlers, or executable code.

Key Insight / Why This Solution Works
  1. Decide whether the value is supposed to be plain text or intentionally allowed rich HTML.
  2. Treat API-provided user-controlled strings as untrusted even when the API uses the application's origin.
  3. For plain text, use textContent, text nodes, or framework text rendering instead of HTML-parsing sinks.
  4. For intentional rich HTML, pass the value through a reviewed sanitizer with a narrow allowlist before any HTML insertion.
  5. Handle normal attributes, URLs, event handlers, and script-related contexts with context-specific APIs and validation rather than reusing HTML encoding.
  6. Never turn untrusted strings into JavaScript code.
  7. Add defense-in-depth controls such as CSP and Trusted Types where appropriate.
  8. Fail safely by rendering plain text or rejecting unsafe rich content.
  9. Test with malicious markup, event handlers, suspicious URLs, malformed input, and normal special characters.
Code
function renderMessage(container, apiMessage) {
  // Values received from the API cross a trust boundary even when the API
  // uses this application's origin; stored user content may still be hostile.
  const wrapper = document.createElement('article');
  const name = document.createElement('strong');
  const comment = document.createElement('p');

  // These fields are defined as plain text, so textContent is the correct sink.
  // HTML-looking input stays data and is not parsed into executable markup.
  name.textContent = String(apiMessage.displayName ?? '');
  comment.textContent = String(apiMessage.comment ?? '');

  // Replace the old rendered message only with DOM nodes we constructed safely.
  container.replaceChildren(wrapper);
  wrapper.append(name, comment);
}

function setProfileLink(anchor, rawUrl) {
  // URLs need URL-specific validation; HTML escaping does not make a URL safe.
  let url;
  try {
    url = new URL(String(rawUrl), location.origin);
  } catch {
    // Fail safely by removing navigation when the value is not a valid URL.
    anchor.removeAttribute('href');
    return false;
  }

  // Allow only the web protocols required by this example and reject other schemes.
  // A real product may also need an allowlist of permitted hosts or destinations.
  if (url.protocol !== 'https:' && url.protocol !== 'http:') {
    anchor.removeAttribute('href');
    return false;
  }

  // Assign the validated URL through the URL property rather than building HTML text.
  anchor.href = url.href;
  return true;
}

function renderReviewedRichText(container, untrustedHtml, sanitizeHtml) {
  // Rich HTML is allowed only because this function represents an explicit product requirement.
  // sanitizeHtml must be a reviewed sanitizer or Trusted Types-aware policy owned by the application.
  if (typeof sanitizeHtml !== 'function') {
    // Fail closed: display the value as text instead of falling back to raw HTML.
    container.textContent = String(untrustedHtml ?? '');
    return false;
  }

  const sanitizedHtml = sanitizeHtml(String(untrustedHtml ?? ''));

  // Only reviewed sanitizer output may reach this HTML-parsing sink.
  // When Trusted Types enforcement is enabled, this value must satisfy that policy.
  container.innerHTML = sanitizedHtml;
  return true;
}
Why Interviewers Ask This

The interviewer is checking whether the candidate understands DOM-based XSS risk, the difference between inserting text and parsing HTML, trust boundaries around API data, contextual output handling, and when sanitization is appropriate. They also want to see whether the candidate avoids broad claims such as treating same-origin API data as automatically trusted or assuming one encoding method is safe in every browser context.

Common interview mistakes

Common mistakes include saying that same-origin API data is automatically trusted, using innerHTML for plain text because it is convenient, escaping only < and > and calling the result safe, writing a home-grown regular-expression sanitizer, or claiming one HTML encoding method protects every context. Another mistake is using HTML escaping for URLs without validating schemes or required destinations. Using setAttribute() with attacker-controlled inline event-handler attributes is also unsafe. Candidates should not claim CSP or Trusted Types replaces safe DOM construction. For rich HTML, failing open to raw innerHTML when sanitization fails is unsafe. Tests should verify that dangerous input creates no executable DOM behavior.

Interview tip

Lead with the decision: plain text goes to textContent; intentional rich HTML requires reviewed sanitization before an HTML-parsing sink. Then explain why API origin does not equal trust, and finish by noting that attributes, URLs, event handlers, and script contexts need their own safe handling.

Interviewer may ask next
If the application intentionally allows users to enter bold text and links, can we still use `textContent`?

textContent would safely display the markup as literal characters, so it cannot preserve intended formatting. If rich HTML is a real requirement, use a reviewed sanitizer with a narrow allowlist for permitted elements, attributes, and URL schemes, then insert only the sanitizer's approved output. If Trusted Types is enforced, follow the application's Trusted Types policy for the sink. Do not build a sanitizer with regular expressions, and fail safely to plain text or rejection if sanitization is unavailable.

Does HTML escaping make an untrusted value safe to use in an `href` attribute or JavaScript context?

No. Safety depends on the output context. For an href, parse and validate the URL and allow only expected schemes and, when necessary, expected destinations before assigning the DOM property. For JavaScript contexts, do not construct executable code from untrusted strings; avoid eval(), new Function(), inline script construction, and string-based event handlers. Text-node or HTML escaping rules cannot be reused as a universal security control.

More questions load as you scroll

Disclaimer: This interview guide is for educational and informational purposes only. It is designed to help readers prepare, but it does not guarantee any interview result, hiring decision, offer, or outcome. Interview questions, hiring criteria, and preferred answers can vary by employer, interviewer, industry, location, and time. The examples and explanations reflect the authors' research and judgment, are provided without warranties of any kind, and should not be treated as the only correct approach. Diagrams are simplified illustrations intended to highlight the main components and their interactions; actual systems and implementations may be more complex. Alternative approaches may be equally valid or better suited to a particular question, context, or interviewer. To the fullest extent permitted by applicable law, the author, contributors, and publisher are not liable for decisions made, actions taken, or losses incurred based on this guide.