
Improve your automated tests
How to test software using Gherkin? The tests are built using phrases that even a non-technical person can easily understand.
Go to content|Go to the main menu|Go to search
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.
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).
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.
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:
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.
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.
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:

How to test software using Gherkin? The tests are built using phrases that even a non-technical person can easily understand.
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.
