Blog
Notes on the .Net ecosystem, Angular, Software Architecture, Machine Learning and CyberSecurity
Series
Articles
Everything together: a vulnerable pull request from start to finish
Last article of the series. Every piece is ready, so this article opens a real pull request on the example repository and follows what happens, including the one vulnerability the detector let through. At the end, what the system does, what it does not do, and the road the series travelled.
Read moreCommenting on the pull request and holding the merge
Thirteenth article of the series. The analysis runs, but the result dies along with the virtual machine. This article publishes the verdict as a pull request comment and turns a confirmation into a check that stops the merge, with attention to a detail that decides whether the team reads the comment or ignores it.
Read moreBuilding the GitHub Action: the detector running on its own at every pull request
Twelfth article of the series. The tool works in the terminal, now it has to work without anyone typing anything. This article assembles the GitHub Action that installs the detector, finds out what changed in the pull request and runs the analysis, with special attention to not downloading half a gigabyte of model every time.
Read moreCalling Claude from C#: asking for a verdict the program can read
Eleventh article of the series. The classifier raises the suspicion, now somebody has to judge. This article shows how to call the Claude API from C#, how to force an answer in a fixed format instead of loose text, and what to write in the instructions so it is strict about false positives.
Read moreWhy 77.3% accuracy is not good enough to block a merge
Tenth article of the series. The classifier is ready and it works. This article explains why putting it alone in charge of blocking pull requests would be a mistake, which of the two kinds of error actually destroys a team's trust, and why the answer is not more training.
Read morePackaging the detector: from trained model to terminal command
Ninth article of the series. The model is trained, but it is still an object inside a project. This article turns it into a command anyone installs with one line, teaches it to read a pull request diff, and solves an annoying problem: how to distribute a 500 megabyte model without putting 500 megabytes in the repository.
Read moreThe exam that was worth nothing: the mistake that inflated the training result
Eighth article of the series. The first training run gave a perfectly believable score, and it was wrong. The number was right, the arithmetic was right, and the result was still a lie. This article shows where the defect was, why it is easy to commit without noticing, and what the real scores of the two models are.
Read moreTraining the classifier: where the examples come from and what exactly gets trained
Seventh article of the series. The fundamentals are done, construction begins. This article shows how to turn five vulnerability categories into hundreds of training examples, and how to train on top of CodeBERT with no graphics card and without putting half a gigabyte in the repository. At the end, the first result, which looked perfectly reasonable and was wrong.
Read moreInsecure Deserialization: when reading data is already running code
Sixth article of the series and the last on fundamentals. The four before it needed an interpreter on the other side. This one does not: the very act of rebuilding the object is what runs the attacker's code. This article explains how that is possible, which .NET APIs carry that behaviour, and what to use instead.
Read morePath Traversal: when the file name points outside
Fifth article of the series. Here the user's data becomes a command to nothing, and still hands over any file the process can read. This article explains why Path.Combine does not protect you (and in one specific case makes it worse), what the correct fix is, and a detail of that fix that is easy to leave out.
Read moreCommand Injection: when the user's data becomes a system command
Fourth article of the series. The two previous vulnerabilities handed the user's data to an interpreter: the database and the browser. This one hands it to the shell, the interpreter with the most power on the machine. This article explains why the fix here is not escaping characters, and why the real defense is using no shell at all.
Read moreCross-Site Scripting: when the user's data becomes code in someone else's browser
Third article of the series. In SQL Injection the user's data becomes a command inside the database. In Cross-Site Scripting it becomes code inside the browser of whoever opens the page, and the victim is not the server, it is the other user. This article explains the mechanism, why the right encoding depends on where the data lands, and the case where encoding solves nothing.
Read moreSQL Injection: when the user's data becomes a command
Second article of the series, and the first on fundamentals. The previous series introduced SQL Injection in passing, as the example that taught the model. Now it is the subject: how the flaw works inside, why it has survived since 1998, what actually fixes it, and the case where the well known fix does not apply.
Read moreIntroducing NeuralGuard: the vulnerable code detector inside the pipeline
First article of a new series. The detector we built with CodeBERT and TorchSharp works, but it lives alone inside a console app. This article introduces NeuralGuard, the project that takes that detector into the pull request, and explains why it does not work alone: the final word belongs to Claude.
Read moreRockRecommender: the feedback loop closed, from a like to the model in production
Sixth and last article in the series. An end-to-end walkthrough joining the five previous pieces, and an honest close about what was left out, on purpose.
Read moreRockRecommender: reloading the production model without restarting the Api
Fifth article in the series. The last piece sits on the Api side: noticing on its own that a new model was promoted, with no restart and no manual endpoint needed.
Read moreRockRecommender: automating retraining with a scheduled job
Fourth article in the series. Turning the pipeline into a service that runs on its own ran into a classic dependency injection trap: a long-lived service can't just inject a short-lived one.
Read moreRockRecommender: comparing models before promoting
Third article in the series. After picking the data source, the pipeline avoids the most obvious mistake of any automated retraining: replacing the production model just because the new one is newer, not because it's better.
Read moreRockRecommender: reading real feedback straight from Mongo
Second article in the series. The training pipeline gets its first new piece: a rule that decides on its own, by comparing volumes, when there's already enough real feedback to set the synthetic data aside.
Read moreRockRecommender: closing the loop between feedback and training
First article of a new series. RockRecommender has been collecting real like and dislike feedback since the API article, but the model is still trained only on synthetic data. This series closes that loop: the pipeline learns to decide on its own when real data is enough, compare the new model against the current one before switching, and reload everything without restarting anything.
Read morePutting it all together: RockPlayer playing, from like to the next song
Eighth and last article in the series. The screen where the song actually plays, with like, dislike, next and back completely independent from each other, and with no need for any state stored on the server to navigate through the history.
Read moreRockPlayer in Angular 22: structure and onboarding
Seventh article in the series. The first screen of RockPlayerWeb: the folder structure designed to grow without pain, and the onboarding where the person picks their favorite bands.
Read moreThe YouTube adapter: finding and playing the full song
Sixth article in the series. The first real implementation of IMusicProviderAdapter, using the YouTube Data API v3, and why it was the one chosen among the available streaming options.
Read moreBuilding the RockPlayer API, layer by layer
Fifth article in the series. With the theory settled, it's time to build the skeleton of RockPlayerApi: the ports, the orchestrator that brings together recommendation, cache and music provider, and the controller, still without any real provider implemented.
Read moreAngular 22 in practice: what really changed
Fourth article in the series. Before writing the first line of RockPlayerWeb, a practical summary of what Angular 22 really changes day to day: change detection, forms and HttpClient under the hood.
Read moreNo database: how RockPlayer avoids asking the music provider twice
Third article in the series. RockPlayer has no database, but it still needs to avoid asking the music provider the same thing twice. This article explains why Redis solves exactly this problem, without turning into a database in disguise.
Read moreAdapters: isolating YouTube from the business rules
Second article in the series. Before any real music provider exists in RockPlayer, this article explains the adapter pattern and why isolating YouTube (or any other provider) from the rest of the system prevents a change in the external API from breaking the business rules.
Read moreIntroducing RockPlayer: an app to listen to RockRecommender's recommendations
First article of a new series. RockRecommender knows which song to recommend, but it doesn't play anything. This article introduces RockPlayer, the project that takes that recommendation and actually puts it to play, and explains how the series will unfold.
Read moreBuilding the rock recommender API
Fifth and last article in the series. After training and evaluating the model, it's time to put everything inside a real API, with MongoDB keeping each person's history and simple endpoints to pick bands, ask for the next song and give a like or dislike. The full code is open on GitHub, in the RockRecommender repository.
Read moreEvaluating the model in practice
Fourth article in the rock recommender series. We trained a model in the previous article, but training is not the same as getting it right. Now we apply, with code, the metrics explained in article 2 (Precision@K, Recall@K and NDCG) on that model, to honestly answer: is it good?
Read moreBuilding the dataset and training the recommender with ML.NET
Third article in the rock recommender series. The theory from the first two articles (types of recommendation, cold start and the evaluation metrics) now becomes code. Let's build our catalog of bands and songs and train the first model, using ML.NET.
Read moreHow to evaluate a recommendation model
Second article in the rock recommender series. In the first one, we saw how a machine decides what to recommend. In this one, I answer the question that closes that article: how do we know these recommendations are actually good? Calmly, and with a numeric example of every metric.
Read moreRecommendation systems: how Spotify knows what you want to hear
This article opens a new series here on the blog, and its destination is very practical: building, from scratch, a rock music recommendation API, similar to what Spotify and Deezer do, with everything running on .NET. But the real subject of the series is not just building a recommender that works, it is understanding, in depth, how to know if it works well.
Read moreWhy I used micro-frontends
In my previous article I explained why I chose macroservices on the backend. That meant six separate Angular applications on the front, and every switch between areas reloaded the whole page. Here is how I joined those applications into a single experience, without giving up the isolation they had behind the scenes.
Read moreBuilding a transformer from scratch with TorchSharp
Last article of the series. For five chapters, the transformer was a powerful box we used closed. Now we open it: we are going to build one from scratch, piece by piece, in C#, and you will understand once and for all how the gear behind ChatGPT, CodeBERT and our detector works.
Read moreBuilding a vulnerable code detector with TorchSharp
Fifth article in the series, and the theory is over: we are going to use CodeBERT and specialize it in recognizing vulnerable code, with training and execution 100% in C#. No Python, no cloud, no sending your code to anyone. And a promise: one of the pieces will stay closed on purpose, because opening it is the subject of the grand finale.
Read moreCodeBERT and the AIs that read code
Fourth article in the series where we will teach a machine to find security flaws in code. Time to meet the tools: the transformers trained to read source code. Who is who in this family, what each one does differently, and which of them will be the brain of our detector.
Read moreWhat vulnerable code is and why it goes unnoticed
Third article in the series where we will teach a machine to find security flaws in code. But what flaws are those? In this article I explain what vulnerable code is, show the classic attacks (including the most famous of them all) and tell how these flaws are found today, and why so much still goes unnoticed.
Read moreFrom counting words to transformers
Second article in the series where we will teach a machine to find security flaws in code. But before that, a more basic question: how did machines learn to read? It's a 30-year story, full of clever ideas, and I tell it in the lightest way I can. Come without fear, there are no formulas or math here.
Read moreTeaching the machine to learn
This article opens a series where I bring together two subjects I love: machine learning and information security. The final destination is a vulnerable code detector running on .NET with transformers. But every journey has a first step, and ours is this one: what machine learning is, explained for those who have never trained a model.
Read moreNeither monolith nor microservices: why I chose macroservices
Every architecture debate turns into monolith versus microservices, as if there were only two paths. In the confidential project from my first article I took a third one that almost nobody talks about. Here is what macroservices are and why, for this product, they beat everything else.
Read moreWhy I'm not upgrading to Angular 22
Angular 22 has been out since June. I audited my Angular workspace's migration dependency by dependency and concluded it's not time yet. Here is why, tool by tool.
Read more