Unplugged holes in the npm and yarn package managers could let attackers bypass defenses against Shai-Hulud 27 Jan 2026, 1:42 am

Javascript developers should consider moving away from the npm and yarn platforms for distributing their work because newly-found holes allow threat actors to run malicious worm attacks like Shai-Hulud, says an Israeli researcher.

The warning comes from Oren Yomtov of Koi Security, who blogged Monday of discovering six zero day vulnerabilities in several package managers that could allow hackers bypass defenses that had been recommended last November after Shai-Hulud roamed through npm and compromised over 700 packages.

Those defenses are:

  • disabling the ability to run lifecycle scripts, commands that run automatically during package installation,
  • saving lockfile integrity checks (package-lock.json, pnpm-lock.yaml, and others) to version control (git). The lockfile records the exact version and integrity hash of every package in a dependency tree. On subsequent installs, the package manager checks incoming packages against these hashes, and if something doesn’t match, installation fails. If an attacker compromises a package and pushes a malicious version, the integrity check should catch the mismatch and block it from being installed.

Those recommendations “became the standard advice everywhere from GitHub security guides to corporate policy docs” after November, says Yomtov, “because if malicious code can’t run on install, and your dependency tree is pinned, you’re covered.”

November’s advice still valid, but more issues need addressing

That advice is still valid, he added in an email interview.

However, the vulnerabilities he discovered — dubbed PackageGate — that allow hackers to get around those two defenses have to be addressed by all platforms, he said.

So far, the pnpm, vlt, and Bun platforms have addressed the bypass holes, Yomtov said, but npm and yarn haven’t. He therefore recommends that JavaScript developers use pnpm, vlt or Bun.

He added that, in any case, JavaScript developers should keep whatever JavaScript package manager they use up to date to ensure they have the latest patches.

GitHub statement ‘bewildering’

Microsoft, which owns and oversees npm through GitHub, referred questions about the vulnerabilities to GitHub. It said in a statement, “We are actively working to address the new issue reported as npm actively scans for malware in the registry.” In the meantime, it urges project developers to adopt the recommendations in this blog issued after the Shai-Hulud attacks.

The statement also notes that, last September, GitHub said it is strengthening npm’s security, including making changes to authentication and token management.

GitHub also warns that that, if a package being installed through git contains a prepare script, its dependencies and devDependencies will be installed. “As we shared when the ticket was filed, this is an intentional design and works as expected. When users install a git dependency, they are trusting the entire contents of that repository, including its configuration files.”

Yomtov found this explanation of intentional design “bewildering.”

Not the complete picture

He says the scripts bypass vulnerability was reported through the HackerOne bug bounty program on November 26, 2025. While other JavaScript package managers accepted the reports, npm said the platform was working as intended, and that the ‘ignore scripts’ command should prevent the running of unapproved remote code.

“We didn’t write this post to shame anyone,” Yomtov said in the blog. “We wrote it because the JavaScript ecosystem deserves better, and because security decisions should be based on accurate information, not assumptions about defenses that don’t hold up.

“The standard advice, disable scripts and commit your lockfiles, is still worth following. But it’s not the complete picture,” he said. “Until PackageGate is fully addressed, organizations need to make their own informed choices about risk.”

(image/jpeg; 0.93 MB)

Descope introduces Agentic Identity Hub 2.0 for managing AI agents 27 Jan 2026, 1:15 am

Descope has announced Agentic Identity Hub 2.0, an update to its no-code identity platform for AI agents and Model Context Protocol (MCP) servers. The new release gives developers and security teams a dedicated UI and control plane to manage authorization, access control, credentials, and policies for AI agents and MCP servers, Descope said.

Unveiled January 26, Agentic Identity Hub 2.0 lets MCP developers and AI agent builders use the platform to manage AI agents as first-class identities alongside human users, and adds OAuth 2.1 and tool-level scopes to internal and external MCP servers. In addition, users can govern agent access to MCP servers with enterprise-grade policy enforcement. Descope’s no-code identity platform is intended to help organizations build and modify identity journeys for customers, partners, AI agents, and MCP servers using visual workflows, Descope said.

Specific capabilities of Agentic Identity Hub 2.0 include:

  • Agentic identity management and a centralized view of the agentic identities connected to an organization’s applications, APIs, and MCP servers.
  • MCP authorization, enabling MCP server developers to add protocol-compliant access control to internal and external-facing MCP servers.
  • A credential vault to manage credentials (OAuth tokens and API keys) that agents can use to access third-party systems.
  • Policy controls to help define granular authorizations to govern which AI agents can access MCP servers and which tool-level scopes can be invoked.
  • AI agent logging and auditing, providing visibility into every agent action.

(image/jpeg; 8.51 MB)

Kotlin-based Ktor 3.4 boosts HTTP client handling 26 Jan 2026, 8:11 pm

JetBrains has released Ktor 3.4, an update to its Kotlin-based framework for asynchronous server-side and client-side application development. The release brings duplex streaming to the OkHttp client engine and introduces a new HttpRequestLifecycle plugin that enables the cancellation of in-flight HTTP requests when the client disconnects.

Ktor 3.4 was announced January 23. Instructions for getting started can be found at ktor.io.

The new HttpRequestLifecycle plugin, which enables cancellation of in-flight HTTP requests when the client disconnects, is useful when there is a need to cancel a long-running or resource-intensive in-flight request. When the client disconnects, the coroutine handling the request is canceled, along with launch or async coroutines started by the client, and structured concurrency cleans all resources. This feature is currently supported only for the Netty and CIO engines.

Ktor 3.4 also introduces a new API for dynamically documenting endpoints that works in tandem with a new compiler plugin. Instead of building a Swagger front end from a static file, the model is built at runtime from details embedded in the routing tree. To generate documentation, developers can enable it through the Ktor Gradle plugin, then it will automatically provide details in code via the new describe API.

Also in Ktor 3.4, the OkHttp client engine now supports duplex streaming, enabling clients to send request body data and receive response data simultaneously, in contrast to regular HTTP calls, where the request body must be fully sent before the response begins. Duplex streaming is available for HTTP/2 connections and can be enabled using the new duplexStreamingEnabled property in OkHttpConfig.

And the Compression plugin now supports Ztsd via a ktor-server-compression-zstd module. Zstd is a fast compression algorithm with high compression ratios, low compression times, and a configurable compression level.

(image/jpeg; 3.01 MB)

Zero-trust data governance needed to protect AI models from slop 26 Jan 2026, 4:08 pm

Organizations need to be less trustful of data given how much of it is AI-generated, according to new research from Gartner.

As more enterprises jump on board the generative AI train — a recent Gartner survey found 84% expect to spend more on it this year — the risk grows that future large language models (LLMs) will be trained on outputs from previous models, increasing the danger of so-called model collapse.

To avoid this, Gartner recommends companies make changes to manage the risk of unverified data. These include the appointment of an AI governance leader to work closely with data and analytics teams; improve collaboration between departments with cross-functional groups including representatives from cybersecurity, data, and analytics; and updating existing security and data management policies to address risks from AI-generated data.

Gartner predicts that by 2028, 50% of organizations will have had to adopt a zero-trust posture for data governance as a result of this tidal wave of unverified AI-generated data.

“Organizations can no longer implicitly trust data or assume it was human generated,” Gartner managing VP Wan Fui Chan said in a statement. “As AI-generated data becomes pervasive and indistinguishable from human-created data, a zero-trust posture establishing authentication and verification measures is essential to safeguard business and financial outcomes.”

What makes matters even trickier to handle, said Chan, is that there will be different approaches to AI from governments. “Requirements may differ significantly across geographies, with some jurisdictions seeking to enforce stricter controls on AI-generated content, while others may adopt a more flexible approach,” he said.

Perhaps the best example of how AI can cause data governance issues was when Deloitte Australia had to refund part of a government contract fee after AI-generated errors, including non-existent legal citations, were included in its final report.

This article first appeared on CIO.

(image/jpeg; 11.39 MB)

Stop treating force multiplication as a side gig. Make it intentional 26 Jan 2026, 10:30 am

Most engineers have heard the phrase “10x engineer” or “force multiplier“. In practice, the highest leverage is not solo heroics but whether your presence makes everyone around you faster, safer and more effective. That is force multiplication.

Early in my time as a Senior Software Engineer, I didn’t have a clear framework for how to excel as a senior IC and multiply my team’s impact. I spoke with more than five mentors and a dozen senior and principal engineers. I distilled the lessons into a practical checklist that I use today. I’ll share that framework and how you can apply it this week to reduce risk, raise quality and increase delivery capacity.

What “force multiplication” really means

When I first joined, I thought being a force multiplier meant shipping more code. It took a few incidents and a couple of painful postmortems to realize the real leverage is what you do before the outage. A “10x engineer” is someone who masters context and amplifies team impact rather than focusing on raw output. Force multiplication is about setting the technical bar, improving team processes, mentoring teammates and providing direction so the whole team moves faster and safer.

  • Lead without authority. You may not have direct reports, yet you shape architecture, quality and the roadmap. Your leverage comes from artifacts, reviews and clear standards, not from title.I started by publishing a lightweight architecture template and a rollout checklist that the team could copy. That reduced ambiguity during design and cut review cycles by nearly 30 percent.

  • Establish clear standards. Work with your peers to define templates for design docs, pull requests, release plans and incident runbooks. Make those templates living artifacts in your wiki. When a new engineer joins, the first question shouldn’t be “How do we do this?”. It should be “Which template applies?”.

  • Hold a high bar with clarity. Give specific, timely feedback on code and designs. When timelines are tight, present options with explicit tradeoffs and risks and recommend a path. I learned to stop saying “we’ll figure it out later.” Instead, I started offering two plans: plan A holds the date with reduced scope and known risks; plan B holds scope with a later date. That framing helped leadership make tradeoffs without surprise.

  • Build in quality and operational excellence. Treat code quality, test coverage, observability, error budgets, release safety and rollback readiness as part of the definition of done. I wired these into code reviews and on‑call routines, so they persisted under pressure. Observability is not a feature; it’s a nonfunctional requirement that must be planned and reviewed. According to the 2023 DORA report, elite teams deploy code multiple times per day and restore service in under an hour, while low performers take weeks to recover.

  • Make learning and knowledge-sharing routine. Run short office hours, host brown‑bag sessions, capture lessons from incidents and maintain a “first 30 days” checklist for new hires. The goal is to replace ad hoc heroics with replicable practices.

The senior engineer portfolio: How you spend your time

To avoid burnout and cover the areas above, you need a plan. Here’s the mix I use as a planning tool. The percentages will vary by company and team, but if any bucket falls to zero, quality or culture may drift.

  • 50%: Individual project delivery. Own a meaningful slice of product or platform work end-to-end. This keeps your judgment sharp and your credibility high. Show by example that your architecture, code and testing follow best practices.
  • 20%: Reviews and feedback on architecture, code and processes. Give actionable feedback that improves maintainability, resilience and readability. Use the documented standards as examples so your comments scale beyond one pull request.
  • 10%: Long-term architecture and technical debt. Maintain a living architecture document, potential bottlenecks, a small set of SLIs and a technical debt register that explains business risk in plain language. Advocate for a steady capacity for debt reduction.
  • 10%: Mentoring and unblocking the team. Run office hours, help teammates navigate tricky technical issues and unblock work.
  • 10%: Learning and sharing best practices. Curate guidelines for architectures, code, rollouts and rollback plans. Encourage the team to contribute and keep the guidance current.

Why this mix matters: culture and quality are as much your job as they are your manager’s. Managers create the environment and priorities. Senior engineers operationalize the standards that make quality and learning the default.

7 practical steps to multiply impact

Below are the actions I took that you could adopt. Each is simple but not easy; they require discipline and a small-time investment that pays back quickly.

  1. Build a weekly learning routine. Block 30 minutes on your calendar to review coding standards, architecture templates and operational excellence practices. Note gaps you see in the team. Compare against company guidance and industry best practices. Share one short tip or pattern each week. Weekly, visible improvements create momentum and motivation.

  2. Schedule peer 1:1s that develop people. Meet teammates with a coaching agenda: understand career goals, the projects they are interested in. Provide actionable feedback to improve in the areas of interest. After design reviews or incidents, send a one‑paragraph follow‑up that captures the lesson and links to a reference example.

  3. Grow your staff network and bring the outside in. Connect with senior and principal engineers across orgs. Ask for one lesson from a recent migration, incident or scale event. Summarize what you learned in a short note and link artifacts your team can copy. This prevents local maxima and speeds adoption.

  4. Advise leadership with options and risk. For deadlines that may potentially compromise quality, present two plans: hold the date with explicit scope tradeoffs and stated risks or hold the scope with a date that matches capacity. Tie technical debt to user or revenue impact and propose a steady allocation to address it. Surface cultural risks like burnout with data and anecdotes.

  5. Influence the roadmap from the bottom up. Facilitate brainstorming on long-term architecture and reliability goals. Turn ideas into lightweight proposals with options and tradeoffs. Partner with product to merge user value, technical debt and reliability into a single prioritized roadmap.

  6. Raise the hiring bar and make it scalable. Invite engineers to shadow your interviews with a clear rubric. Debrief immediately, then graduate them to reverse shadow and go solo. Capture good prompts, work samples and scoring guidance so the loop is consistent and fair across candidates.

  7. Allocate time to do the multiplying work. If your team participates in sprint planning, make sure to reserve your bandwidth for these activities. Trying to do them outside your project work leads to burnout and inconsistent impact.

One small example

On one project, we were shipping a new feature with a tight deadline. The first rollout exposed a gap in observability: we couldn’t distinguish a configuration drift from a control plane bug. I proposed adding a small, focused set of SLIs and a release checklist that required a canary window, synthetic traffic tests and a rollback plan. I also documented the pattern in our wiki and ran a 20‑minute brownbag to walk through the checklist.

The result: the next rollout caught the issue in the canary phase, we rolled back gracefully and the postmortem was short and constructive. More importantly, the checklist became the team norm. We reduced incident severity in the next two semesters and shortened our mean time to recovery. That is force multiplication in action: a small change in standards yielded outsized reliability gains.

Make force multiplication your operating model

Force multiplication isn’t a personality trait or a side gig – it’s a repeatable operating model. It’s the standards you codify, the reviews you run, the guardrails you build and the automations you ship so the team can move faster with less risk. When senior ICs make this work visible and measurable, the organization gets predictable delivery, fewer surprises and more capacity for innovation.

Start this week. Pick one of the seven steps and turn it into a tiny experiment:

  • Publish a one‑page architecture template and a release checklist
  • Add 2–3 SLIs for a critical service and set alert thresholds
  • Draft a one‑page A/B decision memo for your next release

Measure the impact. Track 1–2 leading indicators (e.g., canary‑phase failures caught, number of automated recoveries, review cycle time) and 1–2 lagging outcomes (e.g., incident severity, MTTR, rollback rate). Share the results in your next retro and iterate.

Your next move. Publish your checklist in the team wiki, run a 20‑minute brown‑bag to socialize it and put one “multiplying work” card on the board this sprint. Repeat, measure and teach.

[Note: The views expressed in this article are my own and do not represent the views of Microsoft.]

This article is published as part of the Foundry Expert Contributor Network.
Want to join?

(image/jpeg; 11.16 MB)

Why your AI agents need a trust layer before it’s too late 26 Jan 2026, 10:00 am

When one compromised agent brought down our entire 50-agent ML system in minutes, I realized we had a fundamental problem. We were building autonomous AI agents without the basic trust infrastructure that the internet established 40 years ago with DNS.

As a PhD researcher and IEEE Senior Member, and I’ve spent the past year building what I call “DNS for AI agents” — a trust layer that finally gives autonomous AI the security foundation it desperately needs. What started as a research project to solve authentication problems in multi-tenant ML environments has evolved into a production system that’s changing how organizations deploy AI agents at scale.

The transformation from traditional machine learning to agentic AI represents one of the most significant shifts in enterprise technology. While traditional ML pipelines require human oversight at every step — data validation, model training, deployment and monitoring — modern agentic AI systems enable autonomous orchestration of complex workflows involving multiple specialized agents. But with this autonomy comes a critical question: How do we trust these agents?

The cascading failure that changed everything

Let me share what happened in our production environment that crystallized this problem. We were running a multi-tenant ML operations system with 50 agents, handling everything from concept-drift detection to automated model retraining. Each agent had its own responsibility, its own credentials and its own hardcoded endpoints for communicating with other agents.

On a Tuesday morning, a single agent was compromised due to a configuration error. Within six minutes, the entire system collapsed. Why? Because agents had no way to verify each other’s identity. The compromised agent impersonated our model deployment service, causing downstream agents to deploy corrupted models. Our monitoring agent, unable to distinguish legitimate from malicious traffic, dutifully reported everything as normal.

This wasn’t just a technical failure — it was a trust failure. We had built an autonomous system without the fundamental mechanisms for agents to discover, authenticate and verify each other. It was like building a global network without DNS, where every connection relies on hardcoded IP addresses and blind trust.

That incident revealed four critical gaps in how we deploy AI agents today.

  1. There’s no uniform discovery mechanism — agents rely on manual configuration and hardcoded endpoints.
  2. Cryptographic authentication between agents is virtually nonexistent.
  3. Agents can’t prove their capabilities without exposing sensitive implementation details.
  4. Governance frameworks for agent behavior are either nonexistent or impossible to enforce consistently.

Building trust from the ground up

The solution we developed, called Agent Name Service (ANS), takes inspiration from how the internet solved a similar problem decades ago. DNS transformed the internet by mapping human-readable names to IP addresses. ANS does something similar for AI agents, but with a crucial addition: it maps agent names to their cryptographic identity, their capabilities and their trust level.

Here’s how it works in practice. Instead of agents communicating through hardcoded endpoints like “http://10.0.1.45:8080,” they use self-describing names like “a2a://concept-drift-detector.drift-detection.research-lab.v2.prod.” This naming convention immediately tells you the protocol (agent-to-agent), the function (drift detection), the provider (research-lab), the version (v2) and the environment (production).

But the real innovation lies beneath this naming layer. We built ANS on three foundational technologies that work together to create comprehensive trust.

  1. Decentralized Identifiers (DIDs) give each agent a unique, verifiable identity using W3C standards originally designed for human identity management.
  2. Zero-knowledge proofs allow agents to prove they have specific capabilities — like database access or model training permissions — without revealing how they access those resources.
  3. Policy-as-code enforcement through Open Policy Agent ensures that security rules and compliance requirements are declarative, version-controlled and automatically enforced.

We designed ANS as a Kubernetes-native system, which was crucial for enterprise adoption. It integrates directly with Kubernetes Custom Resource Definitions, admission controllers and service mesh technologies. This means it works with the cloud-native tools organizations already use, rather than requiring a complete infrastructure overhaul.

The technical implementation leverages what’s called a zero-trust architecture. Every agent interaction requires mutual authentication using mTLS with agent-specific certificates. Unlike traditional service mesh mTLS, which only proves service identity, ANS mTLS includes capability attestation in the certificate extensions. An agent doesn’t just prove “I am agent X” — it proves “I am agent X and I have the verified capability to retrain models.”

From research to production reality

The real validation came when we deployed ANS in production. The results exceeded even our optimistic expectations. Agent deployment time dropped from 2–3 days to under 30 minutes — a 90% reduction. What used to require manual configuration, security reviews, certificate provisioning and network setup now happens automatically through a GitOps pipeline.

Even more impressive was the deployment success rate. Our traditional approach had a 65% success rate, with 35% of deployments requiring manual intervention to fix configuration errors. With ANS, we achieved 100% deployment success with automated rollback capability. Every deployment either succeeds completely or rolls back cleanly — no partial deployments, no configuration drift, no manual cleanup.

The performance metrics tell an equally compelling story. Service response times average under 10 milliseconds, which is fast enough for real-time agent orchestration while maintaining cryptographic security. We’ve successfully tested the system with over 10,000 concurrent agents, demonstrating that it scales far beyond typical enterprise needs.

ANS in action

Let me share a concrete example of how this works. We have a concept-drift detection workflow that illustrates the power of trusted agent communication. When our drift detector agent notices a 15% performance degradation in a production model, it uses ANS to discover the model retrainer agent by capability — not by hardcoded address. The drift detector then proves it has the capability to trigger retraining using a zero-knowledge proof. An OPA policy validates the request against governance rules. The retrainer executes the update and a notification agent alerts the team via Slack.

This entire workflow — discovery, authentication, authorization, execution and notification — happens in under 30 seconds. It’s 100% secure, fully audited and happens without any human intervention. Most importantly, every agent in the chain can verify the identity and capabilities of the others.

Lessons learned and the path forward

Building ANS taught me several lessons about deploying autonomous AI systems. First, security can’t be an afterthought. You can’t bolt trust onto an agent system later — it must be foundational. Second, standards matter. By supporting multiple agent communication protocols (Google’s A2A, Anthropic’s MCP and IBM’s ACP), we ensured ANS works across the fragmented agent ecosystem. Third, automation is non-negotiable. Manual processes simply can’t scale to the thousands of agents that enterprises will be running.

The broader implications extend beyond just ML operations. As organizations move toward autonomous AI agents handling everything from customer service to infrastructure management, the trust problem becomes existential. An autonomous system without proper trust mechanisms is a liability, not an asset.

We’ve seen this pattern before in technology evolution. In the early internet, we learned that security through obscurity doesn’t work. With cloud computing, we learned that perimeter security isn’t enough. Now, with agentic AI, we’re learning that autonomous systems require comprehensive trust frameworks.

The open-source implementation we’ve released includes everything needed to deploy ANS in production: the core library, Kubernetes manifests, demo agents, OPA policies and monitoring configurations. We’ve also published the complete technical presentation from MLOps World 2025 where I demonstrated the system live.

What this means for enterprise AI strategy

If you’re deploying AI agents in your organization — and recent surveys suggest most enterprises are — you need to ask yourself some hard questions.

  • How do your agents authenticate with each other?
  • Can they verify capabilities without exposing credentials?
  • Do you have automated policy enforcement?
  • Can you audit agent interactions?

If you can’t answer these questions confidently, you’re building on a foundation of trust assumptions rather than cryptographic guarantees. And as our cascading failure demonstrated, those assumptions will eventually fail you.

The good news is that this problem is solvable. We don’t need to wait for vendors or standards bodies. The technologies exist today: DIDs for identity, zero-knowledge proofs for capability attestation, OPA for governance and Kubernetes for orchestration. What was missing was a unified framework that brings them together specifically for AI agents.

The shift to autonomous AI is inevitable. The only question is whether we’ll build these systems with proper trust infrastructure from the start or whether we’ll wait for a major incident to force our hand. Based on my experience, I strongly recommend the former.

The future of AI is agentic. The future of agentic AI must be secure. ANS provides the trust layer that makes both possible.

The complete Agent Name Service implementation, including source code, deployment configurations and documentation, is available at github.com/akshaymittal143/ans-live-demo. A technical presentation demonstrating the system is available at MLOps World 2025.

This article is published as part of the Foundry Expert Contributor Network.
Want to join?

(image/jpeg; 2.8 MB)

AI makes the database matter again 26 Jan 2026, 9:00 am

Developers have spent the past decade trying to forget databases exist. Not literally, of course. We still store petabytes. But for the average developer, the database became an implementation detail; an essential but staid utility layer we worked hard not to think about.

We abstracted it behind object-relational mappers (ORM). We wrapped it in APIs. We stuffed semi-structured objects into columns and told ourselves it was flexible. We told ourselves that persistence was a solved problem and began to decouple everything. If you needed search, you bolted on a search system. Ditto for caching (grab a cache), documents (use a document store), relationships (add a graph database), etc. We thought we were being clever but really we were shifting complexity from the database engine into glue code, pipelines, and operational overhead.

The architectural frailty of this approach has been laid bare by AI.

In an AI-infused application, the database stops being a passive store of record and becomes the active boundary between a probabilistic model and your system of record. The difference between a cool demo and a mission-critical system is not usually the large language model (LLM). It is the context you can retrieve, the consistency of that context, and the speed at which you can assemble it.

AI has made the database visible again. We are not suddenly loving SQL again, but we are realizing that AI memory is just another database problem. Your database is no longer just where data lives. It is where context gets assembled, and in AI, context is everything.

Consistency and hallucinations

To understand why we are struggling, we have to look at how we got here. We didn’t eliminate the database during the past 10 years. We actually multiplied it.

Modern application design taught us to route around database limits. We built caches, search clusters, stream processors, and a cacophony of purpose-built stores. We convinced ourselves that “polyglot persistence” (wiring together five different “best of breed” systems) was architectural enlightenment. In reality, it was mostly just résumé-driven development that shifted complexity from the database engine to the application code.

That worked when “eventual consistency” was acceptable. In AI, it doesn’t work. At all.

Consider a practical retrieval-augmented generation (RAG) pipeline. It is rarely as simple as “fetch vectors.” A real enterprise AI workflow needs vector similarity search to find semantic matches, document retrieval to fetch the content, graph traversal to understand relationships like permissions or hierarchy, and time-series analysis to ensure the data is not stale. In the “bolt-on” architecture of the last decade, you implement that by composing specialized services: a vector database, a document store, a graph database, and a time-series system.

Such a bolt-on architecture wasn’t ideal but neither was it the deal-killer that AI makes it. Every arrow in the flow is a network hop, and every hop adds serialization overhead. Making matters worse, every separate system introduces a new consistency model. You are paying a tax in complexity, latency, and inconsistency when you split what should be one logical context into six different physical systems. AI is uniquely sensitive to this tax.

When a normal web app shows stale data, a user might see an old inventory count for a few seconds. When an AI agent retrieves inconsistent context (perhaps fetching a vector that points to a document that has already been updated in the relational store), it constructs a plausible narrative based on false premises. We call these hallucinations, but often the model is not making things up. It is being fed stale data by a fragmented database architecture. If your search index is “eventually consistent” with your system of record, your AI is “eventually hallucinating.”

How about if your transactional system is the source of truth, but your vector index updates asynchronously? Well, you’ve built a time lag into your agent’s memory. If your relationship data is synced through a pipeline that can drift, your agent can “know” relationships that are no longer true. If permissions are checked in one system while content is fetched from another, you are one bug away from data leakage.

This problem gets worse when we move from passive chatbots to active agents. We expect the next generation of AI to perform tasks, not just summarize text. But doing things requires transactions. If your agent needs to update a customer record (relational), re-index their preference profile (vector), and log the interaction (document), and your database architecture requires a saga pattern to coordinate those writes across three different systems, you have built a fragility engine. In a fragmented stack, a failure halfway through that workflow leaves your agent’s world in a corrupted state. You cannot build a reliable agent if it cannot rely on atomicity, consistency, isolation, durability (ACID) guarantees across its entire memory space.

That is not an AI problem. It’s a basic architecture problem. As I have noted, you cannot build a reliable agent on unreliable data infrastructure. Reliability work for agents is inseparable from database work.

Architectural constraints

For years, developers have accepted good-enough performance because we could simply scale horizontally. If a query was slow, we added nodes. But AI workloads are computationally heavy, and the underlying physics of our data structures matters again.

Take the simple act of reading a JSON document. In some popular document stores, the underlying binary format requires sequential field scanning. That is an O(n) operation. To find a field at the end of a large document, the engine must scan everything preceding it. That may work for a simple CMS, but it completely breaks down when you’re operating at enterprise scale (say, 100,000 requests per second during a viral event), because nanoseconds compound. An O(n) scan at that volume can waste dozens of CPU cores just parsing data. In contrast, newer binary formats use hash-indexed navigation to allow O(1) jumps to specific fields, delivering performance gains of 500 times or more for deep document traversal.

This is not a micro-optimization. It is a fundamental architectural constraint. “Just nanoseconds” is what you say when you have not operated at the scale where latency kills the user experience. In an AI world where inference is already slow, your database cannot afford to add latency due to inefficient algorithmic foundations.

Stop building infrastructure

I am not saying there is no place for specialized tools. But the mistake we made in the last decade was assuming we could assemble five specialized systems and get something simpler than one general system. For AI, the question to ask is not “Which database has vector search?” The question is “Where does my context live, and how many consistency boundaries do I cross to assemble it?”

If the answer is “a lot,” you are signing up to build infrastructure. You are building pipelines, retries, reconciliation logic, and monitoring for lag you will eventually treat as normal.

The alternative is to stop treating data models as physical mandates. In the past, if we needed a graph, we copied data to a graph database. If we needed vectors, we copied data to a vector store. That copying is the root of the synchronization evil.

The scientific approach is to treat data as having one canonical form that can be projected into whatever shape the application needs. Do you need to traverse relationships? The database should project a graph view. Do you need to search semantics? It should project a vector view. These should not be copies that require pipelines. They should be different lenses on the same single source of truth. When the record updates, every projection updates instantly.

If you are building an AI-infused application and your plan involves maintaining multiple pipelines to keep multiple databases in sync, you are not building AI. You are building a context delivery system, and you are taking on all the operational risk that comes with it.

Here is the decision rule I would use. Count how many consistency boundaries your agent crosses to answer a question. Count how many physical copies of the same truth exist across your stack. If either number keeps growing, your reliability work is already in trouble.

This is why the database matters again. AI is forcing us to confront what we spent a decade abstracting away: The hard part of software is turning messy reality into a coherent, queryable representation of the world. In the age of AI, context rules. Databases, for all their supposed boringness, are still the best tool we have for delivering that context securely at scale. They allow you to delete the infrastructure that provides no business value: the ETL jobs, the synchronization pipelines, the object-relational mapping layers, and the distributed transaction coordinators. The best code is the code you do not write.

(image/jpeg; 5.21 MB)

16 open source projects transforming AI and machine learning 26 Jan 2026, 9:00 am

For several decades now, the most innovative software has always emerged from the world of open source software. It’s no different with machine learning and large language models. If anything, the open source ecosystem has grown richer and more complex, because now there are open source models to complement the open source code.

For this article, we’ve pulled together some of the most intriguing and useful projects for AI and machine learning. Many of these are foundation projects, nurturing their own niche ecology of open source plugins and extensions. Once you’ve started with the basic project, you can keep adding more parts.

Most of these projects offer demonstration code, so you can start up a running version that already tackles a basic task. Additionally, the companies that build and maintain these projects often sell a service alongside them. In some cases, they’ll deploy the code for you and save you the hassle of keeping it running. In others, they’ll sell custom add-ons and modifications. The code itself is still open, so there’s no vendor lock in. The services simply make it easier to adopt the code by paying someone to help.

Here are 16 open source projects that developers can use to unlock the potential in machine learning and large language models of any size—from small to large, and even extra large.

Agent Skills

AI coding agents are often used to tackle standard tasks like writing React components or reviewing parts of the user interface. If you are writing a coding agent, it makes sense to use vetted solutions that are focused on the task at hand. Agent Skills are pre-coded tools that your AI can deploy as needed. The result is a focused set of vetted operations capable of producing refined, useful code that stays within standard guidelines. License: MIT.

Awesome LLM Apps

If you are looking for good examples of agentic coding, see the Awesome LLM Apps collection. Currently, the project hosts several dozen applications that leverage some combination of RAG databases and LLMs. Some are simple, like a meme generator, while others handle deeper research like the Journalist agent. The most complex examples deploy multi-agent teams to converge upon an answer. Every application comes with working examples for experimentation, so you can learn from what’s been successful in the past. Altogether, the apps in this collection are great inspiration for your own projects. License: Apache 2.0.

Bifrost

If your application requires access to an LLM service, and you don’t have a particular one in mind, check out Bifrost. A fast, unified gateway to more than 15 LLM providers, this OpenAI-compatible API quickly abstracts away the differences between models, including all the major ones. It includes essential features like governance, caching, budget management, load balancing, and it has guardrails to catch problems before they are sent out to service providers, who will just bill you for the time. With dozens of great LLM providers constantly announcing new and better models, why limit yourself? License: Apache 2.0.

Claude Code

If the popularity of AI coding assistants tells us anything, it’s that all developers—and not just the ones building AI apps—appreciate a little help writing and reviewing their code. Claude Code is that pair programmer. Trained on all the major programming languages, Claude Code can help you write code that is better, faster, and cleaner. It digests a codebase and then starts doing your bidding, while also making useful suggestions. Natural language commands plus some vague hand waving are all the Anthropic LLM needs to refactor, document, or even add new features to your existing code. License: Anthropic’s Commercial TOS.

Clawdbot

Many of the tools in this list help developers create code for other people. Clawdbot is the AI assistant for you, the person writing the code. It integrates with your desktop to control built-in tools like the camera and large applications like the browser. A multi-channel inbox accepts your commands through more than a dozen different communication channels including WhatsApp, Telegram, Slack, and Discord. A cron job adds timing. It’s the ultimate assistant for you, the ruler of your data. If AI exists to make our lives easier, why not start by organizing the applications on your desktop? License: MIT.

Dify

For projects that require more than just one call to an LLM, Dify could be the solution you’ve been looking for. Essentially a development environment for building complex agentic workflows, Dify stitches together LLMs, RAG databases, and other sources. It then monitors how they perform under different prompts and parameters and puts it all together in a handy dashboard, so you can iterate on the results. Developing agentic AI requires rapid experimentation, and Dify provides the environment for those experiments. License: Modified version of Apache 2.0 to exclude some commercial uses.

Eigent

The best way to explore the power and limitations of an agentic workflow is to deploy it yourself on your own machine, where it can solve your own problems. Eigent delivers a workforce of specialized agents for handling tasks like writing code, searching the web, and creating documents. You just wave your hands and issue instructions, and Eigent’s LLMs do their best to follow through. Many startups brag about eating their own dogfood. Eigent puts that concept on a platter, making it easy for AI developers to experience directly the abilities and failings of the LLMs they’re building. License: Apache 2.0.

Headroom

Programmers often think like packrats. If the data is good, why not pack in some more? This is a challenge for code that uses an LLM because these services charge by the token, and they also have a limited context window. Headroom tackles this issue with agile compression algorithms that trim away the excess, especially the extra labels and punctuation found in common formats like JSON. A big part of designing working AI applications is cost engineering, and saving tokens means saving money. License: Apache 2.0.

Hugging Face Transformers

When it comes to starting up a brand-new machine learning project, Hugging Face Transformers is one of the best foundations available. Transformers offers a standard format for defining how the model interacts with the world, which makes it easy to drop a new model into your working infrastructure for training or deployment. This means your model will interact nicely with all the already available tools and infrastructure, whether for text, vision, audio, video, or all of the above. Fitting into a standard paradigm makes it much easier to leverage your existing tools while focusing on the cutting edge of your research. License: Apache 2.0.

LangChain

For agentic AI solutions that require endless iteration, LangChain is a way to organize the effort. It harnesses the work of a large collection of models and makes it easier for humans to inspect and curate the answers. When the task requires deeper thinking and planning, LangChain makes it easy to work with agents that can leverage multiple models to converge upon a solution. LangChain’s architecture includes a framework (LangGraph) for organizing easily customizable workflows with long-term memory, and a tool (LangSmith) for evaluating and improving performance. Its Deep Agents library provides teams of sub-agents, which organize problems into subsets then plan and work toward solutions. It is a proven, flexible test bed for agentic experimentation and production deployment. License: MIT.

LlamaIndex

Many of the early applications for LLMs are sorting through large collections of semi-structured data and providing users with useful answers to their questions. One of the fastest ways to customize a standard LLM with private data is to use LlamaIndex to ingest and index the data. This off-the-shelf tool provides data connectors that you can use to unpack and organize a large collection of documents, tables, and other data, often with just a few lines of code. The layers underneath can be tweaked or extended as the job requires, and LlamaIndex works with many of the data formats common in enterprises. License: MIT.

Ollama

For anyone experimenting with LLMs on their laptop, Ollama is one of the simplest ways to download one or more of them and get started. Once it’s installed, your command line becomes a small version of the classic ChatGPT interface, but with the ability to pull a huge collection of models from a growing library of open source options. Just enter: ollama run and the model is ready to go. Some developers are using it as a back-end server for LLM results. The tool provides a stable, trustworthy interface to LLMs, something that once required quite a bit of engineering and fussing. The server simplifies all this work so you can tackle higher level chores with many of the most popular open source LLMs at your fingertips. License: MIT.

OpenWebUI

One of the fastest ways to put up a website with a chat interface and a dedicated RAG database is to spin up an instance of OpenWebUI. This project knits together a feature-rich front end with an open back end, so that starting up a customizable chat interface only requires pulling a few Docker containers. The project, though, is just a beginning, because it offers the opportunity to add plugins and extensions to enhance the data at each stage. Practically every part of the chain from prompt to answer can be tweaked, replaced, or improved. While some teams might be happy to set it up and be done, the advantages come from adding your own code. The project isn’t just open source itself, but a constellation of hundreds of little bits of contributed code and ancillary projects that can be very helpful. Being able to customize the pipeline and leverage the MCP protocol supports the delivery of precision solutions. License: Modified BSD designed to restrict removing OpenWebUI branding without an enterprise license.

Sim

The drag-and-drop canvas for Sim is meant to make it easier to experiment with agentic workflows. The tool handles the details of interacting with the various LLMs and vector databases; you just decide how to fit them together. Interfaces like Sim make the agentic experience accessible to everyone on your team, even those who don’t know how to write code. License: Apache 2.0.

Sloth

One of the most straightforward ways to leverage the power of foundational LLMs is to start with an open source model and fine-tune it with your own data. Unsloth does this, often faster than other solutions do. Most major open source models can be transformed with reinforcement learning. Unsloth is designed to work with most of the standard precisions and some of the largest context windows. The best answers won’t always come directly from RAG databases. Sometimes, adjusting the models is the best solution. License: Apache 2.0.

vLLM

One of the best ways to turn an LLM into a useful service for the rest of your code is to start it up with vLLM. The tool loads many of the available open source models from repositories like Hugging Face and then orchestrates the data flows so they keep running. That means batching the incoming prompts and managing the pipelines so the model will be a continual source of fast answers. It supports not just the CUDA architecture but also AMD CPUs and GPUs, Intel CPUs and GPUs, PowerPC CPUs, Arm CPUs, and TPUs. It’s one thing to experiment with lots of models on a laptop. It’s something else entirely to deploy the model in a production environment. vLLM handles many of the endless chores that deliver better performance. License: Apache-2.0.

(image/jpeg; 0.09 MB)

GitHub Copilot SDK allows developers to build Copilot agents into apps 23 Jan 2026, 10:24 pm

GitHub has launched a technical preview of the GitHub Copilot SDK, a tool kit for embedding the “agentic core” of the GitHub Copilot CLI into applications.

Available on GitHub, the SDK was unveiled on January 22. Initially available for Node.js/TypeScript, Python, Go, and .NET, the GitHub Copilot SDK exposes the same engine behind the GitHub Copilot CLI, a production-tested agent runtime that can be invoked programmatically. There is no need to build orchestration, according GitHub. Users define agent behavior, and Copilot handles planning, tool invocation, file edits, and more, according to GitHub. A GitHub Copilot subscription is required to use the SDK.

Developers using the SDK can take advantage of GitHub Copilot CLI’s support for multiple AI models, custom tool definitions, Model Context Protocol (MCP) server integration, GitHub authentication, and real-time streaming. GitHub teams already have used the SDK for applications such YouTube chapter generators, custom GUIs for agents, speech-to-command workflows to run apps, games in which players can compete with AI, and ummarizing tools.

“Think of the Copilot SDK as an execution platform that lets you reuse the same agentic loop behind the Copilot CLI, while GitHub handles authentication, model management, MCP servers, custom agents, and chat sessions plus streaming,” said GitHub’s Mario Rodriguez, chief product officer for the GitHub product team and the author of the January 21 blog post. “That means you are in control of what gets built on top of those building blocks.”

(image/jpeg; 22.45 MB)

Go developers meh on AI coding tools – survey 23 Jan 2026, 9:12 pm

Most Go language developers are using AI-powered software development tools, but their satisfaction with these tools is middling, according to the 2025 Go Developer Survey. The survey also found that the vast majority of Go developers—91%—were satisfied with using the language.

Results of the survey, which featured responses from 5,739 Go developers in September 2025, were published January 21 in the go.dev blog.

In the survey, 55% of respondents reported being satisfied with AI-powered development tools, but this was heavily weighted towards “Somewhat satisfied” (42%) vs. “Very satisfied” (13%). Respondents were asked to tell something good they had accomplished with these tools as well as something that did not work out. A majority said that creating non-functional code was their primary problem with AI developer tools (53%), while nearly one-third (30%) lamented that even working code was of poor quality, according to the report. The most frequently cited benefits of AI coding tools, conversely, were generating unit tests, writing boilerplate code, enhanced autocompletion, refactoring, and documentation generation.

Whereas 53% of respondents said they use AI-powered development tools daily, 29% did not use these tools at all, or only used them a few times during the past month. The most commonly used AI coding assistants were ChatGPT (45%), GitHub Copilot (31%), Claude Code (25%), Claude (23%), and Gemini (20%), the report said.

As for the language itself, almost two-thirds of respondents were very satisfied using Go, with the overall satisfaction rate hitting 91%. Developers find tremendous value in using Go as a holistic platform, said the report. “Go is by far my favorite language; other languages feel far too complex and unhelpful,” one respondent said. “The fact that Go is comparatively small, simple, with fewer bells and whistles plays a massive role in making it such a good long-lasting foundation for building programs with it.”

Other findings of the 2025 Go Developer Survey:

  • Command-line tools (74%) and API/RPC services (73%) were the top two types of projects respondents were building with Go. Libraries or frameworks (49%) finished third.
  • The top three frustrations the developers reported when building with Go were “Ensuring our Go code follows best practices / Go idioms” (33%), “A feature I value from another language isn’t part of Go” (28%), and “Finding trustworthy Go modules and packages” (26%). 
  • Most respondents develop on macOS (60%) or Linux (58%) and deploy to Linux-based systems (96%).
  • Visual Studio Code was the favorite code editor cited (37%), followed by GoLand/IntelliJ (28%) and Vim/NeoVim (19%).
  • The most common deployment environments for Go were Amazon Web Services (46%), company-owned servers (44%), and Google Cloud Platform (26%).

(image/jpeg; 1.69 MB)

Agentic AI exposes what we’re doing wrong 23 Jan 2026, 9:00 am

We’ve spent the last decade telling ourselves that cloud computing is mostly a tool problem. Pick a provider, standardize a landing zone, automate deployments, and you’re “modern.” Agentic AI makes that comforting narrative fall apart because it behaves less like a traditional application and more like a continuously operating software workforce that can plan, decide, act, and iterate.

Agentic AI has changed cloud computing, but not in the way the hype machine wants you to believe. It hasn’t magically replaced engineering, nor has it made architecture irrelevant. It has made weak architecture, fuzzy governance, and sloppy cost controls impossible to ignore. If you are already running cloud with strong disciplines, agentic AI is an accelerant. If you aren’t, it’s a stress test you will fail, publicly and expensively.

Agentic AI is an AI system that can autonomously plan and execute multistep actions toward a goal, often by using tools and services in its environment. That’s the key difference from “chat”: An agent doesn’t just recommend what to do; it can actually do it, repeatedly, at machine speed, and it will keep doing it until you stop it or constrain it properly.

In cloud terms, AI can become a key cloud actor: provisioning resources, calling APIs, moving data, modifying configurations, opening tickets, triggering workflows, and chaining services. This means the cloud now supports autonomous decision loops, which have failure modes distinct from those of web apps with fixed request/response paths.

Adapting cloud networks to agentic AI

Traditional cloud networking assumptions are already shaky: perimeter thinking, coarse segmentation, and “allow lists” that grow without limits. Agentic AI makes those patterns actively dangerous because agents don’t just talk to one back end and one database; they discover, orchestrate, and pivot across systems as part of normal operations. The network becomes a dynamic substrate for tool use rather than a static map of application tiers.

What needs to change is the level of precision and adaptability in network controls. You need networking that supports fine-grained segmentation, short-lived connectivity, and policies that can be continuously evaluated rather than set once and forgotten. You also need to treat east-west traffic visibility as a core requirement because agents will generate many internal calls that look legitimate unless you understand intent, identity, and context.

Finally, plan for bursty, unpredictable communication patterns. Agents will fan out, call many endpoints, retry aggressively, and trigger cascades across regions and services if you let them. That pushes you toward stronger service-to-service policy, more transparent egress governance, and tighter coupling between networking telemetry and runtime controls, so you can see and stop pathological behavior before it becomes an outage or a bill.

Aligning with identity-based security

Cloud security has shifted toward identity for years, and agentic AI completes the move. When the user is an autonomous agent, control relies solely on identity: what the agent is, its permitted actions, what it can impersonate, and what it can delegate. Network location and static IP-based trust weaken when actions are initiated by software that can run anywhere, scale instantly, and change execution paths.

This is where many enterprises will stumble. They’ll give an agent broad API permissions to be helpful, then act surprised when it becomes broadly dangerous. The correct posture is to treat every agent as a privileged workload until proven otherwise because agents are effectively operators with superhuman speed. You need explicit identities for agents, tight authorization boundaries, short-lived credentials, audited tool access, and strong separation between environments and duties.

Identity-based security requires us to clearly define who did what, making it difficult to overlook details. If an agent modifies infrastructure, moves data, or grants access, you need to trace the action back to a specific identity, under a given policy, with an approval or constraint chain. Governance isn’t optional; it’s the essential control framework for autonomous operations.

Cloud finops and cultural shifts

If you think cloud bills were unpredictable before, wait until you unleash systems that can decide to use more resources in pursuit of a goal. Agentic AI changes how cloud resources are leveraged by making consumption far more elastic, exploratory, and continuous. Agents will spin up ephemeral environments, run iterative experiments, call paid APIs, generate and store large artifacts, and repeat tasks until they converge—sometimes without a natural stopping point.

The old finops playbook of tagging, showback, and monthly optimization is not enough on its own. You need near-real-time cost visibility and automated guardrails that stop waste as it happens, because “later” can mean “after the budget is gone.” Put differently, the unit economics of agentic systems must be designed, measured, and controlled like any other production system, ideally more aggressively because the feedback loop is faster.

There’s also a cultural shift here that many leaders will resist. If you cannot answer, in plain language, what value you’re getting per unit of agent activity—per workflow, per resolved ticket, or per customer outcome—then you don’t have an AI strategy; you have a spending strategy. Agentic AI will punish organizations that treat the cloud as an infinite sandbox and success metrics as a slide deck.

Good architecture is crucial

The industry’s favorite myth is that architecture slows innovation. In reality, architecture prevents innovation from turning into entropy. Agentic AI accelerates entropy by generating more actions, integrations, permissions, data movement, and operational variability than human-driven systems typically do.

Planning for agentic AI systems means designing boundaries agents cannot cross, defining tool contracts they must obey, and creating “safe failure” modes that degrade gracefully rather than improvising into catastrophe. It also means thinking through data architecture with new seriousness: where context comes from, how it is governed, how it is retained, and how to prevent agents from leaking sensitive information through perfectly reasonable tool usage. You’re not just building an app; you’re building an autonomous operating model that happens to be implemented in software.

Good architecture here is pragmatic, not academic. It focuses on reference patterns, standardized environments, consistent identity and policy enforcement, deterministic workflows when possible, and explicit exception paths when autonomy is allowed. Most importantly, it recognizes an agent as a new runtime consumer of your cloud platform, requiring a design approach that accounts for this instead of adding agents to old assumptions.

Discipline and responsibility

Agentic AI has raised the operational bar for responsible cloud computing. Networking must become more policy-driven and observable to support autonomous, tool-using traffic patterns. Security must become more identity-centric because the actor is now software that can operate like a human administrator. Finops must transition into real-time governance because agents can consume resources at machine speed. Architecture must lead, not follow, because the cost of unplanned autonomy is failure at scale.

If you want the blunt takeaway, it’s this: Agentic AI makes cloud discipline non-negotiable. The organizations that treat it as an architectural and operational shift will do well, and the ones that treat it as another feature to turn on will learn quickly how expensive improvisation can be.

(image/jpeg; 1.29 MB)

Python picks up speed with a new JIT 23 Jan 2026, 9:00 am

Faster Python is now within reach, thanks to its shiny new JIT. But we also have fast dataframes thanks to Pandas, and three slick new GUI interfaces for SQLite. And then there’s Zed, the new Rust-powered contender to VS Code’s throne. It’s a busy time in the world of Python, and we’ve got all the scoops.

Top picks for Python readers on InfoWorld

How to use Pandas for data analysis in Python
For working with data tables in Python, look no further than Pandas, the fast and universal dataframe solution. With version 3 on the way, now’s the time to learn what to expect.

Get started with Python’s new native JIT
Python’s most potentially game-changing new feature (of late) is the JIT compiler. It promises to add a performance boost to code with no extra work on your part, but do the promises add up? Let’s check the benchmarks and find out.

Get a GUI for SQLite—actually, get three!
Quit poking through SQLite databases at the command line or via clunky scripts. We found three GUI interfaces that provide desktop, web, and VS Code add-ons so you can explore your data in style.

Zed: The Rust-powered challenger to VS Code
Could a platform-native IDE and editor written in Rust be the next big challenger to Visual Studio Code? This video lets you get a feel for hands-on work with Zed.

More good reads and Python updates elsewhere

PyCrucible 0.4 released
One of the best new solutions for redistributing Python apps painlessly now runs faster and can deliver much smaller downloads.

On the future of funding the Python Software Foundation
Deb Nicholson, executive director of the Python Software Foundation, talks about what it will take to keep the PSF funded in the years to come, including how software nonprofits can remain solvent in tough times.

How we made Python’s packaging library 3x faster
This is a great case study for how, among other things, Python’s new statistical profiler (in 3.15) can yield big wins by revealing unexpected bottlenecks. There’s also a nice sidebar on how to take advantage of post-3.11 regex features for performance.

Slightly off-topic: Extracting books from production language models
It’s easier than you think to trick an LLM into revealing most of a text it’s been trained on. And this trick even works with state-of-the-art production LLMs that theoretically guard against it.

(image/jpeg; 0.26 MB)

JetBrains IDEs integrate OpenAI Codex 23 Jan 2026, 2:41 am

OpenAI has made its Codex AI coding agent available directly inside JetBrains IDEs, enabling developers to plan, write, test, review and deploy code without leaving their editor. OpenAI and JetBrains announced this move on January 22.

With Codex now natively integrated into JetBrains AI chat, developers now can collaborate with Codex directly within a JetBrains IDE, starting with version 2025.3. Codex can be used with a JetBrains AI subscription, a ChatGPT account, or an OpenAI API key, all within the same AI сhat interface. Specific IDEs supporting this capability include JetBrains’s IntelliJ, PyCharm, WebStorm, and Rider.

Codex in JetBrains IDEs is powered by the GPT-5.2-Codex coding model from OpenAI. This model can undertake complex tasks such as large refactors, code migrations, and feature builds. GPT-5.2-Codex is positioned as OpenAI’s most advanced coding model, with significantly stronger cybersecurity capabilities, helping teams find vulnerabilities, reason about exploits, and harden security systems at scale, according to OpenAI.

Using Codex, developers can delegate real coding tasks from within an IDE and let the agent reason, act, and iterate alongside them. Codex supports various interaction modes, with users able to decide how much autonomy to give it—from simple question-response permissions to the ability to access a network and run commands autonomously. Users can switch between supported OpenAI models and their reasoning budget directly in the AI chat, making it easy to balance reasoning depth, speed, and cost depending on the task at hand.

The Codex agent is available for free for a limited time when accessed via JetBrains AI, including the free trial or free tier version. The promotion starts on January 22 and will remain available until allocated promotional credits have been used up. This free offer does not apply when using a ChatGPT account or an OpenAI API key, JetBrains said.

(image/jpeg; 8.71 MB)

Rust 1.93 updates bundled musl library to boost networking 22 Jan 2026, 10:56 pm

The Rust team has unveiled Rust 1.93, the latest version of the programming language designed to create fast and safe system-level software. This release improves operations involving the DNS resolver for the musl implementation of the  C standard library. Linux binaries are expected to be more reliable for networking as a result.

Rust 1.93 was introduced January 22. Developers with previous versions of Rust installed via rustup can upgrade by running rust update stable.

With Rust 1.93, *-linux-musltargets will ship with musl 1.2.5. This mostly affects static musl builds for x86_64, aarch64, and powerpc64le, which bundled musl 1.2.3, the Rust team said. For the Rust ecosystem, the primary motivation for this update is to receive major improvements to musl’s DNS resolver that shipped in release 1.2.4 and received bug fixes in release 1.2.5. When using musl targets for static linking, the update should make portable Linux binaries that do networking more reliable, particularly in the face of large DNS records and recursive name servers.

However, the updated musl library also comes with a breaking change: the removal of several legacy compatibility symbols that the Rust libc crate was using. A fix for this was shipped in libc 0.2.146 in June 2023 (2.5 years ago). The team believes this fix has been widely enough propagated, so the team is ready to make the change in Rust targets.

Additionally, Rust 1.93 adjusts the internals of the standard library to permit global allocators written in Rust to use std’s thread_local! and std::thread::current with no re-entrancy concerns by using the system allocator instead, the Rust team said. Also in Rust 1.93, a cfg attribute now can be applied to individual statements within the asm!block. The cfg attribute conditionally includes the form to which it is attached based on a configuration predicate.

Finally, Rust 1.93 stabilizes 23 APIs. Rust 1.93 follows last month’s release of Rust 1.92, which made future compatibility lints deny-by-default, so they would cause a compilation error when detected.

(image/jpeg; 29.91 MB)

MuleSoft gains Agent Scanners to rein in enterprise AI chaos 22 Jan 2026, 1:00 pm

Salesforce has added a new feature, Agent Scanners, to its integration platform, MuleSoft. Agent Scanners is part of Agent Fabric, a suite of capabilities and tools that the company launched last year to rein in the growing challenge of agent sprawl across enterprises.

Agent sprawl, often a result of enterprises and their technology teams adopting multiple agentic products, can lead to the fragmentation of agents, turning their workflows redundant or siloed across teams and platforms.

This fragmentation more often than not undermines operational efficiency and complicates governance, making it significantly harder for enterprises to scale AI safely and responsibly.

MuleSoft’s Agent Scanners is designed to help enterprises discover agents across diverse environments, such as Copilot, Vertex AI, Bedrock, and Agentforce.

After detecting the new agents, the scanners automatically synchronize the agents and their metadata with Agent Registry, which in turn can be used to make the agents discoverable by other agents or developers, the company said.

Agent Registry is one of the many tools inside Agent Fabric, and it acts as the centralized directory that catalogues the capabilities, metadata, and endpoints of both in-house and third-party agents. Other tools inside Agent Fabric include Agent Broker, Agent Visualizer, and Agent Governance.

Simple yet foundational for CIOs

Agent Scanners’ automated agent discovery ability, although deceptively simple, could be more foundational for CIOs trying to adopt agents in production use cases.

“For CIOs and security leaders, the biggest issue today isn’t deploying agents, it’s understanding what’s already running. Many enterprises struggle to answer basic questions like how many agents exist, where they’re deployed, which models they use, and what data they can access. Agent Scanner directly tackles that visibility gap,” said Robert Kramer, principal analyst at Moor Insights and Strategy.

CIOs can also use the tool to cut down on fragmentation, Kramer noted, adding that teams in enterprises often build agents in isolation, duplicating effort because they don’t know what already exists elsewhere internally.

Agent Scanners’ significance, however, extends beyond its appeal to CIOs and security leaders, particularly as the pace of agent creation accelerates across large enterprises.

Stephanie Walter, practice leader for the AI stack at HyperFRAME Research, said the capability is also foundational to the original goal of Agent Fabric itself: curbing agent sprawl rather than just documenting it.

“Manual tracking is already failing. I expect so many agents to be created in the near future that a manual registry would be obsolete within weeks. Without an automated scanner, an enterprise’s Agent Registry becomes a stale spreadsheet that fails to account for the shadow AI being built in various cloud silos,” Walter added.

Metadata extraction to provide more visibility

Further, analysts said Agent Scanners’ ability to automatically read and document agents’ metadata could give CIOs a more practical way to maintain visibility as agent deployments scale, since simply knowing that an agent exists does little to support governance, cost optimization, or reuse.

“The real value comes from understanding context — what the agent can do, which LLM it uses, and what data it’s authorized to touch,” Kramer said.

“Agent Scanner’s metadata extraction adds that depth, making it easier for security teams to assess risk, for architects to identify overlap or consolidation opportunities, and for developers to safely connect agents. That shifts agent management from static inventory tracking to something that supports real operational decisions,” Kramer added.

Seconding Kramer, Walter pointed out that the same metadata can then be standardized into Agent-to-Agent (A2A) card formats, making identifying and trusting agents easier.

Agent Scanners is currently in preview, and MuleSoft expects the capability to be made generally available towards the end of this month.

(image/jpeg; 6.88 MB)

AI agents and IT ops: Cowboy chaos rides again 22 Jan 2026, 9:00 am

In a traditional IT ops culture, sysadmin “cowboys” would often SSH into production boxes, wrangling systems by making a bunch of random and unrepeatable changes, and then riding off into the sunset. Enterprises have spent more than a decade recovering from cowboy chaos through the use of tools such as configuration management, immutable infrastructure, CI/CD, and strict access controls. But, now, the cowboy has ridden back into town—in the form of agentic AI.

Agentic AI promises sysadmins fewer manual tickets and on‑call fires to fight. Indeed, it’s nice to think that you can hand over the reins to a large language model (LLM), prompting it to, for example, log into a server to fix a broken app at 3 a.m. or update an aging stack while humans are having lunch. The problem is that an LLM is, by definition, non‑deterministic: Given the same exact prompts at different times, it will produce a different set of packages, configs, and/or deployment steps to perform the same tasks—even if a particular day’s run worked fine. This would hurtle enterprises back to the proverbial O.K. Corral, which is decidedly not OK.

I know, first-hand, that burning tokens is addictive. This weekend, I was troubleshooting a problem on one of my servers, and I’ll admit that I got weak, installed Claude Code, and used it to help me troubleshoot some systemd timer problems. I also used it to troubleshoot a problem I was having with a container, and with validating an application with Google. It’s so easy to become reliant on it to help us with problems on our systems. But, we have to be careful how far we take it.

Even in these relatively early days of agentic AI, sysadmins know it’s not a best practice to set an LLM off on production systems without any kind of guardrails. But, it can happen. Organizations get short-handed, people get pressured to do things faster, and then desperation sets in. Once you become reliant on an AI assistant, it’s very difficult to let go.

Rely on agentic AI for non-deterministic tasks

What sysadmins need to start thinking about is balancing their use of AI among deterministic and non-deterministic tasks—using AI for non‑deterministic work and then forcing everything important back into the deterministic world.

Non‑deterministic work is the exploratory, ambiguous, “figure it out” side of engineering—searching the Internet, reconciling docs, experimenting with different config patterns, sketching out playbooks or Dockerfiles. Deterministic work is what actually, effectively, purposely, and safely runs your business at scale—the scripts, container images, and pipelines that behave the same way every time across tens or hundreds or thousands of systems.

Retrieval-augmented generation (RAG), agent frameworks, and tool‑calling models all exist to reconnect a drifting, probabilistic model to grounded, deterministic data and systems. Whether the model is hitting a vector database, an API, a ticketing system, or a calculator, the protocol should be the same: Let the LLM reason in a fuzzy space, then anchor its output in something that behaves predictably when executed. Enterprises that blur that boundary—by letting the probabilistic part touch production directly—are inviting cowboy-level chaos.

What to build (and not to build) with agentic AI

The right pattern is not “AI builds the environment,” but “AI helps design and codify the artifact that builds the environment.” For infrastructure and platforms, that artifact might be a configuration management playbook that can install and harden a complex, multi‑tier application across different footprints, or it might be a Dockerfile, Containerfile, or image blueprint that can be committed to Git, reviewed, tested, versioned, and perfectly reconstructed weeks or months later.

What you don’t want is an LLM building servers or containers directly, with no intermediate, reviewable definition. A container image born from a chat prompt and later promoted into production is a time bomb—because, when it is time to patch or migrate, there is no deterministic recipe to rebuild it. The same is true for upgrades. Using an agent to improvise an in‑place migration on a one‑off box might feel heroic in the moment, but it guarantees that the system will drift away from everything else in your environment.

The outcomes of installs and upgrades can be different each time, even with the exact same model, but it gets a lot worse if you upgrade or switch models. If you’re supporting infrastructure for five, 10, or 20 years, you will be upgrading models. It’s hard to even imagine what the world of generative AI will look like in 10 years, but I’m sure Gemini 3 and Claude Opus 4.5 will not be around then.

The dangers of AI agents increase with complexity

Enterprise “applications” are no longer single servers. Today they are constellations of systems—web front ends, application tiers, databases, caches, message brokers, and more—often deployed in multiple copies across multiple deployment models. Even with only a handful of service types and three basic footprints (packages on a traditional server, image‑based hosts, and containers), the combinations expand into dozens of permutations before anyone has written a line of business logic. That complexity makes it even more tempting to ask an agent to “just handle it”—and even more dangerous when it does.

In cloud‑native shops, Kubernetes only amplifies this pattern. A “simple” application might span multiple namespaces, deployments, stateful sets, ingress controllers, operators, and external managed services, all stitched together through YAML and Custom Resource Definitions (CRDs). The only sane way to run that at scale is to treat the cluster as a declarative system: GitOps, immutable images, and YAML stored somewhere outside the cluster, and version controlled. In that world, the job of an agentic AI is not to hot‑patch running pods, nor the Kubernetes YAML; it is to help humans design and test the manifests, Helm charts, and pipelines which are saved in Git.

Modern practices like rebuilding servers instead of patching them in place, using golden images, and enforcing Git‑driven workflows have made some organizations very well prepared for agentic AI. Those teams can safely let models propose changes to playbooks, image definitions, or pipelines because the blast radius is constrained and every change is mediated by deterministic automation. The organizations at risk are the ones that tolerate special‑case snowflake systems and one‑off dev boxes that no one quite knows how to rebuild. The environments that still allow senior sysadins and developers to SSH into servers are exactly the environments where “just let the agent try” will be most tempting—and most catastrophic.

The quiet infrastructure advantage

The organizations that will survive the agent hype cycle are the ones that already live in a deterministic world. Their operating model assumes you do not poke at production by hand; you declare the desired state, you automate the path to get there, and you repeat it across thousands of systems without drama. In that kind of environment, AI shows up at build time and design time, not as an ungoverned runtime actor improvising in front of customers.

The real prize is not another shiny “AI agent for your infrastructure” banner. It is an opinionated stack that refuses to let AI touch production except through artifacts that can be tested, audited, and rerun on demand. That stack quietly protects enterprises from their own worst impulses: from the desperate developer at a startup who is tempted to give an LLM shell access, to the overworked sysadmin staring down a terrifying upgrade window on a legacy box. In that world, AI does what it does best—explore, analyze, propose—while the underlying platform does what it must: keep the cowboys, human or machine, out of production!

New Tech Forum provides a venue for technology leaders—including vendors and other outside contributors—to explore and discuss emerging enterprise technology in unprecedented depth and breadth. The selection is subjective, based on our pick of the technologies we believe to be important and of greatest interest to InfoWorld readers. InfoWorld does not accept marketing collateral for publication and reserves the right to edit all contributed content. Send all inquiries to doug_dineley@foundryco.com.

(image/jpeg; 3.36 MB)

TypeScript levels up with type stripping 22 Jan 2026, 9:00 am

TypeScript is usually described as a superset of JavaScript, meaning all valid JavaScript is also valid TypeScript. With a few notable exceptions (like Enums and namespaces), it is possible to go through a program, delete the type information, and arrive at a perfectly legitimate JavaScript program. This is type stripping, an alternative to transpilation.

Now there’s a move to add type stripping to the core language, which would make it even easier to run your TypeScript programs as JavaScript.

Similar to type erasure in Java, type stripping would make it possible to execute a cheap text replacement of type information at runtime, rather than a heavier compile step later. Modern runtimes like Deno and Bun have supported this capability natively for some time, but type stripping really hit the enterprise mainstream in Node.js.

Starting in Node 22.6, released early last year, the JavaScript runtime can execute TypeScript directly. Node’s --experimental-strip-types flag erases, on the fly, all the parts of a TypeScript program that are not compatible with Node.

We’ll start with a look at how this feature works in Node, then discuss the ramifications of adding something similar to TypeScript.

Type stripping in Node

Consider the following TypeScript program:

// animal.ts
interface Animal {
  name: string;
  winged: boolean;
}

function move(creature: Animal): string {
  if (creature.winged) {
    return `${creature.name} takes flight.`;
  }
  return `${creature.name} walks the path.`;
}

const bat: Animal = {
  name: "Bat",
  winged: true
};

console.log(move(bat));

If we try to run this directly in Node, we get an error:

$ node animal.ts
C:\Users\matth\node\animal.ts:1
interface Animal {
          ^^^^^^

SyntaxError: Unexpected identifier 'Animal'

But if we run it with the new --experimental-strip-types flag, it works:

$ node --experimental-strip-types animal.ts
Bat takes flight.

Type stripping removes all the TypeScript-specific syntax, leaving something like the following:

// The interface is gone (replaced by whitespace)
                                  //
                                  //
                                  //

function move(creature) {         // ': Animal' and ': string' are stripped
  if (creature.winged) {
    return `${creature.name} takes flight.`;
  }
  return `${creature.name} walks the path.`;
}

const bat = {                     // ': Animal' is stripped
  name: "Bat",
  winged: true
};

console.log(move(bat));

Node’s --experimental-strip-types flag has inspired changes to the TypeScript spec itself, starting with the new erasableSyntaxOnly flag in TypeScript 5.8. Having the experimental flag available at runtime is one thing, but having it built into the language is quite another. Let’s consider the broader effects of this change.

No more source maps

For debugging purposes, it is essential that the types in our example are replaced with whitespace, not just deleted. That ensures the line numbers will naturally match-up between runtime and compile time. This preservation of whitespace is more than just a parser trick; it’s a big win for DX.

For years, TypeScript developers relied on source maps to translate the JavaScript running in the browser or server back to the TypeScript source code in their editor. While source maps generally work, they are notorious for being finicky. They can break and fail to map variables correctly, leading to problems where the line number in the stack trace doesn’t match the code on your screen.

With type stripping, the code running in Node is structurally identical to the code in your editor, line-for-line. Line 10 in your IDE is line 10 in the runtime. This eliminates the need for source maps during development, so the stack traces are always accurate, and your breakpoints always hit. Perhaps most importantly, having type stripping built into TypeScript eliminates an entire class of artifacts (source maps) from the build process.

This reinforces the realization that type information is not really a runtime factor but one that matters at development time. We want the guardrails in place while we are coding in the IDE, but after that, we can replace types with whitespace. Then the program can just run—with no build or compile step required.

What we lose to type stripping

With any change like this, there will be casualties. Other than source maps (which few will miss) type stripping in TypeScript mainly affects features that are not amenable to erasure:

  • Enums
  • Namespaces
  • Class parameter properties
  • import =

While some say these features are outside of TypeScript’s scope, they are all valid TypeScript constructs. They cannot be directly whitespaced out and require a compilation step to translate into valid JavaScript; therefore, the flag to enable only erasable syntax will throw an error when encountering them.

The TypeScript 5.8 announcement showed the following errors when using the flag:

// ❌ error: A namespace with runtime code.
namespace container {
    foo.method();

    export type Bar = string;
}

// ❌ error: An `import =` alias
import Bar = container.Bar;

class Point {
    // ❌ error: Parameter properties
    constructor(public x: number, public y: number) { }
}

// ❌ error: An enum declaration.
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

Most of these are self-evident, but it’s worth noting that in parameter properties, the problem is that they require the compiler to inject actual assignment logic (this.x = x) into the constructor, which a simple “strip” operation cannot do.

The ‘Bridge of Zod’

It isn’t new for TypeScript to lose the type information by the time it’s running as JavaScript. It is either removed by the compiler or by stripping. This creates a problem if you need access to type information (for example, if you need to check that a request parameter is a string). The Zod library addresses the problem, and also provides a simple replacement for Enum.

Because type stripping aggressively removes all type information, it underscores that TypeScript cannot validate your API responses or user inputs at runtime. If you define an interface, Animal, that interface ceases to exist the moment Node runs your file.

This is where libraries like Zod can be the perfect partner to type stripping.

Since Zod schemas are defined using standard JavaScript objects and functions, they survive the stripping process completely intact. They provide the runtime safety that TypeScript “types as comments” cannot.

Also, Zod offers a direct solution to the casualties I mentioned above, particularly Enums. Since TypeScript Enums are banned in a type-stripping environment (because they generate code), developers have used Zod Enums instead. They exist as real JavaScript objects at runtime, but  they can still export the static type definitions your IDE loves.

In that case, the workflow might look something like this:

  1. Define a Zod schema (the runtime JavaScript stays).
  2. Infer a TypeScript type from that schema (the static TypeScript is stripped).
  3. Run the code without a build step, knowing your validation logic is still there.

Let’s run through a quick example to see how this works. In the code below, Zod “infers” the type at runtime, using JavaScript, and then exposes a TypeScript type at “type-checking time” (like in the IDE). To start, here’s a Zod schema:

const AnimalSchema = z.object({ 
  name: z.string(), 
  winged: z.boolean(), 
});

Note that the schema is just a JavaScript object with special functions used for validating instances. This object itself gives you everything you need for the runtime checks. To handle the compile-time, you add a line like so:

type Animal = z.infer;

This line will be removed by the type-stripper. This is a very clever piece of engineering; it boils down the whole role of TypeScript, enforcing the Animal type to a single line that smoothly bridges between compile time and runtime.

Type stripping and the future of JavaScript

Type stripping has all kinds of interesting ramifications, including for the future of JavaScript, as the JavaScript design team continues to contemplate absorbing type definitions (in one form or another) into the language itself.

Efforts have been underway for some time to make JavaScript do types. Most notably, the TC39 proposal, officially “Type Annotations,” also known as “Types as Comments.” The current era of type stripping is something of a bridge toward the possibility paid out by TC39. The JavaScript types proposal is still in stage 1, but changes to how we use TypeScript in practice could reawaken its ideas.

The basic idea in the type annotations proposal is very similar to type stripping (and comes with the same caveats for things like Enum), but instead of stripping, the idea is to comment out the type info. The runtime engine entirely ignores the type syntax, while the development-time engine (the IDE or linter) uses it to enforce types.

It’s worth noting that the JavaScript proposal has more than just TypeScript in mind. It also explicitly mentions the Closure compiler and Flow as targets. The end result would likely be the replacement of all three technologies with JavaScript.

As the specification correctly notes, the desire for static types in JavaScript has consistently ranked as the most in-demand “missing feature” in the annual State of JavaScript surveys.

The browser gap

Server-side runtimes like Node, Deno, and Bun are embracing type stripping but web browsers cannot yet embrace it. Both Chrome and Safari will crash the moment they encounter a type annotation.

For now, this creates a split in the ecosystem: A “no-build” utopia for the back end, but a continued reliance on build tools like Vite or webpack for the front end. This is exactly why the TC39 proposal for JavaScript is the final piece of the puzzle. Until browsers can natively ignore type syntax, universal type stripping remains out of reach. (This is a bit reminiscent of when the browser and server diverged on import syntax.)

Type stripping and the ‘no build’ future

Ultimately, type stripping is about much more than a Node flag or even a TypeScript feature. It represents a shift in how we view our tools. For a decade, developers have accepted that enterprise-grade JavaScript requires a heavy, complex build pipeline.

Features like --experimental-strip-types and the TC39 JavaScript proposal challenge that assumption. They point toward a future where the friction between writing code and running it is greatly attenuated. By treating types as useful dev-time comments, rather than compiler instructions, we get the safety we need while reducing the burden of complexity. That is a major level up for TypeScript, and for the technologies that will follow.

(image/jpeg; 14.73 MB)

jQuery 4.0.0 JavaScript library features trusted types 22 Jan 2026, 12:28 am

Version 4.0.0 of the still-widely-used jQuery JavaScript library is now available. Celebrated as the first major release in nearly 10 years, jQuery 4.0.0 features support for trusted types and a new, slimmer build.

Announced January 17, the newest version of the jQuery JavaScript library can be downloaded from jquery.com.  Trusted types in jQuery 4.0.0 ensure that HTML in the TrustedHTML interface can be input to jQuery manipulation methods in compliance with a browser’s Content Security Policy (CSP) required-trusted-types-for directive. In addition, while some AJAX requests already were using tags to maintain attributes such as crossdomain, jQuery’s builders have switched most asynchronous script requests to use to avoid any CSP errors caused by inline scripts. There still are a few cases where XHR is used for asynchronous script requests, such as when the "headers" option is passed, but tag is used whenever possible.

jQuery 4.0.0 also debuts with a slimmer build, with the removal of deferred objects and callbacks. Deferreds have long-supported the Promises A+ standard for interoperable JavaScript promises; however, in most cases, native promises, available in all jQuery-supported browsers but IE 11, can be used. And while deferred objects have some extra features that native promises do not support, most usage can be migrated to Promise methods, according to the announcement. For developers who must support IE 11, it is best to use the main build or add a polyfill for native promises. IE 10 and older versions are not supported in jQuery 4.0.0.

Now 20 years old, jQuery is still used by 70.9% of all websites, according to web technology surveyor W3Techs. Now under the jurisdiction of the OpenJS Foundation, jQuery is intended to simplify capabilities such as HTML document traversal and manipulation, event handling, and animation via an API that works across a multitude of browsers. Other highlights of jQuery 4.0.0 include the following:

  • Focus event order now follows the World Wide Web Consortium (W3C) specification, bringing jQuery in line with the event order supported in the latest versions of most browsers. This event order differs from the order used in older versions of jQuery, making it a breaking change. Starting with jQuery 4.0.0, the library no longer supports override native behavior, and will follow the current W3C specification: blur, focusout, focus, focusin.
  • Internal-only methods were removed from the jQuery prototype. This prototype had Array methods that did not behave like other jQuery methods and were intended only for internal use. Developers who were using the removed push, sort, and splice methods can replace $elems.push( elem ) with [].push.call( $elems, elem ).
  • With the release of jQuery 4.0.0, jQuery 3.x now will receive only critical updates.

(image/jpeg; 2.14 MB)

GitLab 2FA login protection bypass lets attackers take over accounts 21 Jan 2026, 11:59 pm

A critical two-factor authentication bypass vulnerability in the Community and Enterprise editions of the GitLab application development platform has to be patched immediately, say experts.

The hole is one of five vulnerabilities patched Wednesday as part of new versions of GitLab. Three are ranked High in severity, including the 2FA bypass issue, while the other two are ranked Medium in severity.

GitLab says the 2FA hole, CVE-2026-0723, if exploited on an unpatched system, could allow an individual with knowledge of a victim’s ID credentials to bypass two-factor authentication by submitting forged device responses.

It’s this hole that has drawn the attention of experts, because of the implications.

The goal of multifactor authentication is to protect login accounts with an extra verification step in case usernames and passwords are stolen. If a threat actor can access an account, they can do almost unlimited damage to IT systems.

In the case of GitLab, if critical code is sitting in a developer’s account, a threat actor could compromise it, notes David Shipley, head of Canadian-based security awareness training firm Beauceron Security. If that code is to be used in software that can be downloaded or sold to other organizations, then inserted malware could be spread in a supply chain attack. The latest example, Shipley said, is the Shai-Hulud worm, which is spreading because a developer’s account in the npm registry was hacked.

If the code contains cloud secrets, he added, the threat actor could gain access to cloud platforms like Azure, Amazon Web Service, or Google Cloud Platform.

Discovery of the 2FA bypass hole “is a reminder that these [security] controls are important,” Shipley said in an interview. “They absolutely help reduce a number of risks: Brute force attacks, password spraying, and so forth. But they will never be infallible.

“This is not the first time someone has found a clever way to get around 2FA challenges. We have a whole series of attacks around session cookie capture which are also designed to defeat 2FA. So it’s important to remember this when someone drops some Silver Bullet thinking that ‘This magic solution solves it [authentication]’ or ‘That’s the bad MFA. Here’s the new MFA.’ And I include [trusting only] Yubikeys,” he said. “Yubikeys are amazing. They’re the next generation of 2FA. But because they are made for humans, eventually they will have some flaws.”

Even if there weren’t flaws in these controls, employees might be tricked into giving up credentials through social engineering, he added.

It would be easier for an attacker to use techniques like phishing to collect user credentials rather than forge a device credential to exploit this particular 2FA bypass, said Johannes Ullrich, dean of research at the SANS Institute. But, he added, once the attacker has access to valid passwords, they can log in to the GitLab server and perform actions on the source code — download it, alter it or delete it — just as a legitimate user would.

What infosec leaders need to do

This is why Cybersecurity 101 — layered defense — is vital for identity and access management, Shipley said. That includes forcing employees to have long, unique login passwords, monitoring the network for unusual activity (for example, if someone gets in without an MFA challenge recorded) and, in case all fails, an incident response plan.

MFA bypass vulnerabilities are very common, noted Ullrich. “The core problem is usually that MFA was added later to an existing product,” he said, “and some features may not properly check if MFA was successfully completed.”

When testing a multifactor authentication solution, infosec leaders should always verify that an application has not marked authentication as completed after the username and password were verified. Enabling MFA should not relax password requirements, he asserted. Users must still pick unique, secure passwords and use password managers to manage them. Secure passwords will mostly mitigate any MFA failures, Ullrich said.

Any vulnerability found in GitLab is significant, he added. GitLab is typically used by organizations concerned enough about the confidentiality of their code that they want to run the platform on premises. 

GitLab ‘strongly’ recommends upgrades

In describing the patches released Wednesday, GitLab said it “strongly” recommends all self managed GitLab installations be upgraded to one of the three new versions (18.8.2, 18.7.2, 18.6.4) for GitLab Community Edition (CE) and Enterprise Edition (EE). Those using GitLab.com or GitLab Dedicated –  a single tenant software-as-a-service version –  don’t have to take any action.

The other vulnerabilities fixed in Wednesday’s updates are:

  • CVE-2025-13927, a denial of service issue in Jira Connect integration. If exploited on an unpatched system, it could allow an unauthenticated user to create a denial of service condition by sending crafted requests with malformed authentication data. It carries a CVSS severity score of 7.5;
  • CVE-2025-13928, an incorrect authorization issue. If exploited on an unpatched system, it could allow an unauthenticated user to cause a denial of service condition by exploiting incorrect authorization validation in API endpoints.  It carries a CVSS severity score of 7.5;
  • CVE-2025-13335, an infinite loop issue in Wiki redirects. Under certain circumstances, this hole could allow an authenticated user to create a denial of service condition by configuring malformed Wiki documents that bypass cycle detection. It has a CVSS score of 6.5;
  • CVE-2026-1102 – a denial of service issue in an API endpoint that could allow an unauthenticated user to create a denial of service condition by sending repeated malformed SSH authentication requests. It has a CVSS score of 5.3.

In keeping with standard GitLab practice, details of the security vulnerabilities will be made public on an issue tracker 30 days after the release in which they were patched. 

The new versions also include bug fixes, some of which, GitLab said, may include database migrations. In cases of single-node instances, a patch will cause downtime during the upgrade. In the case of multi-node instances, admins who follow proper GitLab zero-downtime upgrade procedures can apply a patch without downtime.

This article originally appeared on CSOonline.

(image/jpeg; 1.19 MB)

How to use Pandas for data analysis in Python 21 Jan 2026, 9:00 am

When it comes to working with data in a tabular form, most people reach for a spreadsheet. That’s not a bad choice: Microsoft Excel and similar programs are familiar and loaded with functionality for massaging tables of data. But what if you want more control, precision, and power than Excel alone delivers?

In that case, the open source Pandas library for Python might be what you are looking for. Pandas augments Python with new data types for loading data fast from tabular sources, and for manipulating, aligning, merging, and doing other processing at scale.

Your first Pandas data set

Pandas is not part of the Python standard library. It’s a third-party project, so you’ll need to install it in your Python runtime with pip install pandas. Once installed, you can import it into Python with import pandas.

Pandas gives you two new data types: Series and DataFrame. The DataFrame represents your entire spreadsheet or rectangular data, whereas the Series is a single column of the DataFrame. In Python terms, you can think of the Pandas DataFrame as a dictionary or collection of Series objects. You’ll also find later that you can use dictionary- and list-like methods for finding elements in a DataFrame.

You typically work with Pandas by importing data from some other format. A common external tabular data format is CSV, a text file with values separated by commas. If you have a CSV handy, you can use it. For this article, we’ll be using an excerpt from the Gapminder data set prepared by Jennifer Bryan from the University of British Columbia.

To begin using Pandas, we first import the library. Note that it’s a common practice to alias the Pandas library as pd to save some typing:

import pandas as pd

To start working with the sample data in CSV format, we can load it in as a dataframe using the pd.read_csv function:

df = pd.read_csv("./gapminder/inst/extdata/gapminder.tsv", sep='t')

The sep parameter lets us specify that the file is tab-delimited rather than comma-delimited.

Once you’ve loaded the data, you can use the .head() method on the dataframe to peek at its formatting and ensure it’s loaded correctly. .head() is a convenience method used to display the first few rows of a dataframe for quick inspection. The results for the Gapminder data should look like this:

print(df.head())
       country continent  year  lifeExp       pop   gdpPercap
0  Afghanistan      Asia  1952   28.801   8425333  779.445314
1  Afghanistan      Asia  1957   30.332   9240934  820.853030
2  Afghanistan      Asia  1962   31.997  10267083  853.100710
3  Afghanistan      Asia  1967   34.020  11537966  836.197138
4  Afghanistan      Asia  1972   36.088  13079460  739.981106

Dataframe objects have a shape attribute that reports the number of rows and columns in the dataframe:

print(df.shape)
(1704, 6) # rows, cols

To list the names of the columns themselves, use .columns:

print(df.columns)
Index(['country', 'continent', 'year', 'lifeExp',
'pop', 'gdpPercap'], dtype='object')

Dataframes in Pandas work much the same way as they do in other languages, such as Julia and R. Each column, or Series, must be the same type, whereas each row can contain mixed types. For instance, in the current example, the country column will always be a string, and the year column is always an integer. We can verify this by using .dtypes to list the data type of each column:

print(df.dtypes)
country object
continent object
year int64
lifeExp float64
pop int64
gdpPercap float64
dtype: object

For an even more explicit breakdown of your dataframe’s types, you can use .info():

df.info() # information is written to console, so no print required

RangeIndex: 1704 entries, 0 to 1703
Data columns (total 6 columns):
 #   Column     Non-Null Count  Dtype
---  ------     --------------  -----
 0   country    1704 non-null   object
 1   continent  1704 non-null   object
 2   year       1704 non-null   int64
 3   lifeExp    1704 non-null   float64
 4   pop        1704 non-null   int64
 5   gdpPercap  1704 non-null   float64
dtypes: float64(2), int64(2), object(2)
memory usage: 80.0+ KB

Each Pandas data type maps to a native Python data type:

  • object is handled as a Python str type. (More on this below.)
  • int64 is handled as a Python int. Note that not all Python ints can be converted to int64 types; anything larger than (2 ** 63)-1 will not convert to int64.
  • float64 is handled as a Python float (which is a 64-bit float natively).
  • datetime64 is handled as a Python datetime.datetime object. Note that Pandas does not automatically try to convert something that looks like a date into date values; you must tell Pandas you want the conversion done for a specific column.

Any data that’s not a native Pandas type—essentially, anything that’s not a number—is stored as a generic NumPy type named object. If you have an object column in a dataframe, it’s worth making sure that data is not being used as part of any computational work, as you’ll get none of the performance benefits of using a numerical type (int64, float64, etc.).

Traditionally, strings have been represented as an object. As of Pandas 2.3 or higher, there’s an option to use a new dedicated str type, which has better Panda-native behaviors (such as a more explicit type for the data and more efficient storage). To enable this behavior, you’d use the command pd.options.future.infer_string = True at the top of your code.

Pandas columns, rows, and cells

Now that you’re able to load a simple data file, you want to be able to inspect its contents. You could print the contents of the dataframe, but most dataframes are too big to inspect by printing.

A better approach is to look at subsets of the data, as we did with df.head(), but with more control. Pandas lets you use Python’s existing syntax for indexing and creating slices to make excerpts from dataframes.

Extracting Pandas columns

To examine columns in a Pandas dataframe, you can extract them by their names, positions, or by ranges. For instance, if you want a specific column from your data, you can request it by name using square brackets:

# extract the column "country" into its own dataframe
country_df = df["country"]

# show the first five rows
print(country_df.head())
| 0 Afghanistan
| 1 Afghanistan
| 2 Afghanistan
| 3 Afghanistan
| 4 Afghanistan
Name: country, dtype: object

# show the last five rows
print(country_df.tail())
| 1699  Zimbabwe
| 1700  Zimbabwe
| 1701  Zimbabwe
| 1702  Zimbabwe
| 1703  Zimbabwe
| Name: country, dtype: object

If you want to extract multiple columns, pass a list of the column names:

# Looking at country, continent, and year
subset = df[['country', 'continent', 'year']]

print(subset.head())
       country continent  year
| 0  Afghanistan    Asia  1952
| 1  Afghanistan    Asia  1957
| 2  Afghanistan    Asia  1962
| 3  Afghanistan    Asia  1967
| 4  Afghanistan    Asia  1972

print(subset.tail())
         country continent    year
| 1699  Zimbabwe    Africa    1987
| 1700  Zimbabwe    Africa    1992
| 1701  Zimbabwe    Africa    1997
| 1702  Zimbabwe    Africa    2002
| 1703  Zimbabwe    Africa    2007

Subsetting rows

If you want to extract rows from a dataframe, you can use one of two methods.

.iloc[] is the simplest method. It extracts rows based on their position, starting at 0. For fetching the first row in the above dataframe example, you’d use df.iloc[0].

If you want to fetch a range of rows, you can use .iloc[] with Python’s slicing syntax. For instance, for the first 10 rows, you’d use df.iloc[0:10]. And if you wanted to obtain the last 10 rows in reverse order, you’d use df.iloc[::-1].

If you want to extract specific rows, you can use a list of the row IDs; for example, df.iloc[[0,1,2,5,7,10,12]]. (Note the double brackets—that means you’re providing a list as the first argument.)

Another way to extract rows is with .loc[]. This extracts a subset based on labels for rows. By default, rows are labeled with an incrementing integer value starting with 0. But data can also be labeled manually by setting the dataframe’s .index property.

For instance, if we wanted to re-index the above dataframe so that each row had an index using multiples of 100, we could use df.index = range(0, len(df)*100, 100). Then, if we used, df.loc[100], we’d get the second row.

Subsetting columns

If you want to retrieve only a certain subset of columns along with your row slices, you do this by passing a list of columns as a second argument:

df.loc[[rows], [columns]]

For instance, with the above dataset, if we want to get only the country and year columns for all rows, we’d do this:

df.loc[:, ["country","year"]]

The : in the first position means “all rows” (it’s Python’s slicing syntax). The list of columns follows after the comma.

You can also specify columns by position when using .iloc:

df.iloc[:, [0,2]]

Or, to get just the first three columns:

df.iloc[:, 0:3]

All of these approaches can be combined, as long as you remember loc is used for labels and column names, and iloc is used for numeric indexes. The following tells Pandas to extract the first 100 rows by their numeric labels, and then from that to extract the first three columns by their indexes:

df.loc[0:100].iloc[:, 0:3]

It’s generally least confusing to use actual column names when subsetting data. It makes the code easier to read, and you don’t have to refer back to the dataset to figure out which column corresponds to what index. It also protects you from mistakes if columns are re-ordered.

Grouped and aggregated calculations

Spreadsheets and number-crunching libraries all come with methods for generating statistics about data. Consider the Gapminder data again:


print(df.head(n=10))
|    country      continent  year  lifeExp  pop       gdpPercap
| 0  Afghanistan  Asia       1952  28.801    8425333  779.445314
| 1  Afghanistan  Asia       1957  30.332    9240934  820.853030
| 2  Afghanistan  Asia       1962  31.997   10267083  853.100710
| 3  Afghanistan  Asia       1967  34.020   11537966  836.197138
| 4  Afghanistan  Asia       1972  36.088   13079460  739.981106
| 5  Afghanistan  Asia       1977  38.438   14880372  786.113360
| 6  Afghanistan  Asia       1982  39.854   12881816  978.011439
| 7  Afghanistan  Asia       1987  40.822   13867957  852.395945
| 8  Afghanistan  Asia       1992  41.674   16317921  649.341395
| 9  Afghanistan  Asia       1997  41.763   22227415  635.341351

Here are some examples of questions we could ask about this data:

  1. What’s the average life expectancy for each year in this data?
  2. What if I want averages across the years and the continents?
  3. How do I count how many countries in this data are in each continent?

The way to answer these questions with Pandas is to perform a grouped or aggregated calculation. We can split the data along certain lines, apply some calculation to each split segment, and then re-combine the results into a new dataframe.

Grouped means counts

The first method we’d use for this is Pandas’s df.groupby() operation. We provide a column we want to split the data by:

df.groupby("year")

This allows us to treat all rows with the same year value together, as a distinct object from the dataframe itself.

From there, we can use the “life expectancy” column and calculate its per-year mean:


print(df.groupby('year')['lifeExp'].mean())
year
1952 49.057620
1957 51.507401
1962 53.609249
1967 55.678290
1972 57.647386
1977 59.570157
1982 61.533197
1987 63.212613
1992 64.160338
1997 65.014676
2002 65.694923
2007 67.007423

This gives us the mean life expectancy for all populations, by year. We could perform the same kinds of calculations for population and GDP by year:


print(df.groupby('year')['pop'].mean())
print(df.groupby('year')['gdpPercap'].mean())

So far, so good. But what if we want to group our data by more than one column? We can do this by passing columns in lists:


print(df.groupby(['year', 'continent'])
  [['lifeExp', 'gdpPercap']].mean())
                  lifeExp     gdpPercap
year continent
1952 Africa     39.135500   1252.572466
     Americas   53.279840   4079.062552
     Asia       46.314394   5195.484004
     Europe     64.408500   5661.057435
     Oceania    69.255000  10298.085650
1957 Africa     41.266346   1385.236062
     Americas   55.960280   4616.043733
     Asia       49.318544   5787.732940
     Europe     66.703067   6963.012816
     Oceania    70.295000  11598.522455
1962 Africa     43.319442   1598.078825
     Americas   58.398760   4901.541870
     Asia       51.563223   5729.369625
     Europe     68.539233   8365.486814
     Oceania    71.085000  12696.452430

This .groupby() operation takes our data and groups it first by year, and then by continent. Then, it generates mean values from the life-expectancy and GDP columns. This way, you can create groups in your data and rank how they are to be presented and calculated.

If you want to “flatten” the results into a single, incrementally indexed frame, you can use the .reset_index() method on the results:


gb = df.groupby(['year', 'continent'])
[['lifeExp', 'gdpPercap']].mean()
flat = gb.reset_index() 
print(flat.head())
|     year  continent  lifeExp    gdpPercap
| 0   1952  Africa     39.135500   1252.572466
| 1   1952  Americas   53.279840   4079.062552
| 2   1952  Asia       46.314394   5195.484004
| 3   1952  Europe     64.408500   5661.057435
| 4   1952  Oceana     69.255000  10298.085650

Grouped frequency counts

Something else we often do with data is compute frequencies. The nunique and value_counts methods can be used to get unique values in a series, and their frequencies. For instance, here’s how to find out how many countries we have in each continent:


print(df.groupby('continent')['country'].nunique()) 
continent
Africa    52
Americas  25
Asia      33
Europe    30
Oceana     2

Basic plotting with Pandas and Matplotlib

Most of the time, when you want to visualize data, you’ll use another library such as Matplotlib to generate those graphics. However, you can use Matplotlib directly (along with some other plotting libraries) to generate visualizations from within Pandas.

To use the simple Matplotlib extension for Pandas, first make sure you’ve installed Matplotlib with pip install matplotlib.

Now let’s look at the yearly life expectancies for the world population again:


global_yearly_life_expectancy = df.groupby('year')['lifeExp'].mean() 
print(global_yearly_life_expectancy) 
| year
| 1952  49.057620
| 1957  51.507401
| 1962  53.609249
| 1967  55.678290
| 1972  57.647386
| 1977  59.570157
| 1982  61.533197
| 1987  63.212613
| 1992  64.160338
| 1997  65.014676
| 2002  65.694923
| 2007  67.007423
| Name: lifeExp, dtype: float64

To create a basic plot from this, use:


import matplotlib.pyplot as plt
global_yearly_life_expectancy = df.groupby('year')['lifeExp'].mean() 
c = global_yearly_life_expectancy.plot().get_figure()
plt.savefig("output.png")

The plot will be saved to a file in the current working directory as output.png. The axes and other labeling on the plot can all be set manually, but for quick exports this method works fine.

Conclusion

Python and Pandas offer many features you can’t get from spreadsheets. For one, they let you automate your work with data and make the results reproducible. Rather than write spreadsheet macros, which are clunky and limited, you can use Pandas to analyze, segment, and transform data—and use Python’s expressive power and package ecosystem (for instance, for graphing or rendering data to other formats) to do even more than you could with Pandas alone.

(image/jpeg; 18.27 MB)

Page processed in 0.097 seconds.

Powered by SimplePie 1.4-dev, Build 20170403172323. Run the SimplePie Compatibility Test. SimplePie is © 2004–2026, Ryan Parman and Geoffrey Sneddon, and licensed under the BSD License.