If you maintain a lot of Umbraco installs, managing your security health can be a big task. When a new advisory is released, you suddenly have a lot of work to do.
The Umbraco Security Dashboard helps by providing regular automatic checks of the running code against the Github Vulnerability Database for Umbraco packages and allows you to report the security health status of the instance to a central location via webhook.
The system also provides checks against common vulnerability exposure points to help you understand which advisories your instance is actually susceptible to. For instance, if the advisory reports an exposure in the Content Delivery API, but you have it disabled, then that exposure is mitigated. This helps you triage your efforts to focus on the instances where you're actually exposed.
To add the package to your project, install it with NuGet:
dotnet add package BlendInteractive.SecurityDashboardThis will add a 'Security Health' tab in the 'Settings' section of your Backoffice.
All settings live under the Umbraco:SecurityDashboard key in appsettings.json.
"Umbraco": {
"SecurityDashboard": {
"AdditionalPackageIds": [],
"Webhook": {
"SiteUrl": "https://yoursite.com",
"EndpointUrl": "https://your-webhook-endpoint.com/hook",
"Secret": "your-secret",
"TimeoutSeconds": 10
}
}
}A list of non-Umbraco NuGet package IDs to include in vulnerability checks. Versions are detected automatically from the runtime dependency graph.
"AdditionalPackageIds": [ "Serilog", "Newtonsoft.Json" ]When configured, the dashboard posts the scan result to an external endpoint after every check, making it easy to aggregate security status across multiple Umbraco instances.
| Property | Description |
|---|---|
SiteUrl |
The public URL of this Umbraco instance. Included in the webhook payload to identify the source. This is simply an identifying string since the web context isn't available in the scheduled check. |
EndpointUrl |
The URL to POST the result to. Leave empty to disable webhook notifications. |
Secret |
Shared secret included in the request header for payload verification. |
TimeoutSeconds |
HTTP timeout for the webhook request. Defaults to 10. |
The Development subsection contains settings that are only applied when the application is running in the Development environment. They are silently ignored in all other environments.
"Umbraco": {
"SecurityDashboard": {
"Development": {
"PackageVersionOverrides": {
"Umbraco.Cms": "17.1.1"
},
"ExposureCheckOverrides": {
"GHSA-xxxx-yyyy-zzzz": [ "Content Delivery API" ]
}
}
}
}PackageVersionOverrides — substitute the detected version of any NuGet package with a fixed value. Useful for testing how the dashboard behaves against a specific advisory without actually downgrading the package.
ExposureCheckOverrides — force one or more exposure checks to run for a specific advisory, regardless of whether the corresponding keyword appears in the advisory description. The key is the GHSA ID (e.g. GHSA-xxxx-yyyy-zzzz) and the value is a list of exposure check keywords (e.g. "Content Delivery API", "Non-Admin Backoffice Users"). Useful for manually exercising exposure checks against a chosen advisory during development.
Exposure checks determine whether your instance is actually susceptible to a given advisory. The package ships with two built-in checks, but you can add your own.
1. Implement IExposureCheck:
using Umbraco.SecurityDashboard.Services.Exposure;
public class PublicRegistrationExposureCheck : IExposureCheck
{
// Must match a keyword that appears in advisory descriptions.
// The evaluator only runs this check when the keyword is found.
public string Keyword => "Member Registration";
public Task<ExposureVerdict> CheckAsync(CancellationToken cancellationToken = default)
{
// Return Vulnerable, Mitigated, or NotAffected
bool registrationOpen = /* your logic here */ true;
var verdict = registrationOpen ? ExposureVerdict.Vulnerable : ExposureVerdict.Mitigated;
return Task.FromResult(verdict);
}
}2. Register it in your composer or Program.cs:
builder.AddExposureCheck<PublicRegistrationExposureCheck>();The check runs only when the Keyword appears in the advisory text, so it doesn't add overhead for unrelated advisories. If the check throws, the evaluator logs the exception and treats the result as Vulnerable.
Built-in checks:
| Keyword | What it checks |
|---|---|
Content Delivery API |
Whether the Umbraco Delivery API is enabled |
Non-Admin Backoffice Users |
Whether any non-admin backoffice users exist |
This project uses Spec-Kit for structured feature development. Feature specifications live in specs/ and drive the implementation workflow.
# Review the current feature plan
cat specs/007-audit-log/plan.md
# Run the implementation agent against the active plan
/speckit-implementEach spec directory contains a plan.md with the feature design and a tasks.md with the implementation checklist. Completed specs are kept for reference.