❌

Reading view

Node.js security starts before CI

In many teams, dependency security still happens after the most important trust decision has already been made. A package is added, the lockfile changes, the feature moves forward, and only later does the pipeline ask whether the application should have trusted that code in the first place.

That workflow made sense when dependency security was mostly viewed as a compliance check. Run a scanner. Produce a report. Fail the build if the risk crosses a threshold. Let someone decide what to do next.

But the modern Node.js ecosystem has changed. The risk no longer begins in CI. It begins earlier, at the moment a developer decides to trust a package.

That is why the next phase of Node.js security cannot be limited to better pipeline enforcement. It has to move closer to the developer workflow, before dependencies become part of the application, before a pull request becomes someone else’s problem, and before a build log becomes the first moment anyone realizes that something important has changed.

Every install is a trust decision

The npm ecosystem is built on trust at an enormous scale. Every install is a trust decision. Every transitive dependency extends that decision to maintainers, packages, scripts, release pipelines, and infrastructure the application team may never inspect directly. This model gave JavaScript its incredible velocity. It also created one of its deepest security weaknesses.

Recent npm supply chain incidents show why this matters. In March 2026, malicious Axios versions were published to npm through a compromised maintainer account. Microsoft later described how those packages attempted to retrieve a second-stage payload during installation. In May 2026, TanStack published a postmortem explaining that 84 malicious versions across 42 npm packages were published through a legitimate release pipeline after an attacker abused GitHub Actions behavior and runner trust boundaries. Security researchers also reported broader Mini Shai-Hulud activity across the npm ecosystem in May, including hundreds of malicious package versions published in a short period.

Not every one of these incidents is a traditional CVE. Some are malicious package compromises. Some involve CI/CD credential theft. Some involve maintainer or pipeline compromise. But they all point to the same larger issue: dependency risk is now part of everyday software engineering, not something that can be pushed entirely to a downstream security process.

The problem is not the scanner. It is the handoff.

Ubiquitous dependency risk changes what developers need from security tooling.

The problem is not that teams lack scanners. Many organizations already run security checks in CI. The problem is that the output of those checks often arrives too late and speaks the wrong language for the person expected to act on it.

A pull request fails. A long vulnerability report appears. The report may be technically accurate. It may contain the right advisory IDs, affected versions, dependency paths, severity labels, and references. But the developer still has to comb through the output and reconstruct the actual engineering decision from the evidence provided.

That reconstruction is rarely simple. The developer has to understand which package introduced the issue, whether the vulnerable dependency is direct or transitive, whether the fix is actually within the application team’s control, and whether the recommended version is safe to adopt. They also have to determine whether the dependency is used in production or only during development, whether the update might break the application, and whether the fix belongs in the current pull request or requires separate engineering work.

That uncertainty is where security work often slows. The scanner has detected risk, but the developer has not been given a clear path from detection to decision.

Security needs to move closer to engineering judgment

This is not a criticism of scanning. Scanning is necessary. CI enforcement is necessary. Centralized security platforms are necessary. But they are not sufficient, because they often operate after the trust decision has already been made.

The real architectural question is this: where should dependency security live in the software development life cycle?

If it lives only in CI, it becomes an interruption. If it lives only in dashboards, it becomes someone else’s queue. If it lives only in periodic audits, it becomes a backlog. But if it lives at the moment a dependency is introduced, upgraded, or reviewed, it becomes part of engineering judgment.

That shift matters because modern JavaScript development is becoming faster than human review can comfortably handle. Developers no longer add dependencies only by reading documentation and choosing libraries manually. AI coding assistants can suggest packages, generate install commands, modify package files, and rewrite code around third-party APIs. Agentic development workflows can make dependency changes as part of broader automated refactors.

AI makes the trust boundary harder to see

That acceleration is useful. It also changes the risk model.

When a human developer adds one package, the team can review the decision. When a coding agent modifies several dependencies as part of a larger task, the trust boundary becomes harder to see. The package file changes, the lockfile changes, the application still runs, and the pull request may look like a normal feature update. But the real security question may be hidden inside the dependency graph.

This is where Node.js teams need a different mental model.

Dependency adoption should not be treated as a small implementation detail. It should be treated as an architectural decision with security consequences. A new package is not just code reuse. It is a new trust relationship.

That does not mean developers should stop using packages. The npm ecosystem exists because reuse works. Most teams cannot and should not build everything themselves. But convenience should not erase visibility. If a dependency becomes part of the application, the team should understand what was added, what changed in the lockfile, what risk comes with it, and what action is available if something is wrong.

Developers need confidence, not just reports

The same applies to remediation. Developers do not want a wall of vulnerability text. They want confidence. They want to know what action reduces risk, what version should be targeted, whether the change is safe, and whether the fix is actually under their control. A vulnerability report that leaves the developer uncertain may satisfy a process requirement, but it does not necessarily improve the speed or quality of remediation.

That is the gap many teams feel today. Security tools are often very good at saying, “There is a problem.” They are less consistent at helping the developer answer, “What should I do next?”

This is the broader problem I have been exploring through CVE Lite CLI, now an OWASP project. The point is not that one command-line tool solves Node.js security. It does not. The larger idea is that dependency security has to move closer to the developer’s moment of decision. A useful developer-side security workflow should not merely report that risk exists. It should help the engineer understand whether the issue is in their control, what change is available, and whether the fix actually reduces risk.

The future is decision support, not just detection

That distinction is important. The future of Node.js security is not just more detection. It is better decision support.

Security teams still need policy. Enterprises still need dashboards. CI still needs gates. But developers need something more immediate: a way to reason about dependency risk while the code is still fresh in their mind. That is where the ecosystem has to evolve.

We already accept that testing belongs close to development. We accept that linting belongs close to development. We accept that formatting, type checking, and build validation belong close to development. Dependency security should follow the same path. It should not be treated as a mysterious report that appears at the end of the process. It should become part of the normal rhythm of engineering work.

Before adding a package, developers should understand what trust relationship is being introduced. Before accepting an AI-generated dependency change, they should inspect what entered the graph. Before merging a pull request, teams should understand whether a vulnerability is direct, transitive, fixable, or blocked by another package. And before treating a CI failure as noise, organizations should ask whether the workflow is giving developers enough information to act confidently.

Node.js security will be won, or lost, before CI runs

The Node.js ecosystem will not become safer by slowing down all development. That is unrealistic. It will become safer when security work is placed where developers can actually use it.

The next generation of Node.js security will be won or lost before CI runs.

It will be won when dependency decisions are still small enough to understand, fresh enough to review, and close enough to the developer for action to feel natural.

That is the shift teams need to make now. Not from insecure to secure in one step, but from late detection to earlier judgment. From vulnerability reports to engineering decisions. From trusting packages by habit to understanding trust as part of software design.

  •  

Microsoft releases .NET 11 Preview 6

Preview 6 of Microsoft’s .NET 11 software development platform is now available, with improvements across the runtime, libraries, frameworks, and C# and F# programming languages.

Announced July 14, .NET 11 Preview 6 can be downloaded from dotnet.microsoft.com. The full, general production release is expected in November. The first preview was unveiled February 10.

Runtime-async, the .NET runtime’s built-in implementation of async/await, keeps getting faster in Preview 6, building on the suspension improvements from Preview 5. Async continuations can now opt out of ExecutionContext capture and restore. And the JIT now compiles a dedicated runtime-async version of a synchronous, task-returning method rather than delegating to it through a thunk. The JIT turns the method’s tail calls into runtime-async calls and awaits the task that would otherwise have been returned, so the async path no longer pays for an extra layer of indirection, Microsoft said.

In library improvements, System.Text.Json can now serialize and deserialize the new C# union types. The serializer recognizes a union through the new JsonTypeInfoKind.Union contract type, reads and writes the active case, and supports the reflection-based serializer and the source generator. The new JsonUnionAttribute, JsonUnionCaseInfo, and type-classifier APIs enable customization of how cases are discovered and named.

In C# improvements, extension members now include indexers, so developers can add this[...] access to a type from an extension block. This rounds out the extension members feature introduced in .NET 10, which already supported extension methods and properties. An extension indexer is declared like an instance indexer inside an extension block.

Other highlights in .NET 11 Preview 6:

  • Math.BigMul(long, long, out long) is now significantly faster on x64. The JIT generates a single MUL r/m64 instruction when both operands are 64-bit values and the caller requests the high half of the result. Previously the JIT emitted a helper call. The change eliminates the call overhead and makes code that multiplies large numbers tighter.
  • Minimal API validation in ASP.NET Core now supports asynchronous validators end-to-end.
  • For F#, the compiler emits better sequence points for several common debugging scenarios. Breakpoints and stepping are improved for call arguments that need stack-empty debug points, for expressions and comprehensions, simple literal bindings, and if or match conditions.
  • For .NET MAUI, .NET 11 Preview 6 advances the cross-platform CollectionView and Shell architecture, removes the legacy Xamarin.Forms compatibility package, and brings the Apple workloads onto stable Xcode 26.6.
  • Also for .NET MAUI, HybridWebView JavaScript interop is reworked to use a source generator instead of reflection, so it no longer produces trim or AOT (ahead of time) compiler warnings and works correctly in fully trimmed and Native AOT apps.
  • Projects that use Microsoft.TypeScript.MSBuild in Razor Class Libraries now properly integrate TypeScript compilation outputs with ASP.NET Core Static Web Assets.

  •  

Ship apps faster with GitHub, Vercel, and Firestore

These days, application developers can take their pick from a vast menu of architectural solutions. We can choose from the well-understood to the experimental, and from blended solutions in between. Several powerful middle-ground technologies that emerged during the cloud revolution have really come of age. Here we’ll take a look at putting together three of the most impressive: GitHub, Vercel, and Firestore.

Each of these is an important tool in its own right that can be used to attack specific problems. In combination, they not only meet the needs of several important application scenarios, but they have a superpower—the ability to dramatically shorten the distance between development and deployment.

There is nothing quite as gratifying as putting your hands on just the right mix of tools for a given need.

A ‘no-ops’ stack built for speed

If your primary goal is sheer development velocity, you would be hard-pressed to top this architecture. This “no-ops” stack collapses the distance between your local IDE and a globally distributed production environment. You are essentially trading the overhead of managing VMs and load balancers for the sheer speed of committing code and watching it deploy automatically.

While each component is highly flexible, adopting them requires a specific, event-driven mindset. There are a few finicky bits to manage, mostly around routing environment variables securely and designing around stateless back-end functions. But the constraints are obvious and well-documented.

Before we look more closely, let’s quickly identify the kinds of apps that are a perfect fit here, along with those that are workable and those that really merit a different approach.

  • The sweet spot (deploy and go): AI-mediated applications, asynchronous game back ends, and real-time collaborative B2B dashboards. This architecture perfectly absorbs the unpredictable latency of LLM APIs and instantly syncs state across multiple clients without requiring you to build custom WebSocket infrastructure.
  • The middle ground (workable, with trade-offs): Headless e-commerce, moderate IoT telemetry, and apps requiring scheduled batch processing. You will encounter friction if your catalog relies on deeply relational SQL constraints, or if your background reporting jobs take longer than a few minutes and hit serverless execution limits.
  • The danger zone (look elsewhere): High-frequency trading, fast-paced action multiplayer games, heavy data ETL pipelines, and core financial ledgers. Serverless architectures cannot natively hold open the persistent WebSockets required for twitch-reflex data, and heavy compute tasks will abruptly time out.

We should mention that these categories are not mutually exclusive. Many enterprise applications, such as a full-scale e-commerce platform, straddle these lines. You might use Vercel and Firestore to build a lightning-fast, reactive storefront that handles ephemeral user state like shopping carts, while simultaneously “stitching in” a managed SQL database like Supabase or PlanetScale. This hybrid approach allows you to maintain the relational integrity required for back-office inventory and financial ledgers and pair it with the front-end velocity this stack provides.

GitHub: the bedrock

I don’t need to introduce you to GitHub. It is a central element of the development landscape. I still remember CVS and SVN with a certain nostalgia, but the enhancements of Git speak for themselves. When combined with the orchestration powers of GitHub, it is no wonder that virtually the whole industry has adopted this type of platform.

Git plus GitHub gives you an enormous amount of power already, in terms of how you can organize and automate your projects. But there is a next-level experience in combining GitHub and Vercel. For JavaScript-based projects, you can take simple GitHub pushes and turn them into instantly deployed clients and serverless functions. It is one of the cleanest and least fiddly ways to move from raw code on your local machine to a globally deployed, full-stack architecture.

Vercel: the nexus

Vercel is more than just a deployment host. It is a control plane that ties this high-velocity, no-ops architecture together. Alongside GitHub and Firestore, Vercel’s deeper strength is its ability to act as an orchestration layer between your reactive front end and external stateful services.

Vercel has a great amount of facility in fine-tuning what branches go to what environment and helpful features like instant rollback. You can just log into Vercel’s dashboard for your project and see the history of deployments and any errors and logs. It’s a simple menu choice to roll back to a historical version or compare one version against another.

When you “stitch in” third-party services (such as a managed SQL database like Supabase or a payment processor like Stripe), Vercel’s serverless functions become the lightweight interface, and Vercel’s the adapters handle the communication. You offload the integration logic (the service layer) to Vercel’s global Edge Network, keeping your UI and back end clean, responsive, and decoupled. 

In short, Vercel allows you to get the speed of the “no-ops” development life cycle without sacrificing the complex transactional integrity required for some applications like enterprise inventory systems.

Firestore: the datastore

Firestore is an extremely lightweight, NoSQL, cloud datastore. It has a great deal of add-on power, but its core value proposition is that it accepts virtually any data you stuff into it and it provides event-driven subscriptions to data changes.

These two capabilities together make Firestore about as straightforward a solution to a managed back end as you can imagine. You subscribe to collections or even fields and then you simply stick “unstructured” data (read: JSON with variable fields) in and the client waits for the changes it is interested in.

This is so streamlined that one can just point the browser (or native mobile app) directly at Firestore and listen for events. Which immediately raises the question of identity, for auth and for data visibility, but hold on—Firestore’s third superpower is that it has an authentication module that actually works. What I mean is, it is actually pretty simple and yet confidently secures your app.

Sometimes auth solutions seem either too simple (and yet opaque) or too mired in the nitty gritty. Firestore auth will let you do some basic configuration and start using a reasonable auth almost immediately. 

Not to belabor the point, but having a realistic and attainable auth solution elevates your stack to a production grade—one that can handle many real-world applications. Firestore auth plays nicely with other important APIs, like Stripe. Typically, auth is a major feature that feels like off-roading in a Honda Civic, but Firestore’s approach to auth, added to this particular stack, feels like a normal speed bump. It’s just another component you plug in, rather than a tentacled alien you weave into the your code.

The limits of the velocity stack

This architecture combines components that are optimized for flexibility. That same character also introduces distinct limitations. Understanding these is essential before committing production workloads.

The serverless life cycle

Serverless functions are spun up to handle requests. They close out soon afterward and lose any state. For that reason, they cannot natively hold open persistent WebSockets. If your system requires continuous, sub-millisecond, bidirectional streams—like a real-time multiplayer action game or a high-frequency trading dashboard—pure serverless will fight you all the way. You are forced to introduce a third-party managed WebSocket service to route messages back to your stateless endpoints via HTTP webhooks.

The execution time ceiling

Vercel (like all serverless platforms) enforces strict timeouts on operations. While enterprise tiers might grant you up to 15 minutes, standard functions often time out after 10 to 60 seconds. Long-running tasks like video transcoding, database scripts, or orchestrating multi-step AI agent workflows, which might take 20 minutes to resolve, will run up against these limits. Heavy-lifting tasks must be offloaded to a dedicated, long-running service like Google Cloud Run, or broken into smaller, asynchronous chunks via message queues.

The cold start reality

While the industry has made massive strides in minimizing initialization times—particularly with lightweight edge networks—traditional Node.js-based serverless functions still experience cold starts. If a function has not been invoked recently, or if traffic spikes require a new instance to spin up concurrently, the first request will take a noticeable latency hit as the container provisions and the code loads.

API instead of RAM

In a traditional server environment, you can store transient data in global RAM, allowing subsequent requests to access shared context instantly. In the serverless model, every request might hit a fresh container. Therefore, all shared context must be externalized. Although Firestore serves brilliantly as the state manager, relying on a database for high-frequency, sub-millisecond, ephemeral caching introduces network latency and per-operation costs. That said, using a shared RAM state on a server is non-trivial also, unless you are using a single app server and VM (because high-availability or fail-over requirements will lessen the RAM win on a traditional server).

Tuning for velocity and control

Every architectural decision is a trade-off. There are no cost-free choices. By adopting the GitHub, Vercel, and Firestore stack, you are explicitly maximizing feature velocity over fine-grained control.

You lose the ability to tweak the underlying operating system, hold open persistent sockets, or run hour-long back-end scripts. In exchange, you gain an architecture that scales from zero to global distribution instantly, requires virtually no devops maintenance, and perfectly absorbs the asynchronous, event-driven realities of modern application development.

For the right application—whether it is a fast-moving prototype or an enterprise AI copilot—this stack doesn’t just save time; it fundamentally changes how quickly a small team (or a single person) can impact the market. You stop worrying about build chains, load balancers, and server patches, and you focus on the central mission: shipping features.

  •  

GitHub Copilot introduces upgrade canvas for modernizing .NET applications

GitHub Copilot has introduced an interactive canvas that makes it easier to follow, review, and steer the actions of the upgrade agent as it modernizes .NET applications.

The GitHub Copilot upgrade agent assesses the application, generates a structured upgrade plan, creates implementation tasks, and executes the work, according to a July 9 bulletin from Microsoft. Now developers can follow that workflow in the GitHub Copilot app through an interactive upgrade canvas. The upgrade canvas provides a live view of the modernization workflow as it unfolds, Microsoft said.

This agent upgrade agent starts by assessing the .NET application and identifying what needs to change:

  • What version of .NET is this application targeting?
  • Which NuGet packages need to be updated?
  • Are there breaking API changes?
  • Which projects can be upgraded independently?
  • What should happen first?

From this point, the agent generates a structured upgrade plan and breaks the work into actionable implementation tasks. While the GitHub Copilot app provides the interactive upgrade canvas, GitHub Copilot upgrade also is available in the following tools:

  • Visual Studio – Built directly into Visual Studio. Right-click a solution or project in Solution Explorer and select Modernize to start a .NET upgrade.
  • Visual Studio Code – Install the GitHub Copilot upgrade extension, select the Upgrade agent from the agent picker dropdown menu, and prompt the agent to modernize your .NET application.
  • GitHub Copilot CLI – Install the GitHub Copilot upgrade plugin to assess, plan, and execute .NET upgrades directly from the terminal.

Developers can get started with GitHub Copilot and the GitHub Copilot upgrade agent by visiting the GitHub Copilot upgrade marketplace.

  •  
❌