Content Security Policy, commonly called CSP, is one of the most useful browser security controls for modern web applications.

A properly configured CSP can restrict where a page is allowed to load scripts, styles, images, fonts, frames, and other resources. This can significantly reduce the impact of certain cross-site scripting and injection attacks.

Blazor applications can be sensitive to CSP configuration because rendering interactive UI involves framework scripts, dynamically updated DOM content, and, depending on the application, generated markup and styles.

Virtualize<TItem> deserves particular attention because virtualization needs to maintain the correct amount of scrollable space while rendering only the items that are currently needed.

In earlier Blazor implementations, virtualization could rely on dynamically generated spacer elements and inline style attributes to control the size of those spaces. A strict CSP can reject inline styles when the policy doesn't allow them.

The .NET 11 implementation improves this behavior by using a CSS custom property for virtualization spacer sizing rather than continually generating the required size through an inline style attribute. This makes the virtualization implementation more compatible with strict CSP configurations.

That does not mean Blazor applications automatically become CSP-secure by upgrading. CSP is an application-wide security policy, and developers still need to configure it correctly and review scripts, styles, third-party resources, and other browser capabilities.

What Is Content Security Policy?

CSP is a browser-enforced security policy delivered by the application.

A policy can restrict different types of resources.

For example:

script-src
style-src
img-src
font-src
connect-src
frame-src

A simplified policy might look like:

default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self';
connect-src 'self';

The browser evaluates resource requests against these rules.

If the application attempts to load something that violates the policy, the browser can block it and report the violation.

The purpose isn't to make every browser request originate from the same location. Instead, CSP lets developers define which resource sources and execution mechanisms are permitted.

Why CSP Matters for Blazor Applications

Blazor applications contain more than ordinary static HTML.

Depending on the hosting model, the application can involve:

A strict CSP therefore needs to be designed around the actual application.

For example, an application might use:

Browser
   |
   +-- HTML
   +-- CSS
   +-- JavaScript
   +-- Blazor framework
   +-- SignalR connection
   +-- API requests
   +-- Images

Each of these can have different CSP implications.

A policy that is too permissive provides less protection.

A policy that is too restrictive can break legitimate application functionality.

How Virtualize Works

Virtualize<TItem> is designed for large lists.

Instead of rendering every item, it renders only the items near the visible viewport.

For example:

<Virtualize Items="Products" Context="product">
    <div class="product-row">
        <strong>@product.Name</strong>
    </div>
</Virtualize>

Conceptually, the browser sees something like:

Top spacer
Visible item
Visible item
Visible item
Visible item
Bottom spacer

As the user scrolls, the component changes which items are rendered.

The spacer areas are important because they make the scrollbar represent the position of the complete collection even though only a subset of records exists in the DOM.

The size of those spacer areas therefore has to change as the virtualized viewport changes.

Why Spacer Elements Matter

Imagine a list containing 100,000 records.

The browser may render only 30 of them.

If the user is viewing items around position 50,000, the browser still needs to create enough virtual space above the rendered items to make the scrollbar behave as though the previous 50,000 items exist.

Conceptually:

+-------------------------+
|                         |
|     Top spacer          |
|                         |
+-------------------------+
| Item 50000              |
| Item 50001              |
| Item 50002              |
| ...                     |
+-------------------------+
|     Bottom spacer       |
|                         |
+-------------------------+

The spacer height changes as the user scrolls.

This is one of the places where virtualization interacts directly with CSS layout.

The CSP Problem with Inline Styles

A traditional way to set a dynamically calculated spacer size is an inline style:

<div style="height: 2400px"></div>

This is convenient because the exact height can be written directly onto the element.

However, a strict CSP can prohibit inline styles.

For example, a policy containing:

style-src 'self'

doesn't automatically permit arbitrary inline style attributes.

A browser can therefore report a CSP violation when application code attempts to use an inline style that the policy doesn't allow.

This creates an awkward situation:

Virtualization needs dynamic size
            |
            v
Inline style
            |
            v
Strict CSP blocks inline style

The application may then experience broken or incorrect virtualization behavior.

CSS Custom Properties Provide a Better Model

CSS custom properties, also called CSS variables, allow a value to be passed into CSS while keeping the actual styling rules in a stylesheet.

For example:

.virtual-spacer {
    height: var(--virtual-size);
}

The dynamic value can then be represented as a custom property.

Conceptually:

CSS rule
   |
   v
height: var(--virtual-size)
   |
   v
Dynamic virtualization value

The important .NET 11 change is that Virtualize uses a CSS custom property for the spacer sizing rather than relying on the previous inline style approach.

This reduces the conflict between virtualization and strict CSP policies.

Why This Is Better for Strict CSP

A strict CSP attempts to minimize unsafe execution and styling mechanisms.

Moving dynamic virtualization sizing away from an ordinary inline style declaration means the framework no longer needs that particular inline style mechanism for its spacer calculations.

This has several benefits:

Fewer CSP Exceptions

You don't need to weaken the stylesheet policy simply because virtualization needs to calculate spacer dimensions.

Cleaner Separation Between Style and Data

The CSS rule defines how the spacer behaves, while the dynamic value supplies the size.

Better Compatibility with Security Policies

Applications can maintain a stricter style-src policy without adding a broad allowance solely for virtualization.

Less Pressure to Use Unsafe Workarounds

Developers don't need to solve the problem by immediately adding:

style-src 'unsafe-inline'

to their CSP.

unsafe-inline Is Not a Good Default

When a strict CSP blocks inline styles, a tempting solution is:

style-src 'self' 'unsafe-inline'

This allows inline styles, but it weakens the policy.

The problem isn't that every inline style is automatically malicious. The issue is that a broad exception makes it harder for CSP to enforce a strict styling boundary.

Therefore, don't add 'unsafe-inline' simply because a component stopped working.

First determine why the inline style is being generated and whether the framework version already provides a CSP-compatible implementation.

For .NET 11 virtualization, the improved spacer rendering reduces the need for this type of CSP relaxation.

Example of a Strict CSP

A starting policy might look like:

default-src 'self';
script-src 'self';
style-src 'self';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
frame-ancestors 'none';
base-uri 'self';
form-action 'self';

This is only an example.

A production policy must be based on the resources and capabilities actually used by the application.

For example, an application using a remote API needs the appropriate connect-src entries.

An application using externally hosted images needs corresponding img-src entries.

Do not copy a CSP from another application and assume it is correct.

Blazor Scripts and CSP

Blazor applications may require framework JavaScript.

The policy must therefore allow legitimate application scripts to execute.

A common mistake is creating an extremely restrictive:

script-src 'self'

policy and then discovering that application functionality doesn't work because the application's actual script-loading or execution model requires additional handling.

When implementing CSP, inspect the generated page and browser console.

Look for blocked script resources and CSP violation messages.

Don't blindly add broad exceptions such as:

script-src 'unsafe-inline' 'unsafe-eval'

just to make the errors disappear.

Understand which operation is being blocked first.

Stylesheet Configuration

The same principle applies to CSS.

External application stylesheets are generally easier to manage under a strict CSP:

<link rel="stylesheet"
      href="css/app.css">

The policy can then allow styles from the application's own origin:

style-src 'self'

The exact policy still depends on the application's architecture.

If third-party style resources are used, those sources must be evaluated carefully.

CSP Does Not Replace Input Validation

It is important not to misunderstand CSP.

CSP is a browser security control. It is not a replacement for:

For example, this is still unsafe:

var sql = $"SELECT * FROM Users WHERE Name = '{name}'";

A strong CSP does not make string-built SQL safe.

Use parameterized database operations instead.

CSP should be one layer in a broader defense-in-depth strategy.

CSP and Blazor Interactive Rendering

Blazor applications can use different interactive rendering approaches.

Depending on the application, you may have:

Each model can have different resource and connection requirements.

For example, Interactive Server applications maintain a connection between the browser and server for interactive component updates.

A CSP should therefore account for the application's actual connection endpoints.

If a policy blocks required connections, interactive functionality can fail even though the HTML initially loads correctly.

connect-src and Interactive Applications

The connect-src directive controls destinations used by browser connections such as fetch requests and WebSocket connections.

A restrictive policy might be:

connect-src 'self';

If the application connects only to its own origin, this may be appropriate.

If the application communicates with a separate API host, that host must be considered.

For example, conceptually:

Blazor application
       |
       +----> Application API
       |
       +----> Authentication service

The CSP must reflect those legitimate connections.

This is separate from the Virtualize improvement, but it is an important consideration when securing an interactive Blazor application.

A Practical CSP Troubleshooting Workflow

When enabling CSP on a Blazor application, don't immediately switch to a permissive policy.

Use a controlled process.

Step 1: Start with the Application's Actual Resources

Identify:

Step 2: Apply the Policy

Configure the CSP through the preferred HTTP response-header mechanism.

Step 3: Open Browser Developer Tools

Look at the Console and Network panels.

CSP violations usually provide useful information about what was blocked.

Step 4: Identify the Specific Directive

For example:

style-src
script-src
connect-src
img-src

Don't treat every CSP error as the same problem.

Step 5: Determine Whether the Resource Is Legitimate

Ask:

Does the application actually need this resource?

If not, don't add it to the policy.

Step 6: Fix the Application or Policy

If a legitimate resource is blocked, adjust the policy appropriately.

If an unnecessary resource is being loaded, remove it instead.

Testing Virtualize Under CSP

A virtualized list should be tested separately from ordinary page rendering.

For example:

<Virtualize Items="Products"
            ItemSize="80"
            Context="product">

    <div class="product-card">
        <h3>@product.Name</h3>
        <p>@product.Description</p>
    </div>

</Virtualize>

Then test:

  1. Initial page load

  2. Slow scrolling

  3. Fast scrolling

  4. Deep scrolling

  5. Variable-height items

  6. Expanded items

  7. Collapsed items

  8. Images loading after render

  9. CSP-enabled browser session

  10. Browser console for CSP violations

A list that looks correct at the top of the page isn't necessarily functioning correctly throughout a large dataset.

Variable-Height Items Under Strict CSP

The combination of variable-height content and CSP is particularly interesting.

Consider:

<Virtualize Items="Messages"
            ItemSize="90"
            Context="message">

    <article class="message">
        <h3>@message.Subject</h3>

        <p>@message.Preview</p>

        @if (message.Expanded)
        {
            <div class="message-details">
                @message.Body
            </div>
        }
    </article>

</Virtualize>

The item can change height after the user expands it.

The virtualization system needs to update its layout calculations.

The .NET 11 improvements make these dynamic measurements more compatible with strict CSP environments by changing how spacer sizing is represented.

However, developers should still avoid unnecessary layout shifts.

For example, if an image has a known aspect ratio, reserve that space:

.message-image {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

Security and layout quality are separate concerns, but good layout practices make virtualization more stable.

Common Mistakes

Allowing unsafe-inline Without Investigation

If CSP reports an inline-style violation, don't immediately add:

style-src 'unsafe-inline'

Investigate the source first.

Assuming .NET 11 Makes the Entire App CSP-Compliant

The virtualization improvement addresses a specific rendering concern.

It does not automatically configure a secure CSP for the entire application.

Copying a CSP from Another Project

Different applications have different resource requirements.

A policy that works for one project can break another.

Ignoring Browser Console Errors

CSP problems are often clearly reported by the browser.

The console should be one of the first places you look.

Using an Overly Broad Source List

Avoid policies like:

default-src *

when the application doesn't require that level of access.

A CSP should be intentionally restrictive.

Assuming CSP Prevents All XSS

CSP reduces certain attack opportunities, but secure application development still requires correct encoding, validation, authentication, authorization, and dependency management.

Troubleshooting Virtualize and CSP Together

Symptom

Possible Cause

What to Check

List doesn't scroll correctly

Virtualization layout issue

Container height and CSS

CSP reports inline style violation

Inline style rejected

Browser console and generated DOM

List works without CSP

Security policy conflict

style-src configuration

Interactive UI fails

Required connection blocked

connect-src

Scripts fail to load

Script source blocked

script-src

Images disappear

Image source blocked

img-src

Styles don't load

Stylesheet source blocked

style-src

Variable-height items jump

Dynamic layout changes

Item dimensions and content

Third-party component fails

Resource not permitted

Required CSP directives

Best Practices

  1. Start with a restrictive CSP and add only legitimate requirements.

  2. Test the policy using real application workflows.

  3. Monitor browser CSP violation reports during rollout.

  4. Avoid broad 'unsafe-inline' allowances when they aren't necessary.

  5. Keep application styles in stylesheets whenever practical.

  6. Understand which CSP directive controls each resource type.

  7. Test Virtualize with both fixed-height and variable-height content.

  8. Give virtualized items a sensible initial ItemSize.

  9. Reserve space for images where dimensions are predictable.

  10. Keep virtualized item components reasonably lightweight.

  11. Test Interactive Server applications with the actual connection policy.

  12. Treat CSP as one layer of defense-in-depth rather than a complete security solution.

Advantages

Better CSP Compatibility

The updated virtualization rendering avoids depending on the same inline style approach that can conflict with strict style policies.

Less Need to Relax Security Policies

Developers can avoid weakening style-src merely to accommodate virtualization spacer sizing.

Better Variable-Height Virtualization

The improved measurement behavior works better with real interfaces where item heights can change.

Cleaner Rendering Architecture

CSS can describe how virtualization spacers are styled while the dynamic value is supplied separately.

Easier Security Reviews

Reducing unnecessary inline styling can make it easier to understand and enforce a strict styling policy.

Disadvantages and Trade-Offs

CSP Still Requires Application-Specific Configuration

The framework cannot determine every external resource your application legitimately needs.

Other Blazor Features Can Still Trigger CSP Issues

Scripts, connections, third-party libraries, and other resources may require additional policy configuration.

Browser Support Still Matters

Security policies and browser behavior are implemented by the browser, so applications should test their supported browser range.

Virtualization Is Still Sensitive to Layout

CSP compatibility doesn't eliminate the need for correct CSS and sensible item dimensions.

Production Checklist

Before enabling a strict CSP on a Blazor application that uses virtualization, verify:

Area

Check

CSP

Policy is explicitly defined

Scripts

Required application scripts are allowed

Styles

Required stylesheets are allowed

Images

Legitimate image sources are allowed

Fonts

Required font sources are allowed

Connections

API and interactive connections work

Virtualize

Large lists render correctly

Variable heights

Expanded/dynamic content remains stable

Browser console

No unexpected CSP violations

Third-party components

Their required resources are understood

Security

No unnecessary broad CSP exceptions

Final Takeaway

Strict CSP policies and dynamic web interfaces have historically required careful coordination.

Blazor's Virtualize<TItem> is a good example because virtualization needs to change spacer dimensions dynamically as the user scrolls. If those dimensions are represented through inline styles, a strict style-src policy can become an obstacle.

.NET 11 improves this situation by using CSS custom-property-based rendering for virtualization spacer sizing and by improving handling of variable-height items.

That is a useful security improvement, but it should be understood correctly.

It does not mean that enabling .NET 11 automatically gives an application a secure CSP.

A production Blazor application should still:

Define a restrictive CSP
        |
        v
Identify legitimate resources
        |
        v
Allow only required sources
        |
        v
Test scripts and connections
        |
        v
Test Virtualize and dynamic content
        |
        v
Monitor CSP violations

The best approach is to treat CSP and virtualization as two parts of the same browser-rendering environment rather than solving one by weakening the other.

If your application uses large, dynamic lists and also requires a strict CSP, the .NET 11 changes make Virtualize a much more practical choice. You can keep the performance benefits of virtualization while avoiding an unnecessary security-policy exception specifically for dynamically sized spacer elements.