Skip to main content

Posts

Showing posts with the label Security

Upgrading Dependency Track from v4 to v5

Dependency Track is an open source component analysis platform from OWASP. You upload the SBOM of your application, and Dependency Track keeps track of the components inside it. It checks those components against vulnerability sources like the National Vulnerability Database, GitHub Advisories and OSV. It also lets you define policies and send notifications when something new shows up. In short: it tells you which of your applications are affected when the next vulnerable library hits the news. Recently Dependency Track got an upgrade and version 5 was released. So, time to upgrade! However, that turned out not to be as easy as expected. It took us 2 attempts. Our first attempt failed completely, so we took a different route. Here is what we tried and the two things that cost us the most time. Big shout out to Jef, who looked over my shoulder during the upgrade and helped tackling the issues when we got stuck. Two approaches in the documentation The Dependency Track documenta...

Passing custom parameters through OpenIddict's client authorization request

In my passthrough authentication post , the login endpoint set a provider value on AuthenticationProperties so the OpenIddict server would know whether to challenge GitHub or ADFS: app.MapGet("login/{provider}", (string provider) => Results.Challenge(new AuthenticationProperties { RedirectUri = "/", Items = { ["provider"] = provider } }, [OpenIddictClientAspNetCoreDefaults.AuthenticationScheme])); Run that as-is and the server never sees it. Items round-trips through your own app's correlation cookie — it was never meant to become part of the outgoing OAuth2 request. Why this doesn't just work AuthenticationProperties.Items is an ASP.NET Core concept. It's how the authentication middleware remembers things like the redirect URI across the round trip to an external provider and back. The OpenIddict client builds the actual /connect/authorize request from a completely different object — an OpenIddictReq...

Passthrough authentication with OpenIddict

In most enterprise applications authentication is externalized to an external identity provider. For our applications we had to support multiple identity providers. How can we do this without tight coupling to each of these providers? In this post we'll bring OpenIddict into the picture and show how it helps to solve this nicely. What is OpenIddict? OpenIddict is an open-source OAuth2/OpenID Connect server and client stack for .NET. It plugs into ASP.NET Core Identity (or your own user store) and lets you run your own authorization server instead of depending fully on an external one. You get the standard endpoints — /connect/authorize , /connect/token , /connect/userinfo — backed by your own database and your own claims. That's exactly what makes the passthrough pattern possible: OpenIddict is the piece in the middle that can defer to external providers for the actual authentication, then still be the one issuing the token your APIs trust. The naive approach The ...

Dependency-Track: Error occurred decrypting the OSS Index API Token

We run Dependency-Track for vulnerability analysis across our projects. One day, the OSS Index integration stopped working. No API calls, no analysis results, just this in the logs: An error occurred decrypting the OSS Index API Token; Skipping [projectName=Balansen - BatchConsole, vulnAnalysisLevel=PERIODIC_ANALYSIS, projectUuid=14ba5633-58c2-45fe-9f04-e4ab0b28375e, projectVersion=DEV] javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption. BadPaddingException is Java's polite way of saying: "I tried to decrypt this with a key, and it's the wrong key." The API token itself was fine. The key used to decrypt it wasn't. The wrong assumption Our first instinct was to re-enter the OSS Index credentials in the UI and assume a fat-fingered token was the culprit. That didn't help. The error came back on the next analysis run, right after we restarted the container for an unrelated...

Safely injecting a JSON configuration object into a Razor Page

While reviewing an ASP.NET Core Razor page application that needed to share server-side configuration with client-side JavaScript, I noticed the following approach to inject a JSON object: <script> var featureFlags= @Html.Raw(Model.FeatureFlagsJson); </script> It works — until it doesn't. This post walks through the right way to do it, why the naive approach can blow up in your face, and what the production-safe pattern looks like. Remark: There was a mistake in the original version of this post. I updated it with a fixed version of the code Why the naive approach is dangerous Directly interpolating server-side values into a <script> block creates an XSS (Cross-Site Scripting) vector . If any value in your config object contains characters like </script> , " , or ' , the browser can interpret that as the end of your script tag — or worse, execute attacker-controlled code. Consider this innocent-looking config value: public string ...

GitHub Copilot SDK–Breaking change in permission handling

If you looked at an older GitHub Copilot SDK example online and copied it over, there is a chance that you see the following error message when you try to execute the code: Unhandled exception. System.ArgumentException: An OnPermissionRequest handler is required when creating a session. For example, to allow all permissions, use CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll }); at GitHub.Copilot.SDK.CopilotClient.CreateSessionAsync(SessionConfig config, CancellationToken cancellationToken) So, what exactly is happening here? The important part is this: An OnPermissionRequest handler is required when creating a session. The GitHub Copilot SDK is designed with a permission-based execution model . Whenever Copilot wants to execute a tool, access resources, or perform potentially impactful operations, the SDK expects the host application to decide whether that action is allowed. This is done through the OnPermissionRequest callback. With older...

How to fix NuGet vulnerabilities with GitHub Copilot in Visual Studio

Security vulnerabilities in your dependencies are one of those things where I know that I should address them promptly, but the process of hunting down the right package version, understanding the scope of the issue, and making the change without breaking anything can turn a five-minute fix into a frustrating rabbit hole. With the Visual Studio March 2026 update, that workflow just got a whole lot smoother. GitHub Copilot can now help you fix NuGet package vulnerabilities directly from Solution Explorer, turning what used to be a manual research task into a guided, in-editor experience. What's new? When Visual Studio detects a vulnerability in one of your NuGet packages, you'll now see a Fix with GitHub Copilot link alongside the vulnerability notification in Solution Explorer. One click is all it takes to kick off the process: Copilot analyzes the vulnerability, identifies the appropriate dependency updates, and implements them for you — without disrupting the rest of y...

ADFS policies vs authorization rules - understanding the difference

While preparing our MFA rollout at ADFS level, we started making the switch from classic authorization rules to custom access control policies in ADFS. This post explains the difference and the rationale behind this switch. A tale of two mechanisms When you work with Active Directory Federation Services (ADFS), there are two ways to control what happens when a user tries to authenticate: authorization rules and access control policies . On the surface, they feel similar; both let you define conditions around user access. But under the hood, they represent two distinct generations of the same capability. Understanding the difference matters especially when implementing MFA, because the mechanism you choose affects flexibility, maintainability, and how cleanly your logic can scale. Authorization rules: the classic approach Authorization rules are the original ADFS mechanism, introduced back when claims-based identity was first baked into the platform. They use a proprietary la...

CycloneDX 1.7 not yet supported by Dependency-Track

As part of our secure SDLC strategy, we generate an SBOM(Software Bill of Material) and store it inside Dependency Track . This gives us a good overview of all our applications, their dependencies and vulnerable components. However after upgrading to the latest CycloneDx-dotnet version, our SBOM pipeline turned out broken. The problem When uploading an XML-based Software Bill of Materials (SBOM) to Dependency-Track, we started to encounter a 400 – Bad Request response. The culprit is a version mismatch: a recent update to the dotnet-CycloneDX tool now generates SBOMs in CycloneDX 1.7 format by default — a version that Dependency-Track does not yet support. Dependency-Track validates incoming SBOMs against its supported schemas. When it receives a 1.7 document, schema validation fails and the upload is rejected entirely. The dotnet-CycloneDX package was updated our your build server, silently bumping the default output format from CycloneDX 1.6 to 1.7. No code change, just...

The silent filter: How an ASP.NET MVC quirk became a security leak

We recently discovered a bug in one of our legacy ASP.NET MVC applications — the kind that doesn't throw an exception, doesn't log a warning, and doesn't announce itself in any way. It simply silently drops a filter on the floor. Unfortunately, that filter happened to be a security control. Here's the story of what happened, why it happens, and what we're doing about it. Remark: If you don’t have any legacy .NET Full Framework ASP.NET MVC apps remaining (good for you), you can stop reading. What we were trying to do Our application uses action filters for authorization. We had a global filter registered for all controllers that enforced a baseline set of access rules. For certain controllers, we wanted a stricter policy, so we added a local filter attribute directly on those controllers. Both filters shared the same attribute type. The attribute was decorated like this: The intention was clear: the local, more restrictive filter on the controller would...

Structuring Projects in Dependency-Track

I promised yesterday that it would be my last post about how we are using Dependency Track. But turns out that there is some confusion and a few people asked me the following question: "How should I organize all these projects?" This is a good question because a well-structured project hierarchy makes the difference between a dashboard that provides clarity and one that creates confusion. In this post, I'll share the project organization strategies we've explored and practical examples you can adapt to your organization. Understanding Dependency-Track's model Dependency-Track organizes work around several key concepts: Projects : The fundamental unit representing a software component. Each project has a name and version. Remark: A project can also be flagged as current. Versions : Projects can have multiple versions representing different releases or deployments. Classifiers : Indicates if the project type is a library, framework, ...

Configuring Dependency-Track with Microsoft Entra ID (Azure AD) OIDC Authentication

In my previous posts, I introduced Dependency-Track and showed you how to deploy it on Azure Container Apps . Now that you have a working instance, it's time to secure it properly by integrating with your organization's identity provider. In this post, I'll walk you through configuring Dependency-Track to use OpenID Connect (OIDC) authentication with Microsoft Entra ID (formerly Azure Active Directory). This integration will allow your users to log in using their existing corporate credentials, enable single sign-on (SSO), and leverage conditional access policies for enhanced security. Why using OIDC with Microsoft Entra ID? Before diving into the configuration, let's understand the benefits of this integration: Centralized Identity Management : Users authenticate with their existing Microsoft Entra ID accounts, eliminating the need to manage separate credentials for Dependency-Track. Single Sign-On (SSO) : Users already logged into Microsoft services can acc...

Setting Up Dependency-Track on Azure Container Apps

In my previous post , I introduced Dependency-Track and explained why we chose it to manage our software supply chain security. Now it's time to get practical. In this post, I'll walk you through how we deployed Dependency-Track on Azure Container Apps, including our architecture decisions, configuration choices, and lessons learned along the way. Why Azure Container Apps? Before diving into the setup, let me explain why we chose Azure Container Apps for hosting Dependency-Track. We evaluated several deployment options including Azure Kubernetes Service (AKS), Azure Container Instances (ACI), and App Service, but Container Apps emerged as the best fit for our needs: Simplified Management : Container Apps abstracts away much of the complexity of Kubernetes while still providing container orchestration capabilities. We don't need to manage nodes, clusters, or complex networking configurations. Cost-Effective : With built-in autoscaling and the ability to scale to zero...