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:
JavaScript required by the framework
Interactive components
Dynamically rendered DOM
WebSocket or other persistent connections
CSS files
Images
Fonts
Third-party resources
Application-specific JavaScript
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:
input validation,
output encoding,
authentication,
authorization,
CSRF protection,
secure database queries,
dependency management,
secure HTTP headers.
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:
Static server-side rendering
Interactive Server
Interactive WebAssembly
Interactive Auto
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:
Scripts
Stylesheets
Images
Fonts
API endpoints
WebSocket connections
Frames
Third-party services
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:
Initial page load
Slow scrolling
Fast scrolling
Deep scrolling
Variable-height items
Expanded items
Collapsed items
Images loading after render
CSP-enabled browser session
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 |
|
Interactive UI fails | Required connection blocked |
|
Scripts fail to load | Script source blocked |
|
Images disappear | Image source blocked |
|
Styles don't load | Stylesheet source blocked |
|
Variable-height items jump | Dynamic layout changes | Item dimensions and content |
Third-party component fails | Resource not permitted | Required CSP directives |
Best Practices
Start with a restrictive CSP and add only legitimate requirements.
Test the policy using real application workflows.
Monitor browser CSP violation reports during rollout.
Avoid broad
'unsafe-inline'allowances when they aren't necessary.Keep application styles in stylesheets whenever practical.
Understand which CSP directive controls each resource type.
Test
Virtualizewith both fixed-height and variable-height content.Give virtualized items a sensible initial
ItemSize.Reserve space for images where dimensions are predictable.
Keep virtualized item components reasonably lightweight.
Test Interactive Server applications with the actual connection policy.
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.

Join the conversation! Your thoughts help the community grow.