.NET Application Protection

Clomotech serves as a technology vendor partner to an enterprise software company, contributing engineering capacity to a commercial .NET application protection platform. The engagement spans mobile runtime security, build pipeline reliability, release correctness, and dependency health.

C# · .NET .NET MAUI Android RASP CI/CD · Jenkins NuGet Vendor Partner
Industry Dev Tools / .NET Security
Partner Enterprise Software Vendor
Product Application Protection Platform
Engagement Vendor Partner
Stack C# · .NET · Assembly Rewriting · NuGet · CI/CD

Engineering Inside a Commercial Product

The platform operates at the intersection of build tooling and runtime security. It intercepts .NET assemblies during the build pipeline — rewriting them to obfuscate logic, encrypt strings, and inject runtime self-protection checks — then ships binary output that must run correctly in production across every customer's runtime environment and OS target.

Clomotech's role as a vendor partner is not client-to-builder. It is integration into the vendor's engineering team — working inside an established commercial codebase with existing customer contracts, existing regression baselines, and a zero-tolerance policy for silent breakage. Every change must be validated against real platform conditions: CI build agents, physical mobile devices, and release configurations that don't exist on a local development machine.

Contributions span four distinct areas of the product, each presenting its own platform-specific engineering challenge.

RASP checks (binary tamper verification, rooted device detection) unreliable on MAUI Android without platform-specific tuning
Intermittent AccessViolationException and assembly access conflicts in high-concurrency CI pipelines
Missing deps.json in obfuscated output causing runtime failures — with a second failure mode specific to Jenkins release builds
Outdated NuGet dependencies with CVE exposure and API drift risk across the product's dependency graph

"Working inside a commercial product's codebase is a different discipline. You're not building from scratch — you're maintaining correctness across existing customer environments and platform versions while shipping new capability."

— Engineering Principle
4 Engineering Contributions
MAUI Android Platform
CI Pipeline Stability

Four Areas of Engineering Work

Each contribution addresses a distinct production challenge in the platform — from mobile security to build infrastructure.

01

Mobile Platform Security

The platform's runtime self-protection (RASP) features — binary tamper verification and rooted device detection — required platform-specific integration work to function reliably on .NET MAUI Android. Updated injection paths and tuned runtime validation to eliminate false positives on real devices.

02

Build System Reliability

Customers hit intermittent AccessViolationException and transient assembly access failures in high-concurrency CI environments. Introduced bounded retry with controlled backoff across the platform's pipeline and its assembly manipulation layer, targeting only retry-safe failure categories.

03

Release Pipeline Correctness

Obfuscated output was missing the required deps.json file, causing runtime assembly resolution failures. A second failure mode appeared only in Jenkins release mode due to unstable System.Text.Json serialization under obfuscation. Both were resolved and validated in the actual failing environment.

04

Dependency Modernization

Executed a security-first NuGet dependency upgrade program — vulnerability-checking packages before upgrading, evaluating alternatives where risk existed, resolving breaking changes in source, and validating functional parity through regression testing across critical flows.

Build-Time Protection Pipeline

The platform runs as a post-build transform step inside the CI/CD pipeline — intercepting .NET assemblies, rewriting them, and producing protected output. Each contribution maps to a specific stage.

Protection Platform — Build Pipeline & Runtime Architecture

.NET Build Output Source Assemblies NuGet Packages Build Metadata Protection Platform Post-build assembly transform · runs inside CI/CD build pipeline Assembly Reader load input assemblies into memory + retry guards · C02 Obfuscation Engine rewrite assembly logic Identifier Renaming String Encryption Control Flow preserves runtime behavior · rewrites structure only RASP Injector embed runtime self-protection checks into assembly Tamper Verification Root Detection Debug Detection MAUI Android integration & tuning · Contribution 01 deps.json Handler XML generation · C03 Assembly Writer write protected assemblies to output path + retry guards · C02 NuGet dependency graph security & upgrade program applied across all stages · Contribution 04 Protected Output Obfuscated Assemblies deps.json included RASP checks embedded deploy MAUI Android Runtime App startup → embedded RASP checks execute (tamper verification · root detection · debug detection) checks pass → protected business logic executes normally

RASP on MAUI Android

The platform's runtime application self-protection (RASP) features — binary tamper verification and rooted device detection — are injected into assemblies at build time and executed at runtime to verify the app's integrity and environment. On .NET MAUI Android, the runtime behaves differently from older mobile stacks: APK packaging, signing mechanics, and app startup differ in ways that affect when and how protection checks can reliably fire.

The challenge was making both checks dependable across real device and emulator conditions without generating false positives that block legitimate users. An overly sensitive tamper check would trigger on unsigned debug builds or test distribution; an overly broad root detection check would flag standard developer devices.

The solution involved updating the integration paths through which checks are injected into MAUI Android assemblies, and tuning the validation flow so checks execute at reliable runtime entry points. The fix was iterated against real device conditions — not just emulators — to catch platform-specific timing and execution differences before shipping.

Tamper Verification

Verifies that binaries were not modified after signing and build. Updated injection paths account for MAUI Android's APK structure and signing pipeline, ensuring the check evaluates the correct binary boundaries.

Root Detection

Detects rooted Android environments where OS-level security assumptions are weaker. Tuned detection sensitivity so legitimate devices — including developer machines where root indicators are present for valid reasons — do not trigger false positives in production distributions.

Why MAUI Android differs

MAUI Android targets the Android runtime through a different abstraction layer than Xamarin.Android. APK assembly layout, startup sequencing, and signing validation differ — meaning injection points that worked for earlier mobile stacks needed platform-specific updates to function correctly in MAUI output binaries.

Balance: security depth vs. usability

RASP checks that are too aggressive break legitimate users. Checks that are too lenient are trivially bypassed. The tuning work balanced detection depth with production usability — a trade-off that can only be verified through testing on real devices under real conditions, not on a developer workstation.

Result

Binary tamper verification and root detection are stable and practical for MAUI Android release pipelines. Security posture is improved without disrupting normal app usage for legitimate users.

Concurrency-Safe Retry Logic

The platform reads and rewrites assemblies during build. In high-concurrency CI environments, assembly files can be temporarily locked by parallel tools — causing intermittent failures that are difficult to reproduce and hard to diagnose.

The Problem

Customers in shared and parallel CI environments hit intermittent build failures with AccessViolationException and transient assembly access conflicts. These failures were non-deterministic — they depended on the timing of concurrent processes (antivirus scanners, build indexers, or parallel build steps locking the same assembly files) and could not be consistently reproduced in isolation.

Because the root cause was environmental concurrency rather than incorrect logic, the failures were easy to dismiss as infrastructure noise — but they were causing real build breaks in customer pipelines.

01
Platform source pipeline

Added retry guards around assembly open, read, and write access points. Improved handling of transient lock and contention scenarios at the obfuscation processing stage.

02
Assembly manipulation layer

Extended retry-aware handling to the assembly manipulation path — a second access layer independently susceptible to transient lock contention during read and write operations.

03
Retry safety boundaries

Retry applies only to failure categories known to be transient and retry-safe. Non-recoverable errors — corrupted assemblies, permission violations, missing files — preserve fail-fast behavior and are not retried, ensuring errors that signal real problems still surface immediately.

Bounded backoff, not open loops

The retry implementation uses bounded retry counts with controlled backoff intervals. This prevents a stuck build from waiting indefinitely while still giving transient locks time to clear between attempts.

Known limitation

Retry attempts originating within external dependency internals may not always surface in the platform's build logs — logging is bounded to what the platform can observe within its own call stack.

Result

Intermittent concurrency-related build failures were substantially reduced. CI pipelines running parallel build agents, antivirus scanning, and build indexing in parallel now produce more deterministic, stable outcomes.

deps.json and the Jenkins Release Gap

Modern .NET applications rely on a *.deps.json file for runtime assembly and dependency resolution. When the platform's obfuscated output omitted this file, apps failed at startup — the runtime could not locate and load the required assemblies.

The first fix — explicit handling to ensure deps.json is always present in final obfuscated artifacts — resolved the runtime failure. But a second, independent failure mode remained: Jenkins release builds were failing even after the file was included. Local builds and debug configurations passed; the failure was specific to the CI release pipeline.

Investigation revealed that the metadata persistence strategy used to generate and store deps metadata — initially implemented with System.Text.Json — was not stable under obfuscation in release mode. The obfuscation process itself was interfering with the serialization path in a way that only manifested under release-configuration CI conditions.

Initial Approach
System.Text.Json

Chosen for modern, lightweight JSON serialization of deps metadata. Passed local and debug validation — failed in Jenkins release builds due to obfuscation-induced serialization instability in release-mode output.

Final Approach
XML Document Generation

Reworked metadata persistence to use XML document generation and storage. More verbose than JSON but proved deterministic across all build configurations — local, debug, and Jenkins release — under obfuscation.

Why validate in Jenkins release mode specifically

The failure only manifested in the actual failing environment — Jenkins release configuration with obfuscation applied. Validating only on local debug builds was insufficient. The fix was confirmed specifically against the CI release pipeline conditions before being accepted as resolved.

The obfuscation/serialization interaction

Obfuscation renames types and methods in assemblies. When a serialization library uses reflection to discover type names or property paths at runtime, renamed identifiers can silently produce incorrect or empty output — a failure mode that is invisible in debug builds where obfuscation may not apply.

Result

Runtime failures due to missing deps.json were eliminated. Jenkins release obfuscation builds are stable. CI artifact quality improved — the obfuscated output reliably includes all dependencies required for runtime startup.

Security-First NuGet Upgrades

Outdated dependencies accumulate CVE exposure, compatibility drift, and maintenance burden. A staged, security-validated upgrade program was executed across the platform's NuGet dependency graph.

1
Identify outdated packages

Audited the full NuGet dependency graph — direct and transitive — to identify packages no longer at a current stable version.

2
Vulnerability assessment before upgrade

Vulnerability checks were performed on each candidate package. If known CVEs existed, alternative packages were evaluated. Security findings requiring escalation were escalated before proceeding.

3
Staged upgrades, not bulk replacement

Packages were upgraded in controlled stages rather than all at once. This limits blast radius — a breaking change in one package is isolated from other concurrent upgrades, making root-cause identification tractable.

4
Source-level compatibility fixes

Packages that introduced API changes were handled with source-level fixes in the platform's codebase — absorbing the package-level breaking change rather than pinning to an older version and deferring the problem.

5
Regression testing across critical flows

Full regression testing validated functional parity after each upgrade stage. Version decisions, compatibility notes, and breaking-change handling strategy were documented throughout.

Vulnerability exposure was reduced — known CVEs in the dependency graph were addressed before they could become a product-level risk
Compatibility with modern .NET runtimes and tooling was restored — reducing future maintenance burden from compounding drift
Product stability was maintained through regression-backed rollout — functional behavior verified at each stage before the next package was addressed

The Platform Engineering Stack

Core Platform
C# .NET Assembly Rewriting
Mobile Target
.NET MAUI Android RASP
Build & CI
Jenkins CI/CD Pipelines MSBuild
Package Management
NuGet Dependency Auditing CVE Analysis
Serialization
XML Document API deps.json .NET Runtime
Security Features
Tamper Verification Root Detection Debug Detection String Encryption Identifier Renaming

Need engineering capacity for a commercial product?

Whether it's platform-specific security features, build pipeline stability, or dependency health — we've shipped these in production as a trusted engineering partner.