What I learned by putting GitHub Copilot behind a MitM proxy
热度趋势
百分比基于当前可用热度信号,而非评论数或独立用户人数。
这条记录涉及编程工具或代码能力更新,适合开发者评估工作流变化和可复用价值。
Hello, Rafael here - every week I cover interesting challenges and developments that I’ve come across recently through the lens of an engineer building AI systems.
Subscribe to get weekly issues 👇
There has been a flurry of AI-powered apps and AI features in the last couple of years. Incumbent players like Slack have swiftly added AI features to its roster . For AI-native ones like Cursor, Notion, ChatGPT Desktop and Claude Desktop, AI was always part of the raison d’être.
The more AI features these apps released, the more I became inclined to look at their inner workings. Hopefully I would be able to uncover a bit of what’s running under the hood; at the very least, I would learn one thing or two about desktop app development.
Coincidentally, I noticed I started exhausting my Copilot credits earlier and earlier each month. This ended up pulling me towards selecting a main candidate for my experiments. I decided to dive deep into VS Code and Copilot.
Common amongst all of the apps above is the fact that they are built using Electron . Electron is a JavaScript framework which helps developers build and distribute desktop applications. In layman’s terms, it works by bundling a Node.js runtime along with HTML, CSS and JavaScript artifacts, which are then rendered via Chromium .
List of apps using Electron. I know, it’s a lot. Source
This removes the need of having multiple codebases in native languages for different platforms (for instance, C# for Windows and Swift for macOS), making it easier for developers to build desktop applications that run across multiple platforms from a single codebase. (Native modules and certain packaging steps still often require per-platform handling, but the bulk of the application logic is shared.)
Because they share Electron, they share a rough architecture, which means whatever I learned probing one should transfer to the others.
Lighthouse Newsletter is free :) support my work by sharing it with friends colleagues would be interested 👇
Share
My first instinct was to just skim through VS Code source and see if it could answer my questions. The problem was that I didn’t have a full set of questions yet - and hunting for them across millions of lines of code would cost me either too much time or too many tokens.
Source code tells you what an app can do; discovering what it actually does at runtime is more challenging. Especially when you still don’t know what you’re looking for.
There was a second problem. VS Code is an exception amongst the apps I had started with: its source code (or at least the majority of it) is open. This is not the case for Claude, ChatGPT, Codex, Notion, and Slack .
That started pushing me toward the reverse engineering route : passively watch the traffic first, let the requests and responses tell me which questions would be worth asking, and only then go to the source to confirm (or disprove) what I was seeing.
It meant getting my hands dirty with Electron’s architecture and network stack - skills that wouldn’t hurt to have afterwards.
By now we know that Electron apps ship with Chromium. The browser provides the rendering engine for the application’s web based UI, but it also provides a network stack that renderer processes can use for HTTP and WebSocket connections.
This is a common (and recommended) option for enabling apps to speak to a remote backend, but it is not the only one. Applications can also make HTTP requests using Node’s http/https/fetch . Which path the request takes becomes important when you’re trying to intercept it.
In some cases, like with VS Code, the application will have a decoupled architecture, where there’s a separate group of processes that acts as an extension host . This helps maintain clear boundaries between distinct responsibilities; in the case of VS Code, a clear boundary between UI, code IDE functionality and plugins/extensions.
One of the classic ways to intercept an application’s network traffic is by standing up a proxy server, and configuring this application to use it.
The proxy acts as a man-in-the-middle (MITM) : it intercepts HTTP requests from a client, forwards them to a server, and relays back the server responses to the client.
Fun fact: a similar approach is quite common in corporate network environments for traffic inspection purposes, especially in highly regulated industries. Fittingly, one of the main open source tools used for this is called mitmproxy , which we will use in the next steps.
An important detail is that most of the network traffic nowadays happens via secure HTTP (HTTPS). This means traffic is encrypted using TLS.
By trusting mitmproxy’s locally generated certificate authority (CA), the client can accept the certificates mitmproxy generates on the fly for each destination. Instead of a single end-to-end encrypted connection, you get two: one between the application and mitmproxy, and another between mitmproxy and the destination server.