Go to content|Go to the main menu|Go to search

edhouse-CookieGdpr-Policy-s
0073657
2
/en/gdpr/
187650B6A

Back to Blog

CybersecurityLessons learned

How a .NET migration revealed a security debt - and why you should care

25.8.2026Milan Jakubec

The customer wanted to migrate software from an older framework to the more modern .NET 8 and ensure compliance with cybersecurity standards. However, legislation and undisclosed incidents turned what was supposed to be a routine technology upgrade into a company-wide transformation. Using a real-world case study, we’ll demonstrate why every development team should start addressing its security debt before strict penalties under new regulations force them to do so.

From a technical standpoint, this was a routine project for us. A client approached us explaining that they operate a distributed system for managing physical infrastructure. The system consisted of a backend built on an older .NET framework, which included several dozen independently running Windows services, and a frontend application.

We were asked to take this backend and migrate it to the newer .NET 8. Part of this migration request also involved reviewing the project’s existing security considering new legislation.

The security guy’s guide to regulations

Lately, many security and legal experts have been warning us about regulations. What regulations are we talking about? The first is the Czech New cybersecurity act, which took effect in November 2025.

It transposes the EU-wide NIS2 Directive, which tightens security requirements for software supplied and information services operated. In short, this transposition requires the implementation of a cybersecurity management system and, more generally, risk and incident management within the company.

From a managerial perspective, this means training employees in cybersecurity and ensuring that organizational leadership takes responsibility for addressing security risks. From a technical standpoint, this involves, among other things, managing access, encrypting data, implementing monitoring, and, finally, ensuring the security of the software development process, the so-called SSDLC (secure software development lifecycle).

In simple terms, a secure development lifecycle is a set of procedural and technical measures that ensure the security of the delivered software is addressed from design through to operation (the “shift-left” approach, i.e., moving security to the beginning) rather than at the end (the “bolted-on” approach, i.e., addressing security only as an afterthought).

For example, the SSDLC includes threat modeling along with the definition of security requirements and architecture during the design (or refactoring/migration) of software, adherence to secure development principles, SAST and DAST (static/dynamic application security testing), scanning dependencies and vulnerabilities in libraries, automation of security checks in the CI/CD pipeline, and, where appropriate, penetration testing.

The second major regulation is the Cyber Resilience Act (CRA), which focuses primarily on the security of products (digital or containing digital components) entering the market. Unlike NIS2, which explicitly targets service providers and their ability to manage cyber risks, the CRA imposes obligations directly on software and device manufacturers.

They must ensure that their products are secure at the time of market introduction and remain secure throughout their entire lifecycle, including the provision of security updates and the resolution of vulnerabilities. This regulation will take full effect in December 2027; from that point onward, full compliance with its requirements will be mandatory. However, the obligation to report actively exploited vulnerabilities and incidents takes effect slightly earlier, in September 2026.

Both regulations partially overlap, particularly in the areas of software development security and vulnerability management. While NIS2 (and its Czech transposition) requires organizations to have processes in place for secure development and risk management within their operations, the CRA specifies these requirements from the perspective of the product itself.

For example, both NIS2 and CRA require supply chain management; from the CRA’s perspective, this is a mandatory requirement that means software must be accompanied by an SBOM (software bill of materials), which contains information about which libraries the software uses. In practice, this means that organizations developing software must meet both the process requirements at the management level (NIS2) and the specific requirements regarding the characteristics and security of the products they deliver (CRA).

What the eye doesn't see, the developer doesn't grieve over (yet)

When we began examining the environment in which the customer was developing their software, we discovered that the security situation was worse than it might have seemed at first glance. The CI/CD pipeline was fragmented between two independent systems -Azure DevOps Server (on-prem) and Jenkins - without a unified strategy, common standards, or any central control.

From a technical standpoint, this setup wasn’t even necessary; it remained in place for “historical” reasons. Worse still, neither environment included any form of security checks, whether in the form of static analysis or even dependency analysis. Visibility into security vulnerabilities in the code and libraries was literally zero, and the client’s team simply could not know what security issues existed in their codebase of hundreds of thousands of lines of code.

As if that weren’t enough, hardcoded credentials were discovered in the Jenkins configuration. All of them in plain text, readable by anyone with access to the build server. This isn’t just technical debt; it’s a security incident that could have existed for months without being noticed, since no one addressed it.

Why didn’t this bother anyone, you ask? Because the system was working. The customer’s team consists of skilled developers, the system runs reliably, customers are paying, and the infrastructure is up and running. The problem is that security isn’t about whether the system works right now.

It’s about whether it will still work when someone is actively trying to make it fail. And for that, you need visibility, that is, the ability to know what’s happening not only inside the software, but also within the development process and environment. The customer had none of that.

Three ways out of a security dead end

Based on our analysis, we proposed a secure pipeline concept to the client that covers the entire development cycle, from commit to production. Since it was not possible to secure the pipeline without making changes, we presented the client with three solution options:

  • Option A: A complete migration to GitHub using GitHub Advanced Security (native CodeQL tools for SAST, Dependabot for SCA, and secret scanning with push protection). From an infrastructure perspective, this would still be a partially hybrid solution; the customer would use self-hosted GitHub runners and manage them independently based on their preferences.
  • Option B: Removal of Jenkins, complete migration to the existing Azure DevOps Server, and integration of external tools (SonarQube Enterprise for SAST, OWASP Dependency-Track for SCA, Gitleaks for secrets).
  • Option C: Migration to Azure DevOps Services in the cloud with GitHub Advanced Security for Azure DevOps enabled. Retain your familiar ecosystem while gaining access to a wide range of security tools.

Each option had its advantages and limitations. In terms of the depth of security analysis, deployment speed, and associated overhead, GitHub came out on top. In terms of minimal disruption to current operations and preserving data on-prems, the existing Azure DevOps Server with an extension was the best choice. Option C, on the other hand, was advantageous in terms of migration speed, which is enabled natively by existing tools.

Among the disadvantages, I’d like to highlight one specific issue that ruled out Option B: the license for SonarQube Enterprise for a codebase of the customer’s size would, on its own, cost more than the entire cloud solution. So, as always and everywhere, it’s all about compromises.

How code migration led to a strategic business decision

During the security analysis of what was originally a migration project, several findings emerged that went beyond the original scope of the assignment. Firstly, Azure DevOps Server is scheduled to reach the end of life in 2033. This means that, from a security perspective, migration to another platform was inevitable in the future anyway - the longer it is postponed, the greater the technical and security debt will become, and the greater the risk of a “time-pressured” migration right before the deadline.

Secondly, our economic analysis revealed that the cloud option is the most cost-effective for the customer, both in the first year and in ongoing operating costs, even when scaled for the entire company. Third, without implementing a secure pipeline, the customer has no chance of complying with CRA requirements or the new cybersecurity law, and penalties for non-compliance run into the millions of crowns.

As a result, what started as a simple request — “Migrate our .NET application and secure the pipeline for a single project” — evolved into a company-wide strategic project. The client’s management began addressing the question of whether and how to migrate the entire DevOps platform from on-premises infrastructure to the cloud - not just for this one system, but for the entire organization. What began as a technical framework migration revealed systemic security debt that required a strategic decision at the executive level.

What should you take away from this?

This customer’s story is not unique. In the field, we encounter similar situations time and again – systems that have been running smoothly for years but hide security risks beneath the surface that no one is aware of. Here are a few key takeaways:

  1. Security isn't something you address later. It's addressed from the very first commit. Every push should go through secret scanning, every build should undergo static analysis, and every dependency should be audited. This isn't a luxury; it's a legal requirement that will be enforced.
  2. Regulations are coming, and they will be enforced. The new cybersecurity law is already in effect in the Czech Republic. The EU-wide CRA, with fines of up to 15 million EUR or 2.5% of global revenue, will take full effect in December 2027, and the first mandatory requirements will take effect this fall. Time to prepare is running out.
  3. “It works” does not mean “it's secure.” A system can work perfectly well and still have leaked credentials in its Git history, outdated libraries with critical vulnerabilities, or APIs without proper input validation. Without the right tools and processes, you simply won't know.
  4. Migration or modernization is the ideal time to implement a secure development process. Whether you’re switching frameworks, transitioning to a new authentication system, or implementing containerization, this is exactly the moment when it pays to build a secure development process from the ground up. A new tech stack typically offers significantly better support for modern security tools.
  5. To conclude, security analysis often uncovers systemic issues that go beyond the original scope of the project. In this case, it served as the catalyst for a company-wide infrastructure transformation. That’s another reason why it’s worth taking a close look at the security of your development process before a regulator forces you to do so.

Share article

Author

Milan Jakubec

Milan JakubecA former .NET developer who switched to application security and DevSecOps to help build more secure software from the ground up.

Edhouse newsletter

Get the latest updates from the world of Edhouse – news, events, and current software and hardware trends.

By signing up, you agree to our Privacy Policy.

Thank you for your interest in subscribing to our newsletter! To complete your registration you need to confirm your subscription. We have just sent you a confirmation link to the email address you provided. Please click on this link to complete your registration. If you do not find the email, please check your spam or "Promotions" folder.