Posts in Javascript (20 found)
Stratechery Yesterday

An Interview with OpenAI President Greg Brockman About Astra and Alignment

Listen to this post: Good morning, This week’s Stratechery interview is with OpenAI President and co-founder Greg Brockman . Brockman dropped out of college in 2010 to join Stripe, and rose to become the company’s CTO; he left in 2015 and co-founded OpenAI, where he also served as CTO. Today, after an interesting few years, Brockman is President of OpenAI, and is the face of yesterday’s announcement of Astra , OpenAI’s newest model. In this interview, recorded before the Astra announcement, we discuss Brockman’s background, his time at Stripe, and the early years of OpenAI. We touch on the ChatGPT launch and the drama of 2023, and whether or not having a billion users is actually a disadvantage. We also touch on OpenAI’s place on the value chain, and their competition with companies closer to consumers, like Microsoft, and their suppliers, like Nvidia. We also talk about Astra and OpenAI’s stated commitment to alignment, and debate whether or not OpenAI took security seriously in the run-up to the Hugging Face incident. As a reminder, all Stratechery content, including interviews, is available as a podcast; click the link at the top of this email to add Stratechery to your podcast player. On to the Interview: This interview is lightly edited for clarity. Greg Brockman, welcome to Stratechery. Greg Brockman: Thank you for having me. Excited to be here. So we obviously have a massive amount of news to get to, but given this is the first time we have talked, I don’t want to pass up the usual Stratechery biography question I ask anyone. I do want to ask — do you define North Dakota as being a part of the Midwest? All right, well, a fellow Midwesterner, of course I have to spend some time there. You went to school in Boston, as they say, but before we get to there — you have an amazing resume even before you get to school, like the International Olympiad , but in chemistry. Where did the computers come in, or were computers a part of your life from the beginning? GB: Well, computers were always in the background for me growing up. I loved to play computer games, but I was really into math, I was into science. I actually thought that I was going to potentially be an actor all the way through ninth grade — I was very into acting and performing as well, and dabbled a little bit in philosophy. There’s a curveball! I did not know that was coming, but I’m going to figure out what the connection is between what you do now and acting, but let’s continue. GB: Well, I felt like in ninth grade, I’d been the star of, or the male lead in, a play or two in my middle school, high school. And I was thinking about, I wanted to double down on something, I felt like I could be best in the world and really try to move the needle in a field, and I felt like I either had to pick a more cerebral, hard sciences approach or more of the arts and acting direction and creative route. I ended up picking the hard sciences one, because I felt like maybe that was an area where I could most make a difference in the world. And why did you think you could most make a difference in the world by going in that direction? GB: I guess for me it felt like — one of the things I loved about acting was actually the group aspect of it. I loved improv, you’re just creatively thinking about things, you’re bouncing ideas back and forth, but it also really requires being part of a team that works together super well, and that’s something that’s not always guaranteed. That’s a hard thing to accomplish and find. The thing that I really liked about the more cerebral route is it feels like you sharpen your own skills. One thing I did learn, actually, was that even if you’re great at writing code, that’s not enough. It is actually about also bringing in that great team, and that’s part of, I think, what my career has been about — really helping to build and shape environments and culture that are actually able to deliver great results. One thing that’s interesting, there’s an aspect here about environment also shaping some of these things. You mentioned you were always the male lead in plays and dramas. I just recognize from my kids going through this era — my daughter was very into musicals and stuff for a while — there’s intense competition for the female lead, and usually if there’s just a competent male who’s willing to volunteer, he gets the role every time. Was there a lot of competition for the male leads, or were you one of one? GB: (laughing) I think that might explain it. I’ll tell you a story, though. What about the flip side too? Being in North Dakota, were there not a lot of people super intense at the hard sciences, and so did that almost seem like a rarer thing by the same token? GB: Well, I’ll tell you two stories. So one on the acting front. My first ever paid job was an acting gig. Mannheim Steamroller was in town in Grand Forks, North Dakota. Are you familiar with Mannheim Steamroller? I am. Yes, absolutely. GB: So they were putting on a concert, and they needed extras. They needed people to be these tin soldiers to walk around, because it was a Christmas holiday concert. I went to the audition, and I was this scrawny ninth grader, and there were all these big college students there. What they told everyone to do is, “Okay, everyone march in that direction”, and then the casting people would compare notes and you’d have some downtime, then they’d say, “Okay, march in the other direction”. What I noticed is that all these college students during that downtime were talking to each other, hanging out, and I was like, this job has one requirement, which is you’re going to be six hours at attention the whole time walking around this concert. So during that downtime, I was there standing at attention, just being in character. At the end, they said, “Okay, we’re selecting this person, this person, this person. Everyone else can leave”. I was not picked. But on the way out, they said, “Actually, we thought you were amazing. We loved seeing how much you were dedicated to this, so we’re going to actually make a new role for you”. And so I got to be a gingerbread man, and they gave me a whole costume. And that was my first job. So it was a little bit of trying to be out of the box in order to try to get the job done — not always defaulting into the role, but trying to find creative ways to get it. But I think that when it came to growing up in North Dakota, one of the things that was really great was that it was possible for me to really excel and be the best in the state at different areas that I put my mind to. So I was advanced in math. I ended up going to University of North Dakota starting in 10th grade and taking a bunch of courses there. I got very into math competitions, and then I’d go to the national competition, I’d go to the national math camp, and there I would meet the best in the country. These people were so amazing, and actually, one thing that’s been a real privilege and honor is that many of the people that I really looked up to at math camp now work at OpenAI. So I’ve gotten to see them in this new field, this new light. That’s amazing. GB: But it was both that I could really chart my own course. I started doing math research, and I know that if I’d gone to some of these high-powered high schools or these much more competitive states, I think I wouldn’t have stood out. I would have had to be in the standard track. So it was by being in this area that I was able to explore my interest and really march to my own tune. So when people say they went to school in Boston, they usually mean Harvard, which is where you started. Then you switched to MIT. And then at some point you’re working for Stripe. What’s the sequence there? When did you meet the Collisons? What happened in Boston? GB: Well, after high school, I took a year off, and I actually started working on a chemistry textbook , because I’d gotten very into chemistry in high school, competitive chemistry, and come up with a unique way of thinking about it. Very first principles, very mathematical, rather than memorization. I wanted to teach that, I wanted to propagate that. So I actually wrote 100 pages. It’s on my website right now. I haven’t finished it. I’ve been intending to get back to it. That’s like a retirement project, I love it. GB: Exactly. Well, at this point, I think you can just ask Astra , and it’ll do a great job. But I was trying to figure out how do I get this thing published, so I asked one of my friends who had done something similar in math, and he said, “Well, you don’t have a PhD, so no one’s going to publish it. So you can either self-publish” — and I was like, oh, that’s a lot of work, a lot of capital — “or you can make a website and try to promote the ideas that way”. And I said, “I guess I’m going to learn how to code”. So I went on W3Schools . Do you remember W3Schools? Have you ever seen that website? No, I don’t think so. GB: Okay, so this is the classic — they have an HTML tutorial, JavaScript, CSS, PHP. I read through them and I was like, “I should test this out”. I remember I built a little first widget: you could click a table column, and it would sort the rows accordingly. It was the coolest feeling ever. I had this thing in my head that I was picturing, now it’s in the world, and anyone can benefit from it. They don’t need to understand the details behind it, it just works. I remember the very first thing I built that had users, it was actually a competitive chatbot game, and I got 1,500 hits from StumbleUpon one day. It was the most glorious feeling, there were 1,500 people who had played with my game, had hopefully enjoyed it, but they stuck around enough to play it. I was just like, “This is what I want, I want to help people, I want to benefit people and build for them”. So that’s what I showed up thinking I was going to do at Harvard, that really had changed for me. I thought I was going to do these more eclectic interests, and instead I was like, “I just want to build”. Freshman year at Harvard, I was in this computer club, there were these two seniors who would have obscure technical debates every single time. We would all listen and say, “One day we’ll understand, one day that will be us”. But then they graduated, and sophomore year came. So did you just switch over to MIT because you realized you had this focus on coding and building? GB: That’s basically right. Because sophomore year, I was running the club. I was supposed to be having the obscure technical debates, and I was like, “I’m not ready. I have so much to learn. I need to be around people who are so much better than me”. GB: And so I spent so much time down at MIT, and I was like, it just makes sense to transfer. Got it. So when did you meet the Collisons then? GB: So I met them in 2010, late 2010. We had a lot of mutual friends, because John had gone to Harvard, Patrick had gone to MIT, and they were poking around. That team was poking around trying to find who’s into computers at either of these schools, and my name kept coming up. GB: So I got a reach out from the team, and I flew out. And I remember meeting Patrick, really, for me, was the moment I was like, “All right, this is someone I want to work with, I feel like we could build something great together”. So my next question was what attracted you to Stripe , but it sounds like you just answered it. What did you learn there? You were pretty early on the team, progressed very rapidly. By the time you left, you were CTO. What was the takeaway for you from Stripe itself and Stripe scaling, but also yourself growing so rapidly inside this company that is itself growing rapidly? GB: First of all, for me, it’s always been about the people. I knew that these were people that I wanted to work with, that it felt like we could learn together, we could accomplish something great, and so that was a real key. And by the way, dropping out of school twice is something that I do not wish on anyone’s parents. It definitely was something that was difficult for mine, but they actually were very supportive in the end. No, we’re getting the idea, you take things to the extreme, right? Most founders drop out once, you had to do it twice. We’re getting the drift. GB: Exactly, exactly right. I remember a lot of the early days of Stripe was really about first principles thinking. We were in a domain, this credit card industry, that is very opaque, very Byzantine, it’s been built up over many decades and has so much complexity that the card networks themselves run on ISO 8583 , the spec from the ’80s. It’s a byte-oriented format, the whole thing. And we were trying to figure out, “How do we make this simple, dead simple, for the Internet era?”. So a lot of this is about deep understanding of a domain that you have no familiarity with. None of us really grew up as payments experts, but you just want to really deeply understand how it works so that you can expose the right primitives and the right APIs and abstractions. That to me was actually the core skill, and something that has been very transferable between Stripe and OpenAI. They’re very similar in some ways, where you go and you have to scientifically learn about a domain. AI versus payments, obviously different in terms of the specifics of those domains — one is much more about natural science, the other is almost this system that has been built up of complexity — but they are fundamentally about understanding the underlying why of how something works and exposing it in a way that’s simple and easy. I spent a lot of time on recruiting, a lot of time on culture, I think one thing I found is that I love coding, I love that feeling of flow state and just building and creating. Right, you’re legendary for these hours-long flow states and just coding endlessly. What’s the longest coding session slash flow state you had while building Stripe? GB: Oh, it all blurs together. I couldn’t possibly say, but I would just say that for me, there was this 24-hour sprint that was how we actually got onto the credit card networks. That was just this really great time that all of us were there together in the office, none of us slept, and it was supposed to be an integration that was going to take nine months, we got it done overnight, and if we had missed it by a day, it would have been another month. As a startup, every day matters, so that kind of accomplishing what seems impossible otherwise, I love it. That is something that was incredibly exciting. When you became CTO, you wrote a post saying how you were talking to other CTOs, you thought it was more of an architectural job, none of them did that, and you’re like, “I feel like I lose my feedback loops, I’m not connected to the product, I need to code again, I’m going to become a coder”. I’m curious, you wrote that towards the beginning of being a CTO, how long did that last? How long did you stay in touch with coding? GB: Well, I would say probably for almost another decade. One area that I think I’ve grown on and that I’ve really learned is how to stay in touch and really help move forward a team and bring together a team, even if you yourself are not hands on keyboard. And by the way, I will say that this is something that I think is actually an important lesson almost for every software engineer now, because the act of what coding is has changed so significantly over the course of the year. I think over the next year it’s going to change even more. We are all moving away from having to be the one who knows exactly which library to use and is able to craft the syntax and where the semicolons go. We are all moving to being these higher-level managers, these directors, the source of the inspiration, the vision, the judgment, the feedback. I think that shift, it’s been something for me that was difficult, because you had to let go of something that I was used to and valued and really loved. But I’ve actually replaced it with something I love even more. I know I’m talking to a smart guy because you stole my foreshadowing. I was going to circle back to that in a little bit, but yes, that’s exactly where we’re going. Let’s get to OpenAI. You’re a part of the OpenAI founding team. What’s your version of the story? I’m sure this could be a whole hour-long podcast, but what drew you to this space and got you guys started? GB: Well, I have been excited about the idea of AI for a long time. I remember when I was first getting into programming, I read Alan Turing’s 1950 paper on the Turing test. It’s this really interesting paper, it’s like 70 pages or something. It starts out by saying, “Well, what does it mean for a machine to be intelligent? I don’t know what that means. Intelligent is not well-defined. So let’s have a well-defined version of it”. I’m going to ask you what is AGI in a little bit. So it sounds like it’s still unsettled, right? GB: Well, there you go, yes. So Turing very smartly sidestepped the question and said, “Let’s just have an operational definition of this, where if you can have a test where a human can’t tell the difference between an AI speaking to them and another human, we’ll define that machine as intelligent”. The thing that was very interesting, though, that gets much less airtime, is he said, “Well, how are you ever going to solve this? It’s just too hard to program an answer to it. You cannot write down all the rules for how to respond to questions. Instead, what if you could build a machine that learns? What if you could build what he called a child machine?”. And then you teach it — you have a teacher who gives it rewards and punishments, and then you’re able to actually give it intelligence and help it be able to pass this test. I remember being so struck by this idea, because as a programmer, you only make progress by deeply understanding the solution to something. There are so many problems I don’t know the solution to, you don’t know the solution to, no person has ever come up with a solution to, we’re never going to be able to program the answer. But what if you could have a machine that could understand problems that we cannot, that could understand solutions that we could not? This isn’t just about image recognition, though of course it has applied to that. This is also about questions of how do we get along better as a society? How do we structure the world? How do we ensure that the benefits of what we’re creating end up lifting up everyone? These are super hard questions that humanity is not necessarily the best positioned to solve. But if a machine could understand, could look through more data, could have a deeper, richer understanding of many different fields all coming together, maybe it could solve them in ways that we could not.= So I was so inspired by that idea. But it was an idea. I remember showing up at Harvard, asking my professors, “Hey, could I do some AI research?”, and they showed me what the natural language processing state of the art was at the time. It was so clear to me, I was like, this is not what Turing was talking about. It’s much more hard-coded, parse trees, all of those things, this is not going to scale to AGI. But something in the early 2010s changed, and I was watching from the outside. 2012 was AlexNet , then there was a series of other papers, and the thing that I would just keep seeing on Hacker News, it felt like every day there was a new “deep learning for X”, I was just like, “What is deep learning?” — I remember going to deeplearning.org, and it just said, “Deep learning is a new approach to artificial intelligence”. I’m like, I have no idea what this means, I actually knew one person in the field, I went to them and asked them to introduce me to more people in the field, and I just kept getting reintroduced to a bunch of my smartest friends from college. I was like, “Wait, that’s interesting, these people are working on this, that’s actually a very strong signal”. So by 2015, it felt to me like there was something real happening. I was spending a lot of time as well really thinking about AI safety, thinking about the long-term future of this kind of technology, what it means to get it right, and it was more philosophy at the time. There were various writings you could find online that were very cool thought experiments, I ran a reading group at Stripe where we would talk about these things every week. So it’s something I deeply cared about, thinking about if there’s any way that I could help AI go slightly better than it would without me, that would be the best thing I could do with my career. That was all leading up to 2015, and I felt like I’d reached a milestone at Stripe where the company was going to work with or without me, it was kind of a question of, “Do I want to go the manager route?”, which is what you need to get to the next phase, or, “Do I want to go start a new company?”, That was something that had always motivated me, and so I decided that’s what I wanted to do. As I was about to leave, Patrick said, “Why don’t you go talk to Sam [Altman] “, who he had introduced me to a couple years before. He said, “He’s seen a lot of young people in similar situations, maybe he can give you some advice” — kind of hoping that Sam would convince me to stay. It didn’t quite play that way. (laughing) Yeah. GB: I met up with Sam, and three minutes in, he’s like, “Okay, you’re clear you’re out, what are you thinking about doing next?”, I said, “Well, I’m thinking about doing something in AI”, he said, “I’m also thinking about doing something in AI”. And that was the start. Were you on board with the whole non-profit thing ? What were your thoughts on that when you set that up ? GB: Well, the idea of being a non-profit is something that Sam had proposed, and I think that there are actually a lot of very important properties, and you see ones that have really rung true to today. The technology we are building, it’s just bigger than anything that’s been created, it’s bigger than the traditional structures and systems. There is no one corporate structure that exists that actually fully encapsulates the mission and the work we need to do. So I think starting that way made perfect sense, and there was always a question of what is it going to take to actually operationalize the mission? That’s something we spent a long time really thinking about. I think we’ve been the company that’s been the most innovative in really thinking about can you build a structure around all of the different aspects of both the commercial development that needs to happen, the distribution of benefits that needs to happen, the practical way of actually bringing forth this compute-powered economy, and doing all of that at once. So I think it’s been an important element, it remains a critical element to what we do. But again, I think we’ve innovated so much on corporate structure around the core of this mission, and that mission is invariant. Yeah, innovate is one way to put it. You mentioned the credit card networks, right? It’s super opaque, lots of stuff from the ’80s, a massive amount of path dependency that gave Stripe an opportunity, because you could abstract that all away and just be, for everyone else, “Here’s an API, it’ll work, don’t ask questions”. Now when you look back at OpenAI — it’s hard to believe it’s been over a decade now — could OpenAI have come about in any other way? Is there that sort of path dependency in there, or is there a, “If I went back to first principles, me, Greg Brockman, which I like to do, I would have structured this a lot differently”? GB: I don’t see any other way that we could have gotten to where we are, and I think where this mission needs us to be. Tell me about the ChatGPT launch , because you have the turning point where you realize you need to scale, you partner with Microsoft, add the for-profit bit, and then ChatGPT comes out and it’s huge. Did you have any expectations it would be as big as it was? GB: So the thing that surprised me, my prediction error, was GPT-3.5 being something that people would really love and want. We had GPT-4 at the time, it had finished training in August or so, and we launched ChatGPT at the very end of November of ’22. The thing that always happens when we have a new model is that we just latch onto it. The old one looks terrible. GB: All we see is just flaws in the previous one. We’re just like, “Ah, this previous one is so bad, I can’t imagine anyone would ever want to use it”. We had like 200 testers who we’d been paying to use the pre-release ChatGPT, and again, we had to pay them to use it rather than the other way around. So there were some signs of product-market fit if you really dug in and were close to the details, but if you zoomed out, it really didn’t look like we had it. But the way that we thought about it was GPT-4 clearly was going to change the world, we knew that, it was very obvious from the first moment we talked to it. I remember for that first week after GPT-4 came out of training, just feeling the reality of it. We’d been dreaming of AGI, thinking about AGI, thinking about what it might be like. But the first time you have a technology that really you can ask any question and it can give you pretty sensible answers, that got a 5 on AP Bio — all of those things, to me, felt like, okay, something is going to be different. It may not transform the world tomorrow, but over upcoming years, this technology absolutely will, and it’s real now. That was very clear. So you look at the ChatGPT launch, the way I thought about it was we just need to get the infrastructure out first, so that we can have LLM-serving infrastructure that’s battle-tested, that we’ve put our reps in. Then in March, when we launched GPT-4 — which, if you remember, we did the six-month delay between completing it and actually launching it — then we’ll already have the infrastructure ready to go. But I didn’t expect it to quite take off in that form, even though I expected it to do so in the future. What was it like at that time? Was it just all hands on deck to keep the servers from melting? GB: Oh, absolutely. So we launched into what we called a low-key research preview, and of course, it was just the full exponential, every single system you can imagine breaking, broke. Our login system became a big bottleneck, we had to do so much work to improve the login system, and you’re scratching your head saying, we’re building this magic AI technology, and the thing that is your bottleneck is, “Does your login actually scale?”. I remember that we had a fairly inefficient set of inference kernels that were rolled out to production, and I’d actually written some more efficient things, or we had some more efficient things on the research side, and one of the big pieces of work was, “Let’s actually take those optimizations, let’s move them over”, so a bunch of people swarmed on that problem, got it done. I think this was the general flavor of it for that first day, for that first week, for that first month, it was just scaling every system and trying to really keep up with this wave after wave of demand. What happened in November 2023 ? GB: Very complicated answer. Where do you want to start? I don’t know, I feel like I have to ask you about it. They’re tied into — you took a sabbatical not too long after , was there a link between those two things? GB: Look, I would say the way to think about it is that at the highest level, I think that 2023 really showed that there were tensions that had built up, really interpersonal tensions that had built up, that we had not sufficiently gotten ahead of. To me, that’s one of the most important lessons of OpenAI, the fact that we’re building technology, but it’s always about the people, in good and bad ways. It means that really managing people dynamics, that is one of the most important things that we do, and if we don’t get ahead of it, if we don’t have the hard conversation, then that is actually where things can become much rougher. So I’m happy to drill into more details, but I think that a lot of it, if you really get there, it’s not the more interesting technological things. How much of that is tied to ChatGPT being this massive, huge hit you weren’t necessarily expecting ? Was there a link between those things, or do you think these tensions would have come to a head regardless? GB: I don’t think that there’s a direct causal link, at least not in my view. I think that to some extent, there maybe is an underlying theme of, as our technology has progressed, everyone feels the weight of the world on them, feels the stakes on them. Actually, one of the things that’s hardest is how do you just move forward? To me, the thing that I always remark upon is that the day-to-day activities that we do almost look the same as at every other company. You’re still debugging some low-level issue, someone’s upset at someone else because they said something, or they didn’t include them in the meeting, whatever it is. It’s just the human factors, the human work. But of course, the stakes are so massive. So I think that there is something that has been very important at OpenAI, and actually one of the big things that I have focused on, is really trying to not put people in positions where they feel that weight of the world and feel like they’re alone in it. Really doing it together as a team, that’s the critical thing, and that I think is maybe the way in which I would say that there is something — and it’s not really specific to those events, but it is a consistent theme over the course of OpenAI — which is really keeping that feeling of we’re doing this together, and trying to both rise to that occasion, but also make sure that we’re doing all the basics and doing all those basics right. That’s one way that I think we move forward. Yeah, I mean, you’ve been a very vocal proponent of what I think is one of the overall philosophies of OpenAI: get things out in the world, experiment, see what happens, and react from there. Make your decisions based on empirical evidence, not theorizing about the future. That philosophy, I think you guys articulate that a lot in terms of AI, but this is my question, which I think you’re kind of getting to as well, it feels like OpenAI as an organization is also this massive experiment that’s being tweaked. The negative read on that is it seems like it’s just veering back and forth, reorganization here, new leader there, is this an unwieldy monstrosity, or is it maybe more organic and more resilient than it’s given credit for? As you look back, you say it could not be any other way, would it be better if it was a different way? GB: First of all, it is absolutely true that we have changed and grown so much from where we started, a very different operating business, but we’ve been consistently the pioneer in terms of moving forward this field. That’s true on safety, that’s true on security, that’s true on the core technology and just really thinking about the distribution of benefits. All of those areas we have focused on from the very beginning, and I think really the results speak for themselves. Now, that change, it’s real. And it is the case that sometimes the team that you have that’s right for one phase is not the right team for the next phase. One thing that I have been really focused on this year has been building up a leadership team that I’m just so excited about, thinking about this next phase and what we’re going to be able to do together. So part of the theme of 2026, and one shift maybe from where we were before, is that because there are so many people in this field, because there’s so much to do, and because the technology is taking off so fast and we’re so compute bottlenecked, you’ve got to focus. You’ve got to really prune. You’ve got to pick the areas that all synergize together. So actually making the decisions on things like, “ Hey Sora , amazing technology, but being in that specific, more entertainment aspect of consumer, that’s not something we can prioritize relative to other things”, then we’ll cancel it. And then that causes downstream effects, and it’s painful, it’s tough to actually make these decisions, but it’s all in service of really having that tight focus so that we’re able to accomplish the core mission. You’re a big believer in scalability, is OpenAI itself scalable? GB: I believe it is possibly the most scalable business ever. Yes. I mean just internally, as far as an organization. What is not scalable? We talk about compute, we talk about data, you mentioned the human factor before. Is the ultimate alignment challenge — we think about alignment in terms of getting the AI to do what we want to do, but do you have the reverse challenge? Can you keep up from a management perspective with this space, this problem? GB: I’d say two answers, first of all, absolutely yes. I think you can see it in how much we’ve matured as an organization over the past couple of years, where we were a couple of years ago is we had a lot of management debt. Again, there were a lot of areas where I think we did need to grow up, we did need to mature, but I think we’ve done that work. It’s been hard, it’s been painful, but I think we’re in a so much better spot, and I feel just immensely excited about the company and our future. But there’s a second thing, too, which is that I think it’s also worth stepping back and just recognizing that how companies run is changing. You can look at this, for example, just looking at revenue per headcount. The revenue per headcount for us and similar businesses is just off the charts relative to any previous business. There’s a reason for that, you’re starting to see this increased leverage you can get through this technology. And by the way, because we’re making that technology and fighting to make that technology broadly available and to help so many companies, you’re going to see many other companies be able to run in different ways, to be able to have that outsized revenue per head. That to me is something that is very exciting, that we are shifting what it even means to run a company and how to operate. So there are some things that are invariant, just people working together — there’s something very fundamental there, and really doing that in a good and consistent way is something that, again, I’ve really focused on. But I think that there is also something about leaning into what is possible with our technology, which means that every company is going to have a new opportunity. You mentioned cutting off Sora , and you framed it as being the entertainment aspect of consumer. ChatGPT, huge consumer hit, you made an unbelievable amount of money from consumers. But at the end of the day, how many people are willing to pay for this? How many customers actually want to be productive ? Is there a bit where having such a hit in the consumer market was almost a negative, in that it was distracting, used up a lot of GPUs, and maybe you missed the boat — not missed the boat, but were late on the boat — as far as enterprise being the top focus? GB: So we have conversations like this all the time internally, and actually, I think that’s one of the strengths of OpenAI, that we really examine everything we’re doing from first principles, rethink it all the time, have lots of diverse opinions and perspectives. There are some people who can take almost any angle on this argument, and they all have a point. So there’s some truth to, “Hey, there’s this agentic moment, we were late to it”. There’s also some truth to having a billion people — that’s over 10% of the world population. Within the U.S., I think the number is something like maybe a third of the U.S. population uses ChatGPT every single week. Every week, that many people using your system, that is unique, there’s nothing like it for this kind of advanced technology. So on the one hand, if you just think of it as, “Hey, we have advancing technology”, one of the challenges with chat as a product is that it’s not necessarily aligned with more intelligent models. It’s not clear that people get the benefits of that directly through classic chat, if you’re just using it as a search engine replacement. But I think that all of these things are going to come together and come to a head, and I think we’re going to see that this billion users is an investment, that it is something that actually accrues to how models get unlocked in the future, and you’re seeing the first steps towards it with ChatGPT Work and things like that, there’s a bunch of nuance and complexity there, but a lot of the strategy has been to say, we’ve got consumer, we’ve got enterprise, these are two things — we don’t want to do two things, we want to do one thing. We want to build one AGI, one system, one unified stack. We want it to be something you use in your personal life, work life. Right, but is there a bit about shipping the internal org chart? You come out with a new ChatGPT, a dramatic departure from the old one , it’s built off of Codex. I can see the benefit for OpenAI internally, but is there a frustration that customers don’t realize what they can do, so, “We’re going to drop them in on the deep end, and hopefully that will help them figure it out”? GB: I think that there’s a fundamental shift happening in the industry, and you can see it with new emerging agentic products that are happening right now. I think that the core shift is you’re going from chat to agentic use cases. And again, it’s not just about productivity. I think that in your personal life, you want to be able to ask the thing to go book tickets for you, to be able to book your haircut, to be able to do those kinds of personal things, but you also want it to be able to give you good life advice, to be able to help you with health information. So to me, productivity is too narrow of a box. To me, consumer is too broad of a term. Enterprise is also something I think is going to shift. All these classic words, they are all going to smush together and grade together in ways that I think no one has ever built a product like that before. So my view has been that there’s a change management required of how do you bring along a billion users to a new set of use cases, help them understand. And by the way, there is an unfair advantage that is possible, which is you have an AI that understands what you’re trying to accomplish. That’s right. GB: It can say, “Oh, I can actually help you more if you enable this connector, if you do it in this way”. That’s something where I feel like it’s just an amazing thing, an amazing opportunity, and there’s a lot of potential there. When I say unfair, I mean just relative to what you would be able to accomplish with classic technology. If you just compare one technology versus another, there’s something unique about this one. You mentioned the Turing angle before, and I’m glad you brought up both parts, because can AI talk like a human? Obviously, we surpassed that point a long time ago. But to me, the AGI definition — which is a fraught thing for you guys, it’s finally, I think, out of your Microsoft agreement , so we don’t need to worry about that angle anymore — to me, it’s some connection to learning. You mentioned learning, and to what extent an LLM learned, past tense, but the challenge is does it learn on an ongoing basis? To me, what is revolutionary about the agentic moment, the way I think about it, is really the ability to write things down. That’s why the Codex/ChatGPT shift was necessary, because it gained the ability to write things down. If you write things down, you can remember things. If you can remember things, you can be tremendously more useful in all sorts of ways. The question is, is that an end state, or are we going to get an LLM that can learn continuously, and that’s AGI? Am I thinking about this all wrong, or does that fit the part two of Turing’s questions that he was raising? GB: Yeah, I think that this is also a very interesting area for debate, because people do have their own definition of AGI, it’s almost this blurry thing. At the beginning, we thought it’d be like, here’s this point in time that everyone agrees that is the AGI, it hasn’t played out like that at all. Now, I tend to take an abstracted view from the technology. So the question of, does memory have to get baked into the weights? Is this a transformer or something else? Those questions, I think, are details. The real question is, do you have a system that operates the way you would expect for a real AI, for something that can learn, that can learn from you, that can adapt to what your needs are? And the question of, is that implemented through a scratchpad that it writes down memories in? Is that implemented through soft tokens? Is that implemented some other way? All of that, to me, feels like possible answers to the question. I think it is very clear we’ve gone so much further with “write things down in a scratchpad” than is almost reasonable. It’s actually quite amazing to see how successful it is, because there has been a lot of push — two years ago, we would have said, “Yeah, you need these super long contexts, that’s the thing you need”, actually, it turns out that with just “write down a scratchpad” and shorter contexts, it just goes unreasonably far. Just write stuff down. GB: So we’ll see what the future holds in terms of improving these things. I have this belief that if you zoom out, everything’s an exponential. You zoom in, you see these paradigm shifts. This, by the way, was the Ray Kurzweil view of how technology and computing works. I think it’s been absolutely true for even these questions of how is memory going to work. So you just launched Astra . We’re finally here. Is this a new pre-train? Are you releasing any details about the size, the architecture? We’re recording this before it’s officially announced, so I haven’t seen everything that you’ve published. GB: So we’re not talking about the internal details and architectures, things like that. But this is a huge step forward. We’re talking about the fact that this is the first run that we’ve trained on more than 100,000 GPUs, which is an easy number to throw around, but just think about the scale of that. These data centers in some ways are these big machines that we’ve built in order to help deliver and create AI technology, and it’s a real engineering challenge and marvel that people are able to harness that amount of compute to deliver the kinds of results that we have. So part of that is about making the models more capable, but so much of the compute goes into safety and alignment, and we have so much security work that’s gone around it. I think that we’ve done a huge amount of work to deliver this model safely. It’s our most aligned model yet, which to me is something that is absolutely critical and always has been. But because the capability is so strong, alignment and safety become even more front and center in terms of everyone’s work. Your announcement post is interesting. It’s very matter of fact. There’s a huge number of practical use cases. The contrast to, say, your competitors’ announcements is very, very large. Is your framing of AI as a tool — which I think is a fair way to put it — is that about marketing, or is that how you think about AI, as opposed to, like, creating God? GB: I think there’s a deep fundamental value that we have, and some of it actually relates to how we think about people. People are valuable not just because we can do tasks. We are valuable because we are humans, because we have feelings, because we matter. That human judgment, human oversight, human control, all of those things are absolutely critical to maintain, and to maintain forever. That is something that we believe is a core invariant. So when we think about what we can do to help steer the future of this technology — which in some ways is what it’s all about, that is why we started this place, that is what we care about, how can we help this technology go in even a slightly more positive direction than it would without us — we think about these questions of how does this technology roll out in the world? We want it to be something that uplifts everyone, but also the question of how humans relate to technology, to computers. It’s clearly changing. It’s even changing in terms of just typing less, talking more to your computer, having this much more natural interface. But really, that human oversight and creativity and vision, all of those things I think are very important to preserve. So that does then bleed down to these questions of, do you talk about it like it’s a person, or do you talk about it like it’s a tool? Do you think about the use case? Do you think about it something differently? You can see this as almost a small thing, and I’m actually glad you pointed it out, but it’s something we’re very thoughtful about. The team spends a lot of time really thinking about everything we want to talk about and how we want to present this kind of work to the world. So is this a model release, or is it a product release, or is there any difference? GB: These things do blur together. I would say that this is first and foremost a model release, but the model is qualitatively more capable. Maybe the headline one is computer use. It’s really crossed the threshold for me, computer use has always been — even from the beginning of OpenAI, I remember in November of 2015, before it even really started— Well, that was like your first product, right? It was like playing video games or something like that. GB: Yeah, exactly. Ah, you remember, yes. We had this vision of if you could do screen pixels, keyboard, mouse, an AI that you train end-to-end on that, it would be able to actually go and address any sort of task, anything that you want people to have help with, this AI will be able to do. If you look at the era we’ve been in for the past two years, it’s been a connector era. You have some pieces of software, humans can use it just fine, the AI has no access to it. So what do you do? You have to write a very specific connector that hooks up to the APIs, and not everything’s exposed, so you can’t do everything that you could. Then you think about that there are so many pieces of software that don’t have APIs, and those are totally out of bounds. So we have this limited world where the AI is so restricted from helping you. I think that we now have the technology that’s almost this universal connector. Now, that doesn’t mean that all the problems are solved. You have to think about how do you have enterprise guardrails around what these AIs are doing? How do you have the appropriate oversight, management, tracking, and observability? All of those we’re working on. So I would view this as a continuous process of how the product rolls out in order to help harness this capability. But it’s already transforming how people do work within OpenAI, and it’s really, I think, going to uplift so many companies, so many individuals. If you think about the overall value chain, there’s a place where you’re fighting battles on two fronts, I could see. One is you have companies like Microsoft, or other partners — if you don’t want to use their name since they’re still an important partner — but they want to commoditize models . They want to build the thing on top, and you can plug-and-play, shift models in and out, they’re holding all the context and what’s important. But at the same time, you’re building these incredible capabilities that are really tied ultimately to the end user, it just goes and does the things that you want it to do. Is that just inevitably where you have to get to, to accomplish what’s yours? Is there also this economic imperative — if we don’t want to be commoditized, we need to get up into products and actually doing things directly connected to users? GB: I would say that our underlying imperative is really that we want there to be more AI capability in the world. We want people to be doing more with AI, for it to help them, and we really view that we’re shifting this compute-powered economy. What that means takes different forms, especially across different verticals. Sometimes we feel like we are in a position to really focus on an area and do a good job with it, or it’s very core to our mission. Health is a good example. We’re building something incredibly unique in health. It’s actually very surprising to me how little airtime what we’re doing in health gets relative to how many people it’s actually helping. We have like 300 million people each week coming to ChatGPT for health queries. 300 million people, that’s a huge number. Then we’re also building a bottoms-up clinicians product , and we’re building a top-down enterprise product for hospitals . So we have this three-sided marketplace in health, and what we’re going to be able to do there is things like, you want to find people for clinical trial enrollment — that’s a hard problem, but we actually may have the ability to help find people that would otherwise not be found. That both helps the patient and helps these drugs be able to move faster. So there’s this core of saying health is so critical to our mission, we have a unique shot on goal, a unique opportunity, let’s really focus on it. We put a team behind it, we put all the effort behind it, we build the relationships. One thing that we do when we go into specific verticals is we think about how do we play well with the ecosystem. It’s not to say we won’t compete there — we often do compete very hard — but we also really think of it as we’re going to lift up all the boats, too, and how do we actually just focus on this core mission of, we have this technology, we want it to be broadly diffused, we want it to be out there. So sometimes it can be a little bit nuanced. There are always a lot of questions when we go into a specific area of exactly what we want to do, what we’re set up to do and what we’re not. But I think the way that we view it is that our overall goal at OpenAI benefits the more people are using AI to positive benefit. Well, if you have the layer on top of you trying to commoditize you, there’s probably an angle of you trying to commoditize the level under you. You guys just talked a lot more about your Jalapeño chip at Hot Chips . Why is Jalapeño important? Is it important beyond just saving money as far as paying for chips? GB: I would think of it as, since 2017, we have been plugged into basically every hardware startup out there, every vendor. We talk to them, we give them feedback, we say, “Hey, here’s where we see the models going, here’s what we think you should do”. Sometimes they listen to us, sometimes they don’t listen to us, sometimes we’re close partners, sometimes they don’t really want to talk to us. One thing that has been very freeing about having a chip program in-house is that we’re able to just go directly to the thing that we think is the best, that we think is exactly tuned for, not just necessarily what we’re doing, but the aperture of where we think this technology is going. It was a very big investment — we have a team, an absolutely incredible team, with great leadership that has been working on this for quite some time. But again, it is also something where we work very closely with the ecosystem. We partner very closely with Nvidia as our preferred compute partner, and if you look at the size of the computers we’re building and the unique computers we’re building, we need Nvidia, there’s no question about it, we’re building these amazing training computers, we’re building lots of inference with them, we’re able to push their hardware actually sometimes in ways that even they didn’t realize was possible. Yeah, I heard there was a little bit of a hard pickup, maybe that made it a little harder to get very large models out in time, but it’s working now, I suppose. GB: Yes, yes. And I would say that there’s something that is enabled by us having that in-house expertise, because we deeply understand things. It’s one thing to be sitting on the sidelines and throwing advice over the fence, it’s another if you actually have gone through the pain. A good example of this actually is AI for chip design. We’ve talked about this, that we’ve used our own model in the design of Jalapeño, it really sped things up, it got us some real wins, all the cool things. As an aside, there’s a cool story there where we were coming up on a deadline, we had like a month to go, we got some optimization done with our model. We’re like, “Do we spend the time to really read what it did? We know it’s correct. Do we need to understand exactly what optimizations it did, or do we just spend the rest of the time getting more optimizations?” — and so we said, “You know what? We’ll just get more optimizations in”. So we spent that month on just running it without deeply understanding exactly all the tweaks it made. Then we went back and read it, and it actually turned out that it found a bunch of optimizations that had been on our list, but we just never would have gotten to, so that was actually a pretty cool story. But now we have that expertise, we know this thing works, and we can bring that to the ecosystem. We can work closely with everyone in order to actually bring these benefits broadly, to transform hardware and do that at mass scale. So there’s something about that flywheel that’s absolutely critical, the chip is incredible, the team did a great job. Is it a problem talking about it now, though, when you can’t ship in volume and you still need to partner with other folks in the ecosystem to get the supply you need? GB: Well, but this is the core, this is actually the core of everything. We think of it as — I think everything is multiplicative, everything is complementary, everything adds up. And again, it is absolutely the case that Nvidia is our preferred partner, that’s not changing. In fact, we’re leaning in even more with them. We’re deeply, deeply grateful for that partnership, we spend a lot of time with their team, there’s a lot of things that we learn from them, there are things that we hope that they can learn from us, I think that’s something that doesn’t change. The fact that we are able to have in-house expertise and really think about things in our own way as well, to me, that’s something that’s just multiplicative, I think it really benefits everyone. You mentioned you just trusted the AI design, and that got you further down the road. Is that the answer to cybersecurity? You had some engineers give a talk at the Black Hat conference and talk about this structural problem — attackers don’t need to worry about breaking things, they’re trying to break things. If you’re on the other side, you’re worried about everything continuing to run in addition to fighting off these attacks. Do defenders need to get to the place where they just fully trust the AI? GB: I think the hardware side is a very important case study, because there we have guardrails. We have verification, and actually, the way that we write our underlying hardware design is specifically to allow verification, so we almost co-designed the whole system. That’s like how you code, it writes the unit test first and then backs into it. . GB: That kind of thing, how you pick your language and the toolchain, the whole thing, it’s all together, and it actually all adds up to a system that you can have that kind of observability and trust. I think it’s okay for there to be some areas where you say, “I have sufficient guardrails here that it is actually okay if it’s this code or optimizations that I haven’t fully inspected”, as long as you have the appropriate compensating controls. But I think that it is very important that you as a human do understand and feel accountability for the system you’re creating. That to me is actually a core thing, back to what is it that humans are, what is unique to us, what is something that we are going to carry forward, I think accountability is a core of it. At the end of the day, you’re responsible for what happens at your company. Right, but if those on offense are not accountable, is that a structural disadvantage? GB: So I think that this is something we think about a lot, that there is what we call this The Defender’s Window . I think that we can see a little shape of the future, we have frontier capabilities that have shown the kinds of capabilities that will diffuse to threat actors. And by the way, I think the fact that this capability is not being locked up forever in a small number of labs is actually very important, it is very important that there is broad distribution of power, that is part of our mission as well. But we have the ability to have a separation in time. There’s this window where defenders can get access to these capabilities, and differentially so. And my view is that it is true — there’s a common wisdom in cybersecurity that offense is a technology problem, defense is a political problem. The attackers can just take something off the shelf and run with it, whereas as a defender, you have to think about your stakeholders, you have to think about your business, you have to think about how you actually get people on board, your CEO, all the executives, all those things. So I think that there is something here where defenders need that willpower. One thing we are recommending, and we’ve actually done ourselves and are talking about it publicly now, is that every company should treat this as a proactive incident. Critical business operations, proactive incident, that’s your next priority, so we actually took 25% of our production engineers and put them to securing ourselves. We took our models — in fact, we took Astra, pointed it at our own systems to find vulnerabilities, and not just read the code, but really look at the end-to-end of how these things are running, so we would find real validated vulnerabilities, and then it also helped us with the remediation, patching, and fixing. So I think that you do need a shift in the energy in the ecosystem in order to stay ahead and to take advantage of this window. Well, that’s all great and fine that you’re doing this now, but to me the most remarkable thing about the Hugging Face incident and the things that have come up about it is it doesn’t feel like OpenAI was particularly concerned about cybersecurity. Why didn’t you do this before? Hasn’t the Defender’s Window been open for a while, and you were also failing to take advantage of it? GB: Well, two answers. So one is that if you look at the way that we were doing sandboxing, it was not that this workload was not sandboxed. There was actually a sandbox around it, and I think that one thing we realized is that we had— Right, which wasn’t clearly sufficiently tested. Is it really a sandbox, or is there a connection to the Internet via a third party who were just thrown in there? That’s the most remarkable thing about this incident . It’s like, if you wanted to test for vulnerabilities, I guess you did that. GB: It’s definitely the case that the AI was able to do very creative things in order to get out and get into Hugging Face. But to me, there is a bigger thing, and I think you’re pointing at the right thing, which is that since this summer, when Mythos came out, when we started to have cyber-capable models — and we even talked about our Trusted Access for Cyber program back in February, because we saw this wave coming, we wanted to really prepare for it — there is a tendency— I know, but you talked about it in February, but you didn’t point it at your sandbox, “Is my sandbox actually secure?”. GB: There is an instinct, there’s a reaction to that, to say, “Let’s restrict access massively, let’s really put a bear hug around this, only if you can get access”. And I think that to your point, because the field continues to move, it means there’s time that defenders lost, there’s time that people were not defending. Part of that is about access, but part of that is about how much do you put your full weight behind saying we’re going to shift around this in a significant way. Now, I think that to some extent, the time is not all made equally, because we’ve gone from a world of cyber models being not that useful, not that differentiated, to actually being incredibly capable, incredibly powerful. We’re seeing that with Astra, we’ve talked about how it’s really saturating a bunch of these evals. I think now is the time, it’s possible that a couple of months ago could have also been the time, but you would just have had much less capable models, you would have made much less progress. So I think that really estimating where we are, we are clearly there now, and I feel like that is something that we have learned, we’ve taken it to heart, I think that you’ve seen a real shift. It’s actually been a cultural change in a lot of ways, an operational change, and it’s not easy, because it really means that you have to have teams working together very tightly in a loop with much higher standards around how policies are set and all these things. All of that, for us, it wasn’t a shift in terms of we’ve always cared about these aspects, but really bringing them together operationally and being able to make decisions the way that we have, I think it’s been an up-level across every aspect of what we do. Now suddenly they’re able to do it, as if doing it previously would have been a waste of time, which I think is kind of a valid point. How do you avoid the trap of, “Well, the AI will be able to do this in the future, so we don’t need to do it now”? Just in general, though, not even just with this. GB: I was going to say one thing that’s a specific data point, so early on, sometime in Q1, we really started thinking about, we are going to have — it’s hard to know when, but we’re going to have these very cyber-capable models. What is a sandbox that we could build from first principles that’s as secure as you could get while being built on cloud infrastructure? And we built that. We actually took some of our best engineers and pointed them at that problem, and they sprinted on it and they produced something. So I think building infrastructure from first principles around what you see coming, that is something that I think is important. And to your point on when is it, “Oh, we can just let the AI do it” — again, we’ve seen this show before in different fields, in writing kernels, and thinking about the fact that, “Okay, we’re going to be in a world where in the future the AI is going to be able to write GPU kernels very well”, do the classic kinds of investments where it takes many months, sometimes a year, to get new infrastructure in place for thinking about new hardware, that kind of thing, or do we just say, “Ah, the AI will figure it out”? I think the answer is always that it takes a little bit longer than you expect for the AI to get there. But when it does, it is surprising and powerful in ways you didn’t imagine. One example of this is with Astra. One thing we have found is that a number of our skills that we’ve built up over the course of this year, very painstakingly, to show our models the right way of doing things in OpenAI and things like that are actually now net negative for its performance. Too many rules. GB: Exactly. It is able to generalize better, or be able to find better ways of approaching patterns and things like that, than what we had written. So I think there’s something about this where you do want to build those controls, you do want to build the deterministic infrastructure, you want to write those skills. But you also need to be prepared for, as the AI gets more capable, that some of those things, the scaffolding, will become a limiter. It’s kind of like training wheels. At first, it helps you, but once you start going faster, once you have something more capable, something better, something more aligned, then it actually starts to be a hindrance. Will you ever be in a 12-hour or 24-hour coding flow state ever again? GB: I hope so. I think there may be a day where that happens, but I will say that I have found so much joy and value in helping the team in the way that I do now. I think that for me, it’s really about that mission. Well, it’s not just you, but will anyone? Because isn’t AI’s benefit almost that it is permanent flow state available at your command? GB: I think that we’re going to find new ways, whether it’s managing agents — actually, one thing that’s been so wild is seeing that software engineers are working harder than ever, because you realize if your agents aren’t working, it’s just time that’s lost, you’re never getting it back. So I think that people will achieve that flow state in ways that are kind of unimaginable right now. At the end of the day, you’re talking about this is going to be controllable, these AIs, “Don’t put too many rules, they’ll figure it out”, if you play that out in the fullness of time, isn’t that ultimately about them being uncontrollable? GB: Well, I think this is the core of the moment, of the new phase that we’re in, and in some ways I would say we’re into the AGI era now. I think that is the core of this moment, where — maybe it was the previous model, maybe it’s Astra, maybe it’s the next model, but somewhere in there, I think we’re going to cross most people’s AGI threshold. Ensuring that we are pacing , ensuring that we’re thinking about safety, security, alignment, and capability, all as requirements — we have standards around each of these, we want to progress them together — that is something we’ve always believed. But I think it’s becoming very front and center that these other aspects are becoming almost the bottleneck to development. And I think that, again, is something where we’ve been prepared for that, we’ve been thinking about this, and I think we’re operationalizing it in a real way. So my view is that there’s a lot of progress to be made, but I think that the way that we should approach it is through increasing our standards in all of these. If you look at that, I think we see line of sight for things like monitorability. That’s very key. We’re bringing that in a real way. I think that we have a very good program. We have a good set of people, we have a good track record and a good mission that I think all point towards we are building systems in a way that they are controllable, and we’re taking these step by step in terms of pacing. Greg Brockman, congratulations on Astra, and yeah, can’t wait to use it. GB: Thanks so much, thank you for having me. This Daily Update Interview is also available as a podcast. To receive it in your podcast player, visit Stratechery . The Daily Update is intended for a single recipient, but occasional forwarding is totally fine! If you would like to order multiple subscriptions for your team with a group discount (minimum 5), please contact me directly. Thanks for being a supporter, and have a great day!

0 views
Unsung 2 days ago

“I would be very happy to see all kinds of text editors adopt this.”

Speaking of cut in File Explorer , Will McGugan, creator of the writing editor Ishmael , proposes doing the same thing for text editing – that is, leaving ghost text behind: I call it “Ghost Cut”, and it works like this: pressing Ctrl+X fades the selected text and makes it inert—you can’t click on the cut text and the cursor just kind of leaps over it, but it is still present in the document. Nothing is placed in the clipboard at this point and there is nothing to undo. If you decide you don’t want to paste then hitting Escape will restore the text to its active editable state. I do not think this is a good idea. It seems like McGugan proposes somewhat arbitrary reasons that cut and paste are “broken,” and to me the proposal fails even within his own framework: for example, it still doesn’t avoid the reflow, but moves it to the other side, making paste feel unstable (the included JavaScript playground feels disorienting to use). I think it also is at odds with the editor’s own about page , which talks about distraction and simplicity – and yet, what’s introduced here is a host of complex new things: a new visual state for cut text (that looks like AI autocomplete), some new logic to avoid moving into the cut text (which will also prevent easy selection adjustments), likely new confusion around undo, and a necessary new Esc gesture to get rid of a cut you decided not to pursue. But! There is something interesting in seeing this ghost text, and specific critique aside, it is fun to see experiments like these, with interactive explainers, poking at long-established interactions. Just yesterday, a second one appeared: an interesting new way to extend selection upwards – similar to double and triple clicking on text, but via the keyboard. This is the power of prototyping: sometimes seeing an idea you disagree with is the only thing that can unlock a different solution in your head. Let’s go back to cut and paste, though. You will notice that what’s listed as a precedent is not File Explorer, but Excel. It also doesn’t immediately remove selected cells on cut, but leave them in a temporary “possibly getting moved or removed” state first, only to have them disappear after paste: Why is that? I believe out of a similar principle, but a distinct reason that File Explorer too opts to leave a cut ghost behind. The stakes are higher in a different sense: cells refer to other cells. Were the removed cells to disappear immediately, you might witness the rest of the spreadsheet error out or show zeroes, as its formulas start pointing to emptiness. And it’s a good principle to generally avoid frightening your users. Here’s an example from Numbers, which doesn’t do ghosting, making cut a bad choice to do a simple move, as it doesn’t even recover after paste: #explainer #text editing

0 views
David Bushell 4 days ago

Fine, I’ll build my own text editor!

Hello RSS reader! This post contains interactive features. Please visit the canonical web page for an optimal viewing experience :) “They don’t make ’em like Sublime Text anymore” resonated with a lot of folk. Software these days is garbage. That got me thinking; I’m good at building garbage! Why can’t I build my own text editor? VS Code is built upon Monaco Editor which is a soup hellscape. I was late to the VS Code train because for years my Intel inside™ Mac was too slow. That issue was resolved when I bought Apple silicon. If that’s the standard I have a lot of room to make mistakes. My first experiment renders everything on a element. RSS does not support this interactive feature. Please visit the canonical web page. You can’t tell, but your CPU is doing a lot of work to render that picture at 60–120 frames per second. Lack of interactivity is an obvious problem for a text editor. I made a list of the “minimum viable” features and implemented them. This next demo is interactive, click around and type. RSS does not support this interactive feature. Please visit the canonical web page. Before you @ me about Vim bindings: shut up, I’ve got more pressing issues. Canvas gives me nothing for free. Amongst many desirable features, I’m missing: That last one is critical. Life is too short to implement custom elastic scrollbars. I decided to cheat and use native browser overflow on a hidden element. A is sized to match the canvas text and the scroll position is used to calculate render offsets on the . RSS does not support this interactive feature. Please visit the canonical web page. I’m pleased with how that’s coming along but I’m also disheartened because is entirely inaccessible. I could continue to add text selection and other features but I’m not solving the fundamental accessibility issue. I had a better idea. Instead of rendering text on the I can just render it natively in the overflow and make it editable with a attribute . That attribute has a value that is perfect for code. All content remains within a single text node. Attributes like must be disabled to avoid input latency spikes. Want to guess how many days it took me to discover that fix? Days! Using gives native text selection and undo history etc. So much accessibility goodness is wired up for free by the browser. RSS does not support this interactive feature. Please visit the canonical web page. The provides metrics I use to continue rendering a custom text cursor. is available so I can style that too. I’ve set the native invisible, which is probably a no-no. The technique is promising but I’ve noticed strange performance issues beyond a certain character count. Chromium browsers perform worse than WebKit and whatever Firefox is now but it’s unpredictable. Instead of plaintext would a simple be viable? In short: yes. Turns out a is far more performant for longer text. In this final demo I’ve added syntax highlighting too. RSS does not support this interactive feature. Please visit the canonical web page. My original plan was to use custom on the element. can’t use CSS highlights so a third layer was required. For demo purposes I added some soup for the visible lines to apply MicroLighter . Edit: I’m told the new OpaqueRange API unlocks custom highlights for — neat! Too many CSS highlights are another performance bottleneck. A more robust solution would be to use Tree-sitter to generate a syntax tree and walk that to generate highlights for only visible lines. I was hoping to avoid virtualised scrolling entirely but I could improve it using the inverse sticky technique . Or I can go back to because the file sizes I’d be editing don’t hit the performance wall. Anyway, looking good, right? Looks like 90% of a text editor with 1% of the features. From here it’s pretty straight forward to draw the rest of the owl . I’m tempted to keep drawing but then I think about all the little things like tab indentation. Right now I just hijack the tab key to insert two spaces… My demos above are unoptimised and far from perfectly accessible but at least I’m not starting from a losing position. Rendering on would be a nightmare. I’m filing this project away for a rainy day. JavaScript strings and text ranges work with UTF-16 code units. It’s easy to naively introduce bugs. I’m sure my demos are full of them. I’ll leave with a code example to nerd snipe. Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds. Pointer down to position text cursor Arrow keys to move text cursor Highlight current line Type to enter text Fancy cursor animation Text selection Undo/redo history Multi-line paste Overflow scrolling

0 views
Ahmad Alfy 6 days ago

I wanted the browser to just ship jQuery. Cross-Origin Storage came for rescue

Early in my career I had an idea I thought was obvious. Almost every site on the web was loading jQuery. The same file, over and over, millions of times a day, across the whole internet. Why didn’t Chrome just include it? Ship the file with the browser, save the world a mountain of bandwidth, move on. Nobody I said this to was impressed, and the idea falls apart the moment you poke at it. Which version do you ship? What about the next one? Do you also ship Bootstrap, Lodash, Angular? Where does it stop? But the instinct behind it was right. There’s a proposal in the Web Platform Incubator Community Group that arrives at roughly the same destination by a much better route. It’s called Cross-Origin Storage . The web had already solved this, in its own way. For years the standard advice was to load your libraries from a public CDN. Link jQuery from Google’s copy, link Bootstrap from a shared host, and everybody wins. The browser cache was keyed on the URL. If you visited site A and site A pulled jQuery from a shared CDN, the file went into the cache. When you later visited site B, and site B pointed at the exact same URL, the browser already had it. No download. That was the whole pitch, and it worked. Not quite “the browser ships with jQuery,” but close enough in practice that it was in every performance checklist for a decade. Two separate things killed it. The SPA era arrived and we all started bundling. Webpack, Rollup, Vite. You no longer ship jQuery as a file the browser can recognise. You compile it into a single bundle along with your own code, your framework, and everything else you imported. Then we added content hashes to the filenames, because cache busting needed to be reliable. Now every build produces a new URL. Change one line in your app and the entire bundle gets a new name and a fresh download. And tree shaking finished the job. Your copy of a library isn’t the library. It’s whatever subset of it your imports happened to pull in, mangled by your minifier settings. Two sites can both depend on the exact same version of the exact same package and end up shipping bytes that don’t match. So the shared cache had nothing left to share. Before any browser changed anything, we had already built our applications so that no two sites on the web send the same file. Safari had partitioned its cache for years. Chrome followed in version 86 , released on 6 October 2020, keying cached resources on a Network Isolation Key made up of the top-level site and the current-frame site. Firefox shipped the same idea in version 85 in January 2021, partitioning the HTTP cache along with the image cache, font cache, DNS cache, connection pools and more. A file fetched while you’re on site A now lives in site A’s slice of the cache. Visit site B and site B downloads its own copy, even when the URL and the bytes are identical. The reason is that a shared cache leaks. If I run a site and want to know whether you’ve visited a competitor, I can load a resource only they use and time the response. Fast means it was cached, which means you were there. Chrome’s own explainer for the change notes that exploits along these lines had been demonstrated in the wild, including cross-site search attacks that read your search results one string at a time. Chrome published the impact of that change. Cache miss rate up about 3.6%, bytes loaded from the network up around 4%, First Contentful Paint up about 0.3%. They decided that was a fair price, and they were right. So by around 2021 the trick was dead twice over. Our own build tools had made it pointless, and the browsers had removed the mechanism. None of this mattered much when we were arguing about a 30KB library. It matters now. AI models, WebAssembly modules, game engines, large web fonts. These are big files, they’re publicly distributed, and they’re byte-for-byte identical no matter which site asks for them. The Cross-Origin Storage spec puts the problem plainly: when two unrelated sites both depend on the same 8GB model, partitioned storage forces you to download and keep that model twice. Your bandwidth, your disk, your battery, and the network’s capacity, all spent on a file you already have. Nobody is bundling an 8GB model into their webpack output. These files ship whole and unmodified, which is exactly the property the shared cache used to depend on. The proposal is a cache that ignores URLs completely. Files are stored and looked up by their cryptographic hash. That single change answers the version question I couldn’t answer years ago. There is no “which jQuery do we ship,” because you never ask for jQuery. You ask for a specific SHA-256 digest, and the browser either has those exact bytes or it doesn’t. Two sites referring to the same hash are, by definition, talking about the same file. Reading looks like this: You get back a , the same object the File System API already gives you, so there’s no new file-handling vocabulary. Writing is the same call with , plus an option that declares who else may see the file. Declarative versions are being proposed too, so a tag or a rule could opt in with no JavaScript at all. The idea is to hang it off the attribute you may already be using: Note that this syntax is illustrative only. Sharing files across sites is easy. Sharing them without rebuilding the tracking problem that killed the shared cache is the entire engineering challenge, and it’s the part of this proposal I find clever. Every time a site asks “do you have this file?”, the question is a probe. If a file is used by only three sites in the world, a “yes” tells the asker you visited one of them. You’ve reinvented the leak. The proposal answers in layers. A file is only shareable with the whole web if its hash is on a Public Hash List . A hash earns a place by being genuinely widespread, appearing across enough independent sites that knowing you have it says nothing about you specifically. The spec proposes governing that list across vendors, in the same spirit as the Public Suffix List. If your file isn’t popular, it doesn’t get listed, and other sites can’t probe for it. The browser is allowed to lie . The spec calls it GREASE’ing (occasionally answering “not found” for a file it actually holds). One uncertain answer poisons the whole pattern. Your first instinct is probably that I’d just ask three times and take the majority answer, and you’d be right, which is why the noise never stands alone. The spec pairs it with rate limiting on repeated requests from one origin, and with on-device heuristics watching for hashes that look generated per user. If you can’t re-probe cheaply, you can’t average the noise away. There’s a limit on the dishonesty, though. The spec says a browser must not do this for gigabyte-scale files, because forcing a pointless multi-gigabyte re-download is too high a price for the privacy it buys. Which means the noise is thinnest exactly where the files are largest. The result is, the you might get never means “this file is definitely absent.” It only ever means “go fetch it from the network.” Treat Cross-Origin Storage as a bonus. The proposal is a Draft Community Group Report, which means it is neither a W3C standard nor on the standards track. You can still try it. There’s a browser extension that implements the proposed API and injects it into pages, so you can build against the shape of it today. I like this proposal because it takes a naive instinct I had years ago, agrees with the instinct, and then does all the work I didn’t know was needed. My version was answering a 30KB problem, which is exactly why nobody needed it. This one exists because sending a gigabyte to a browser apparently will become an ordinary thing to do in the age of AI.

0 views
Simon Willison 6 days ago

Understanding ChatGPT Work

OpenAI announced ChatGPT Work on July 9th, and have been furiously iterating on it ever since. It is an extraordinarily confusing and very powerful product. Here's what I've figured out about it so far. The more interesting version of ChatGPT Work is the one that runs in the cloud. This can be accessed via chatgpt.com or through the ChatGPT mobile apps. Let's call it Work Cloud . If you install the ChatGPT desktop app - the app that used to be called Codex - you gain access to a thing called ChatGPT Work that can access files and run programs directly on your computer. Let's call that one Work Local . This one feels more like regular Codex re-skinned to be less intimidating to non-software-developers. For the rest of this article I'm going to talk exclusively about Work Cloud. Right now, ChatGPT Work (in both flavors) is available only to $20/month and up subscribers. Free users and $8/month Go users do not have access. The interface for accessing Work is a tab selector, which presents it as an alternative to Chat: The obvious question is when should I use Chat, and when should I use Work? OpenAI's official answer to that question is: Use Chat when you want an answer, explanation, brainstorm, or short draft. Use ChatGPT Work when you want ChatGPT to complete a task with a clear outcome, such as a brief, deck, analysis, recurring update, workflow, or file you can review and use. I find that almost entirely useless, because I've been using regular ChatGPT Chat for all of those task categories for years! The better question then is what features does Work have that are missing from Chat? After extensive experimentation I think I've mostly figured that out: In Work, you get the option to pick GPT-5.6 Sol, Luna, or Terra, each with Light, Medium, High, Extra High, Max, or Ultra reasoning levels. You can also pick GPT-5.5 at Light, Medium, High, or Extra High. These look to be the same models that are available through the OpenAI API. Chat offers a different selection: 5.6 Instant, Medium, High, Extra High, and Pro (actually Extra High and Pro are only available for $100/month+ subscribers - $20/month subscribers cap out at High). It doesn't explain if those are Luna or Terra or Sol (I'm assuming Sol?). 5.6 Pro appears to be exclusive to Chat, with no equivalent in Work. My current understanding from using Codex is that Ultra is a special mode that more eagerly delegates to sub-agents. I believe ChatGPT Work sessions are billed against your Codex allowance, while ChatGPT Chat Sessions get their own, separate allowance. This may help explain the model availability differences. As a long-time fan of the Code Interpreter pattern - pioneered by OpenAI in 2023 - this is by far the most exciting feature of ChatGPT Work (Cloud) for me. The code execution environment can now talk to the rest of the internet! ChatGPT Chat can't do this - if you ask it to install additional software packages or interact with websites or APIs that access will be blocked by the container proxy. (Weirdly, back in January it grew the ability to install packages , but that doesn't seem to work any more. I wish they had better changelogs!) Claude's equivalent container has allowed restricted internet access since it launched last September . Claude can install packages from PYPI and NPM and clone repositories from GitHub. But that is about it: the allowlist of domains is very short. ChatGPT Work allows a whole lot more than that. It can be configured with a specific list of allowed domains, but the default appears to be open to all. This makes Work an incredibly useful tool. You can have it clone GitHub repositories, install their dependencies, then use them to interact with the rest of the web! Another killer feature of ChatGPT Work is the browser tool . ChatGPT Work can launch a full Chrome instance, load websites, fill out forms, and take screenshots. If a site requires sign in the browser can prompt you to take over and enter both passwords and 2FA codes, without round-tripping those credentials through the model itself. It can even run JavaScript against the DOM of loaded pages. I prompted: ChatGPT Work fired up a browser instance and ran the code: This feels a lot like my shot-scraper javascript tool, only now I can access it on my phone! ChatGPT Chat gets a fresh filesystem for each chat session. These cannot be accessed from any other session. In ChatGPT Work each session gets its own scratch folder - named something like - but each of those are persisted across sessions, so you can access files from previous chats. I have 171 folders in right now! As far as I can tell that volume is mounted to all Work sessions that are currently running - file edits from one can be instantly seen by the others. They don't seem to share the same process space though, and localhost servers running in one can't be accessed from another. ChatGPT Work has the ability to build and deploy entire websites, using Cloudflare Workers. These can have HTML and JavaScript and can run server-side features too, including stateful features on top of Cloudflare D1 and R2. Here's a simple site I built with this feature: london-pelicans-in-her-piety.simonw.chatgpt.site My prompt was: (A pelican in her piety is a fascinating piece of medieval Christian imagery - once you know about them you'll find them all over the place.) These sites default to being private to the user that created them, but you can make them public and (on team plans) share them with other specific individuals. There's not much to say about this one. ChatGPT Chat can't run sub-agents. ChatGPT Work can. This is very much a power-user feature: if you are running a complex project that can benefit from multiple parallel agents working together, Work can do that. Another feature that seems to have migrated from regular ChatGPT to ChatGPT Work at some point. You can prompt ChatGPT Work like this: This will schedule a prompt to run on that frequency. These prompts can decide that nothing interesting has happened, or they can decide to notify you of some new information. Update : Actually this seems to work in ChatGPT Chat as well. It's still worth noting here though, as it can be used in conjunction with other ChatGPT Work exclusive features. You can set a scheduled task to update a ChatGPT Site on an hourly basis, for example. An open question for me right now is how safe all of this stuff is. My lethal trifecta model warns about the risks inherent in any agent system that combines access to private data with exposure to untrusted content and a way to communicate stolen information back to an attacker. ChatGPT Work combines all three! I'd love to hear more from OpenAI about how they protect ChatGPT Work sessions against prompt injection attacks. I expect their answer is the same auto-review mechanism as Codex. Figuring this all out took way more work than it should have. I think there are two key problems here: If the ChatGPT Work documentation included the exact system prompt and tool descriptions used by the agent I wouldn't have needed to write this post. Shortly after publishing this article I had an idea. I started a fresh Work session and prompted: Here's the site it built , which includes details of 223 registered tools - though 6 of those are from my own personal MCPs served via datasette-mcp . I noticed that the only browser-related tool in the list was web.run , which has methods for running searches, opening URLs, and clicking links, but didn't look like the full story in regards to headless browser automation. This made me suspicious that something was missing, so I told the ChatGPT Work session that built that tools reference site: It turns out ChatGPT Work uses a lot of skills - 44 in fact! The control-browser skill explains how the browser works: Run browser setup code through the Node REPL tool. In this environment the callable tool id typically appears as . [...] The ability to interact directly with the browser is exposed through the runtime via the API. Before trying to interact with it, you MUST emit and read the complete documentation returned by in one go. So I told Work: Add the full output of await browser.documentation() to the bottom of the /skills/control-browser page And now you can read that on /skills/control-browser as well. A few more interesting Skills: You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options . Options to use Luna and Terra in place of Sol A code execution environment with Internet access A headless Chrome browser A persistent filesystem shared between sessions The ability to publish ChatGPT Sites The ability to run sub-agent sessions with Sol, Luna, and Terra Scheduled prompt automations (may be in ChatGPT Chat too) OpenAI explain Work in terms of what it's for, not what it actually does OpenAI still insist on hiding their system prompts and tools descriptions documents for creating files imagegen with tips on creating images with the tool pdf for both reading and rendering PDFs Spreadsheets for manipulating , , , sites:sites-building for creating ChatGPT Sites openai-docs for answering questions about itself data-analytics:build-dashboard for building data dashboards

0 views

Two Alleged ‘TeamPCP’ Hackers Arrested in Australia

Authorities in Australia have arrested two men believed to be members of TeamPCP , a prolific cybercrime and data extortion group blamed for perpetrating the longest running spree of software supply chain attacks ever. In a statement released today, the Australian Federal Police (AFP) said two men from Western Australia, aged 21 and 23, were arrested in connection with a “sophisticated cybercrime syndicate that allegedly created malicious open-source software to rob thousands of global businesses.” The AFP did not name the defendants, but KrebsOnSecurity learned the 21-year-old suspect’s real identity in June, and has been communicating with him ever since. This story includes interviews with TeamPCP’s self-described spokesperson, and examines clues left behind by the TeamPCP leader that likely led to his undoing. TeamPCP vaulted onto the cybercrime scene in late 2025, embedding malicious code in hundreds of open source software tools and extorting victims for profit. Members of the group made headlines by compromising corporate cloud environments using a self-propagating worm dubbed  Shai-Hulud , which added malicious code to open source programs maintained by developers whose credentials at public code repositories like GitHub or NPM were phished or stolen. Writing for Wired , journalist Andy Greenberg described TeamPCP’s core tactic as a kind of cyclical exploitation of software developers. “The hackers gain access to a network where an open source tool commonly used by coders is being developed,” Greenberg wrote in May . “The hackers plant malware in the tool that ends up on other software developers’ machines, including some who are writing other tools intended to be used by coders. The malware allows TeamPCP’s hackers to steal credentials that let them publish malicious versions of those software development tools, too. The cycle repeats, and TeamPCP’s collection of breached networks grows.” TeamPCP also has practiced something akin to cyclical recruitment. In May, the source code for the third iteration of Shai-Hulud was published online, and TeamPCP soon after launched a contest offering $1,000 in virtual currency to whichever participant could conduct the largest supply chain operation using the worm’s code. According to the contest rules, participants were scored based on the number of weekly and monthly downloads of packages they compromised — directly incentivizing them to target the most popular code libraries. A screenshot of a message from TeamPCP’s Telegram account, announcing the supply chain hacking contest. Image: dataminr.com. “TeamPCP has stated the competition is a recruiting opportunity and they intend to purchase all meaningful access harvested from participants’ campaigns,” the security firm Dataminr wrote . “The $1,000 XMR (Monero) prize is a recruitment floor and has been dismissed by the actor as ‘just like participation trophy,’ adding ‘if you find something good you will be paid way more,’ confirming the contest’s true function as talent identification and malicious access acquisition at scale.” In March, TeamPCP executed a supply chain attack targeting AI infrastructure by compromising the code for LiteLLM , an open source AI gateway that connects users to more than 100 different large language models. A recent analysis by the security firm CloudSEK found TeamPCPs attack on LiteLLM harvested cloud service keys and other secrets from more than 2,500 organizations, including many of the world’s top technology companies. In May, TeamPCP claimed credit for compromising at least 3,800 code repositories at the Microsoft-owned GitHub , after a GitHub developer installed a code extension that was compromised by TeamPCP’s malware. Security experts say TeamPCP is less of a hacker group than an amalgamation of threat actors from multiple cybercriminal gangs who sometimes work together toward similar goals. “It is not a structured criminal crew with a single operator,” said Austin Larsen , a principal threat analyst with the Google Threat Intelligence Group . “It is a peer community of individually-skilled actors, with one clear center of gravity.” That center of gravity is George Prepakis , an accomplished security researcher and self-described exploit developer who operates the Twitter/X profile @kernelstub . Earlier this year, @kernelstub tweeted a public invite link to a Matrix chat server he created and dubbed “Cybercats,” and TeamPCP and several other cybercrime entities have been using this server to communicate daily for the past several months. A screenshot of the Matrix chat server “Cybercats,” whose members used hacker handles associated with multiple distinct cybercrime groups that have occasionally collaborated on a series of supply chain and data ransom attacks over the past nine months. Kernelstub, like other administrators in the Cybercats chat, has been using his Twitter/X profile name as his handle in these Matrix communications, frequently tweeting references to other members and to conversations taking place in the Cybercats chat. In a number of cases, the corresponding X accounts for members of the Cybercats chat taunted cybercrime victims publicly before the incidents were reported in the news media. The Cybercats administrator listed at the top of the screenshot above — “ Boxturtle ” — is a close associate of TeamPCP who has been tweeting about the group’s conquests under the name @xpl0itrsturtle . This handle corresponds to a data breach broker active on Breachforums and Darkforums who has been selling data stolen in a wave of recent breaches at automobile manufacturers, including BMW Group , Audi , Honda , Mercedes-Benz , Volvo and Toyota , as well as data allegedly taken from Snapchat and SportRadar . The data leak site for the extortion group or handle “xpl0itrs.” The Cybercats administrator “ SeesawSec ” in the screenshot above is the alias of whoever is behind the cybercrime group known as Fulcrumsec , which recently claimed credit for data extortion attacks against the pharmaceutical giant Novo Nordisk , the data broker LexisNexis , and Avnet , a Fortune 500 distributor of electronic components. The data leak site of Fulcrum Security, a.k.a. Fulcrumsec. The Cybercats administrator “ @pcpcasper ” also has been using a similar name on X to discuss TeamPCP’s attacks and victims. This person has an extensive message history on Telegram, where their messages and shared videos show @pcpcasper is an active and vocal member of the National Socialist Network, a neo-Nazi political organization based in Australia. At one point in these chats, @pcpcasper shared videos and images of what they claimed was their cat, and several of those videos place this user in Western Australia. One source close to the investigation told KrebsOnSecurity that @pcpcasper was one of the two arrested, a claim supported by messages that @kernelstub posted online this morning. The Cybercats member roster pictured above also features an administrator with the username “ T ,” which is short for the now-banned Twitter/X profile @pcpcats , the account operated by the self-described TeamPCP spokesperson who was arrested today. As we’ll see in a moment, @pcpcats also is from Western Australia. By the time @kernelstub tweeted a public invite link to the Cybercats Matrix server, T/@pcpcats was posting only infrequently to the group chat, with other members often inquiring as to his whereabouts and well-being. The group’s collective concern related to @pcpcats’s tendency to blame his increasingly extended absences on the use of hallucinogens and other narcotics that kept him awake for days on end, but also caused him to crash in bed for several days after the highs wore off. The Cybercats member @pcpcats has used multiple nicknames on the cybercrime forums, including EllisD25/LSD on Darkforums, BulkDMT on Breachstars, and Express on Breachforums. These accounts are linked because they all advertised the same Tox ID and/or Session ID as instant message contact handles in their cybercrime forum posts. BulkDMT was also known on the forums as DMT Host , which was a virtual private server (VPS) hosting service that was peddled on Darkforums and Breachstars. DMT Host/EllisD25, posting on the English-language cybercrime community DarkForums in September 2025. Image: ke-la.com. According to the cyber intelligence firm Intel 471 , Express registered on Breachforums using the email address [email protected] . Intel 471 finds Express posted on Breachforums across a two-month period in 2025 using four different Internet addresses located in South Africa . On July 30, 2025, Express announced on Breachforums they were selling access to 14 gigabytes of data stolen from South Africa’s State Information Technology Agency. The threat intelligence platform Flashpoint recorded more than a year’s worth of messages from the TeamPCP leader’s alter ego on Telegram — Persy_PCP —  who claimed they split their life living between two countries [full disclosure: Flashpoint is an advertiser on this blog]. “I have these [files] as well, problem is these are in another country,” Persy_PCP explained to another user inquiring about a stolen data set in November 2025. Later that month, Persy_PCP complained, “My whole country is racist and they want people like me dead.” Flashpoint records show BulkDMT shared in September 2025 that “this country is going to fucking starve when they take the farmers land,” a likely reference to white landowners in South Africa who claim to be targeted by an ongoing genocide campaign . This tracks with public reporting on TeamPCP. Cyberscoop reported in June that Google had traced TeamPCP’s residential and mobile Internet address connections to South Africa, “indicating the primary operator was located there during at least some of its attacks.” BulkDMT also shared on the group chat at Breachforums that they were recovering from an addiction to methamphetamine. “My life is kinda fucked rn [right now], but that’s fine and there isn’t really a point in pouring so much emotional energy into that fact, my parents had money but I unfortunately got really addicted to some things so I don’t get to benefit from that. As long as I continue to survive, stay sober, and move closer towards my goals that’s enough drive and meaning.” The identity threat protection company SpyCloud finds [email protected] shows up in the registration of an account called ChristmasSnow on the cybercrime community Raidforums in 2022. Nearly all of the Internet addresses used to access that account came from ISPs in Perth, Australia, SpyCloud found. KrebsOnSecurity looked up all of those Perth IP addresses in passive DNS records maintained by DomainTools.com , and found one of them — 211.27.196.111 — for several years was used as a private file server by a family in Perth with the last name of Thomson . Those records show at least three hosts — ithomson.direct.quickconnect.to (a remote Synology server), kthomson0061.direct.quickconnect.to, and joshuawthomson39.myqnapcloud.com (a QNAP network storage device) — persisted at that address between 2022 and 2025. Searching on “ joshuathomson39 ” in the breach tracking service Constella Intelligence reveals an account at the freight forwarding company kwe.com created in the name of Joshua Thomson from Perth, Australia. The open source intelligence platform Epieos finds the phone number attached to that kwe.com account was used to register a Facebook profile for Josh Thomson, which says his family includes a brother named Ruben , his father Ian , and his mom Cindy. That Facebook profile also says Josh and his family are originally from Pietermaritzburg , in KwaZulu-Natal, South Africa, but currently living in Cottesloe , a beach-side suburb of Perth. A search in DomainTools for Ian Thomson and Australia unearthed five domains by the same registrant, including securecomputing.au , thomson.org.au , and thomsonfamily.net.au . Ian Thomson is a dentist in Cottesloe, and a biography says he graduated from The University of the Witwatersrand in Johannesburg, South Africa. Constella finds a [email protected] registered a number of accounts online, but Josh doesn’t seem to have much of a connection to dodgy cybercrime forums. His brother Ruben, on the other hand, has quite the presence on these communities, dating back to at least 2018. Constella reports [email protected] frequently reused the password “joshuathomson1,” and Constella further finds that password was used by just a handful of accounts, including [email protected] and [email protected] . According to Intel 471, [email protected] was used to register the user Yolosolo17 on the crime forum Altenen in 2018, and that user account was registered from the Perth address 110.141.230.15 . On Altenen, Yolosolo17 advertised free web proxies, as well as the domain rubenthomson.com, which was at one point used to sell steeply discounted iPhones. DomainTools says rubenthomson.com was hosted at 110.141.230.15 and registered to [email protected]. A cached copy of the domain rubenthomson.com from 2017 shows a login page underneath a banded stack of money. Image: archive.org. SpyCloud reports 10.141.230.15 was used by the email address [email protected] on Raidforums and [email protected] on Nulled, and that the same IP was used by the email addresses [email protected], [email protected], and [email protected]. SpyCloud also shows that sheepstealing Gmail address is tied to the accounts Sheep420 , YoloSolo117 and Yakuza.cc on Raidforums, and to the account “Sheep Stealing” on Hackforums. Intel 471 says [email protected] was used to register the account DingoFlour on Breachforums in October 2023, as well Sheepx on Altenen. Epieos reports that [email protected] is tied to an Airbnb account for Ruben, who described himself as a Web developer who went to school at the University of Western Australia and was living outside the country. “Hey, I’m Ruben, my friends call me Ellis . I’m a Perth creative who occasionally books rooms when visiting family and for photography.” Epieos also finds [email protected] registered an upwork.com profile under the name Ruben, who said his main skills are setting up secure server hosting solutions and PHP full-stack Web development. “I’m familiar with Linux, working with relational databases (SQL),” the Upwork profile reads. “I also script in Python mainly for writing social media bots.” The Upwork profile for Ruben Thomson in Cottesloe, Australia. Epieos further discovered [email protected] is connected to a Microsoft account for Ruben Thomson, and to a now-defunct GitHub account called XmasSnow/XmasSnowisBack that scammed people on the forums in 2022 by claiming to sell exclusive exploits for recently-released software patches (recall that [email protected] was used to register a forum account named ChristmasSnow). This same sheepstealing email address registered a Twitter/X account in 2026 called “Gone Fishing” that lists its location as South Africa. That Gmail account also left several reviews for businesses listed on Google Maps over the past seven years, but all of those establishments are located on the west coast of Australia. Business reviews in Western Australia left by the Google account sheepstealing at gmail.com. The people search service Pipl finds a 21-year-old Ruben Thomson in Western Australia who has a phone number ending in 979. A lookup on that number at Epieos reveals it is connected to a TikTok account under the name Ellis, and to a PayPal account in the name of Ruben Thomson. Finally, a search on the name Ruben Thomson from Cottesloe at the Australian government’s record of registered businesses finds he has incorporated or served as an official in multiple companies created since 2024, including Secure Computing Solutions , Tensor Industries , and another entity ironically named OPSEC Express . Recall that Express was BulkDMT’s nickname on Breachforums. Australian companies connected to Ruben Thomson. Image: abr.business.gov.au. It’s ironic because OPSEC is short for the term “operational security,” which refers to techniques and behaviors used to obfuscate and compartmentalize one’s real-life identity online, and using your cybercrime handle as part of your own company name is very much the antithesis of that practice. There is at least one other major opsec failure by Ruben that exposed a link to TeamPCP. In June 2025, someone using the name Ruben Thomson registered on HackerOne , a popular “bug bounty” program that seeks to reward and recognize researchers who agree to work with affected software vendors to help fix the flaws before publishing about their findings. What was Ruben Thomson’s chosen HackerOne username? Deadcatx3 , a nickname that has been flagged by multiple security firms as an alias used by TeamPCP. The HackerOne profile for “Ruben Thomson” uses the nickname Deadcatx3, which multiple security firms have concluded is an alias used by TeamPCP. Image credit: flare.io. In early July 2026, not long after having discovered clues about Ellis’s real life identity, KrebsOnSecurity interviewed the TeamPCP leader via Signal, where he was remarkably open about his activities and personal struggles [for the sake of simplicity, the TeamPCP spokesperson will be referred to from here on as Ellis]. Ellis claims he stopped doing cybercrime for TeamPCP in March 2026 — just before the attacks that compromised LiteLLM — and that at least one other individual has taken over the group’s leadership since then. Ellis shared that a year earlier he had just completed the latest in a series of detox and sobriety programs, and was two months sober when he reconnected with some old friends from the malware development scene. “One year ago I needed help monetizing some [GitHub credentials], I was two months sober and needed a distraction and something to keep busy as well as people to speak to,” Ellis said. “I had largely disconnected from my old circle, they had become very toxic and I needed to get away from the substances. Previously I had done some mass exploitation campaigns and grew up doing [malware development] and [capture the flag] contests. There were some friends who were also vending but had stopped a while, and one of them introduced me to some chats where I posted access for sale.” Prior to that, Ellis said, he was homeless and hopping between “some very unstable places.” “Blackhatting is fun,” he said. “There are actual rewards and incentives to learn and you grow with your team. Without qualifications, no employer will even take the time to hear you out.” Ellis claims he’s earned a grand total of about $20,000 for his activities with TeamPCP, and that it was never about the money or fame for him. Asked whether his experiences with TeamPCP might prepare him for gainful employment in a legitimate IT job, Ellis said he doubted it. “I am nowhere close to a skill level where I am comfortable, and this would take maybe half a decade of further experience,” he said. “I no longer have to choose between rent and food for that I’m grateful and so are the team members.” Ellis expressed no remorse over his cybercrime activities, and said he was grateful for the friendships and relationships built throughout his engagement with TeamPCP. The young hacker also seemed resigned to his fate, and told KrebsOnSecurity that he’ll accept the consequences if he’s ever arrested. “If I’ve already been found out then its out of my control, I’ll make peace with that,” he said. “Honestly, I think someone like me needs a lot of help that prison just can’t provide. If I had the funds to study different parts of the field and closer guidance, this would have turned out differently. But that’s a pipe dream and we both know this.” It is clear from reading Ellis’s posts to the group’s Matrix server chats that his struggles with sobriety are ongoing. On Thursday, June 25, Ellis told @kernelstub he was about to “trip” with his “homie.” “What kind,” @kernelstub inquired. “Ketty and some DMT,” Ellis replied, referring to the dissociative anesthetic ketamine and dimethyltryptamine (DMT), a powerful psychedelic compound that is found naturally in some plants but is also synthetically produced in underground lab environments. “There’s a little 2cb so we might throw that in the mix,” he continued, referring to another psychedelic compound by its chemical shorthand. Roughly two weeks before his arrest, Ellis told KrebsOnSecurity he was ready to leave his life of crime behind and was prepared to turn himself in, but that in the meantime he was making plans to tie up loose ends. Less than 24 hours later, the TeamPCP leader posted an image on Telegram showing a yellowish powdered substance in a baggie and on a scale, possibly synthetic DMT. The image shows the powder being weighed next to a series of small vape cartridges, two of which are open on the table in front of the photographer. An image posted by the TeamPCP leader to Telegram, advertising his acquisition of some type of psychoactive substance, most likely a synthetic version of the powerful hallucinogen known as DMT. The two defendants were arrested Wednesday morning. The AFP said the men face a combined 14 cybercrime offenses and are scheduled to appear in Perth Magistrates Court today. Charlie Eriksen is a security researcher at Aikido Security who has closely followed TeamPCP’s cybercrime campaigns. Eriksen said TeamPCP are a good example of a new kind of threat actor that does not fit neatly into the usual categories. “They are not a state actor, not quite organized cybercrime, and not purely ideological,” he said. “Their motivations seem to mix money, disruption, attention, and ideology.” Eriksen said that historically there has always been a meaningful gap between reading about an attack technique and being able to reliably turn it into an operational campaign, but that large language models (LLMs) and artificial intelligence increasingly are helping threat actors to bypass that knowledge gap. “You had to understand the research, adapt the code, troubleshoot it, build infrastructure around it, and then repeat that process across different targets,” he said. “LLMs have compressed that gap significantly.” According to Eriksen, this creates an environment where threat actors suddenly have the ability to operate at significant scale without having developed the operational discipline that traditionally accompanies that level of capability. Put another way, it sets the stage for cybercriminals who are capable enough to cause significant damage, but not necessarily careful enough to understand or care about the consequences. “They can be noisy, they can make mistakes,” he said. “They can leave evidence everywhere. They can take risks that a professional criminal group or intelligence service would consider completely unacceptable. But that does not necessarily make them less dangerous. In some ways, it can make them more dangerous.” In a recent blog post , Eriksen called TeamPCP’s Shai-Hulud worm the “best thing to happen to supply chain security,” because it forced GitHub and other public coding platforms to erect new security safeguards. In direct response to TeamPCP’s broad success at pushing poisoned versions of popular software packages, GitHub in late July introduced a three-day “cooldown” mechanism for Dependabot, the platform’s tool for auto-fetching newly shipped updates for any package dependencies. Cooldown periods are designed to help buy time for security tools and package maintainers to identify and remove any compromised versions. Other coding ecosystems like Python and various JavaScript platforms also added support for cooldown periods this year amid growing calls from security experts about the need for more widespread adoption of the safety feature. Eriksen said TeamPCP’s legacy is that they achieved in the span of a few months what the supply chain security community has been unable to do for years. “They managed to wake up Microsoft to the fact that they had become negligent in terms of security,” Eriksen said. “By compromising GitHub and stealing their source code, they humiliated Microsoft into action, making them finally act on what we had been asking them to do and take seriously for a while now.” Update, 10:08 a.m. ET: A story this morning from ABC News in Australia confirms Ruben Ian Thomson of Cottesloe was one of the two arrested. The 23-year-old suspect thought to be @pcpcasper, Michael Gaebler, also was arrested in Perth. ABC News reports that Thomson was denied bail (Mr. Gaebler’s attorney reportedly did not request bail for his client), and that both men will be held in custody until their next court appearance on September 18.

0 views
Himanshu Anand 1 weeks ago

I had some free time, so I tried to pwn V8

I am not working full time right now, which means I have free time which is dangerous. You start by reading one V8 blog post and somehow end up trying to make Google’s Chrome open with a ROP chain. That is basically what happened. I chained three public V8 bugs against the exact Chrome build used by Google’s v8CTF . The first bug leaked a compressed object address, second turned a garbage collection mistake into a fake JavaScript array and read/write access inside the V8 cage and the third used a JSPI and JS Dispatch Table mismatch to pivot the native stack outside that cage. Then I reused code already inside Chrome to open, read and print the flag. Real Google flag: yes . V8 sandbox escape: yes . $10,000 bounty: no . Getting the flag and winning the challenge turned out to be two completely different things. This is the full story, including the ugly reliability numbers and how much LLM assistance went into the work. There is a very specific kind of confidence you get after reading three browser exploitation posts. You do not know enough to build an exploit, But you know enough to believe that you probably can. That is where this started. I have spent years around application security, old Internet Explorer exploitation, heap sprays, ROP, ASLR, DEP and the usual fun. Modern V8 exploitation still looked like a different planet. Every useful pointer seemed to live behind another table, every object had a compressed representation. Every time I thought I understood the heap, the garbage collector moved it. So I decided to learn it the only way that works for me: choose one concrete target, define a ridiculous finish line and keep going until either the finish line or my patience breaks. Google had already provided the finish line. v8CTF is Google’s continuous V8 exploit challenge. Google runs a pinned Chrome build on its infrastructure. You connect to the service, solve a proof of work and give it an HTTPS URL. Chrome opens your page and A flag exists at . Your job is to make Chrome print it. That sounds simple because the sentence has hidden almost all the work. the protocol is tiny. the amount of browser internals between the first and last box is not. The official rules say an eligible submission can receive $10,000 . But the word eligible is doing a lot of work there. If you found and reported the initial bug, Google can treat the chain as a 0 day. If the bug was already public or somebody else found it, the chain is an n-day. Mine was very much an n-day chain as I did not discover the original bugs. I combined public work, adapted it to the exact target and built the missing pieces between those bugs. Still difficult but not a 0-day. The target was Chrome for Testing on Linux x86-64. It contained V8 at commit . Browser exploitation is not “Chrome 150-ish”. A map value, object layout, builtin offset, ROP gadget or pointer table rule can change between nearby builds. An exploit for the wrong minor version is often an expensive way to launch a crash reporter. The challenge disabled the crash reporter too, so sometimes it was only an expensive way to stare at silence. Chrome was launched with flags including: The flag needs an explanation. Chrome has more than one security boundarys, The process sandbox was disabled for this challenge, but the in process V8 heap sandbox still existed. The outer kCTF and nsjail isolation also remained. Native code execution in the renderer was enough to read the challenge flag, but getting ordinary corruption inside the V8 heap was not. I escaped the V8 sandbox into the native renderer. I did not escape Chrome’s process sandbox because the challenge had disabled it and I did not escape the outer jail. This distinction matters. “Chrome sandbox escape” would make a much better headline. It would also be wrong. If you remember old browser exploitation, the rough plan looked like this: Modern V8 has the same family resemblance. It has also put several locked doors between every step. The modern exploit was not one magical bug that immediately produced native code execution. It was a ladder of smaller capabilities. every box had a test. if a stage did not produce an observable result, it did not exist, no matter how convincing the theory sounded. JavaScript values need to represent integers, doubles, strings, objects, arrays and functions. V8 uses tagged values so it can quickly distinguish a small integer from a heap-object reference. On a 64-bit pointer compressed build, many heap references are stored as 32-bit offsets inside a 4 GB region called the cage. V8 reconstructs the full pointer using the cage base. This saves memory and limits where corrupted compressed pointers can point. It also means leaking one compressed pointer is useful but does not reveal Chrome’s native image base. The V8 sandbox goes further. It assumes an attacker may already be able to corrupt memory inside the heap cage and tries to keep important native pointers outside it. The simplified list of things standing in the way looked like this: So even after gaining arbitrary read/write inside the cage, the exploit was not finished. It had only earned the right to start fighting the next layer. The target build contained several issues fixed later in Chrome 150. I looked at V8, Blink, PDFium, Skia, ANGLE and other routes. Most produced crashes, partial capabilities or technically fascinating ways to waste a week. The chain that finally worked used three public CVEs. CVE-2026-15903 was an optimizing compiler bug, A safe-integer assumption was lost while V8 lowered a number-like value to a 32-bit machine word. TurboFan’s reasoning said the value stayed inside a safe range. The generated machine code disagreed. That disagreement could make read outside its intended string. This was useful because it affected the exact target, triggered from an ordinary web page and provided a controlled byte-reading oracle. If I placed many references to the same object nearby, the oracle could scan memory and find the repeated compressed pointer. It could read but It could not give me the write I needed. CVE-2026-15776 was a RegExp representation mistake involving and the largest positive Smi, . The vulnerable path incremented that value across the Smi boundary. The result became a heap-allocated , but one fast path treated it enough like a Smi that the old-to-young reference was not recorded correctly. After minor garbage collections, the RegExp could still point to an allocation that the collector had already recycled. Salvatore Gulizia, also known as Serotav , published excellent work showing how to reclaim the stale slot as a fake array. His public exploit depended on layout assumptions that were not stable enough in my target. The address oracle from the first bug supplied the missing location information. Bug one knew where the object lived but could not write and Bug two could replace the object but needed help finding the right layout. The first two bugs produced arbitrary read/write inside the V8 cage. The V8 sandbox still protected native process memory. For that boundary I reused the public JSPI and JS Dispatch Table issue tracked as Chromium issue , fixed by Jihyeon Jeong ( ) in commit . The short version is that a hidden fixed-arity builtin and its JDT entry could disagree about how many native stack arguments needed cleanup. A disagreement about stack cleanup is not harmless metadata confusion. It can move the return slot into attacker influenced values. That was the path outside the cage. The final exploit ran in a normal web page. It could not use or other d8 shell helpers. I trained the vulnerable functions through ordinary DOM event dispatch instead: The optimized reader believed its last index remained inside a 256-byte string. Generated code could select a 256-byte window outside it. I placed arrays containing 64 references to the same nearby and scanned for a repeated odd 32-bit value. Odd mattered because compressed heap pointers carry the object tag in the low bit. Repetition mattered because random memory contains plenty of odd numbers too. Sixty-four copies of one candidate are a much better signal than “this number feels pointer-ish”. The live run eventually printed: That address belonged to that process. It was evidence, not a reusable magic constant. V8 uses a generational garbage collector. New objects normally start in young space. Objects that survive can move into old space. When an old object points at a young object, a write barrier records the relationship so a minor collection knows the young object is still alive. The RegExp bug broke that bookkeeping. The old retained a pointer to the young , but the collector did not remember the edge correctly. A minor collection reclaimed the number. The pointer stayed. I sprayed attacker-shaped allocations and tried to win the freed slot. same address, completely different object. the collector sees reusable memory. the RegExp still sees lastIndex. I see a fake array. The trigger looked roughly like this: The reclaimed bytes described a fake packed-double array: With an attacker-selected elements pointer and a very large length, ordinary JavaScript indexing could read and write outside the original array. This was the old heap-spray idea wearing a modern garbage-collector costume. A renderer crash is not an arbitrary read/write primitive. A fake object that survives one property access is not a stable primitive either. I used a sacrificial double and required a complete round trip: Only after all of that passed did I call the primitive read/write. There was also a four-byte alignment problem. Compressed object fields sit on a four-byte grid. JavaScript doubles occupy eight bytes. Some values fit inside one double. Others were split across two neighboring doubles. This sounds like a small implementation detail because the sentence is small. The debugging time was not small. The reclaimed master array was also fragile. The rest of the exploit needed Promises, WebAssembly modules, external strings and many allocations. Any collection could inspect or move something I desperately wanted left alone. The useful fix was V8’s large-object space. Large backing stores are not compacted like ordinary small objects. I prepared three stable allocations: The lesson was not “disable GC”. The lesson was “give GC legitimate references it knows how to maintain”. At this point I controlled memory inside the V8 cage. ASLR still hid Chrome’s native image base. The External Pointer Table stopped the obvious attack. An does not store a raw native resource pointer that caged corruption can simply replace. It stores a protected handle. But the JavaScript string still had a writable length inside the cage. I enlarged that length while preserving the legitimate EPT handle. then trusted the corrupted length far enough to read beyond the native external-string allocation. Repeated external resource objects exposed a repeated vtable pointer inside the Chrome binary. For this exact build: That defeated ASLR for the current renderer. It did not provide unrestricted native write. It did not need to. The next bug supplied control flow. This separation was important: one primitive disclosed native addresses, another primitive controlled the native stack. I kept looking for one perfect native read/write primitive when two narrower tools were enough. JavaScript Promise Integration or JSPI, lets WebAssembly suspend when a JavaScript import returns a Promise and resume later. V8 preserves native execution state to make that asynchronous trick work. I created two suspended WebAssembly computations with and . Their Promises contained internal reactions pointing to genuine hidden handlers. Using caged read/write and , I recovered those handlers as JavaScript values. The vulnerable build allowed the hidden builtin and its JDT metadata to disagree about stack cleanup. I supplied a forged receiver and a deliberately mismatched call frame. At the controlled return, a gadget moved the native stack pointer into the large carrier backing I had prepared inside V8. the caller and callee disagreed about where the call frame ended. the CPU eventually asked my carrier array for directions. That crossed from corrupted JavaScript objects to native renderer control. That was the V8 sandbox escape. I did not need a reverse shell, a calculator or an executable memory page. I needed to read one file. The ROP chain reused code already present in the exact Chrome binary: Open, read, write. ORW. W^X remained intact. The exploit used short instruction sequences and PLT calls already present in Chrome. There was one final piece of nonsense. V8 heap pointers are tagged, so the native receiver pointer landed one byte past the aligned location where the caged writer naturally wrote. The ROP stream had to be shifted by one byte without destroying its neighbors. That is modern browser exploitation in one sentence: after crossing several serious security boundaries, you lose another evening to one byte. Local testing used the exact Chrome build inside Docker, a read-only synthetic , fresh profiles for every attempt and no Docker networking. I did not touch Google’s service until the complete ORW chain printed the local synthetic flag. The live client solved the kCTF proof of work, sent the hosted exploit URL and captured Chrome’s output. The important part was this: I stared at the final line for a while. A web page had entered headless Chrome. A compiler bug leaked one compressed address. A RegExp bug let me reclaim a stale allocation. A fake array produced caged read/write. An leaked the native image. A JSPI mismatch unbalanced the native stack. Existing Chrome code opened one file and printed one line. I got the flag. That part was not theoretical. I did not build this alone and I do not want to pretend otherwise. I chose the target, ran the experiments, debugged the exact Chrome build and decided what evidence counted. ChatGPT using the Sol model did a large amount of source navigation, experiment design and code drafting. I used other models to research alternative paths and challenge claims before trusting them. The LLMs helped with: There was no prompt that said “pwn V8” and returned a working exploit. The real loop looked like this: The models were useful and confidently wrong on a regular basis. They invented object layouts, treated unrelated crashes as progress and proposed beautiful exploit chains that immediately fell apart against the binary. If an idea did not produce a marker, a controlled value or a successful run, it did not count. This work made me more optimistic about AI-assisted security research and much less interested in AI-generated exploit claims without logs. Now for the less cinematic part. This was not a credible $10,000 claim, even though it recovered the flag. Two independent eligibility problems were visible. First, this was an n-day chain. The initial vulnerabilities came from other researchers. Google’s public sheet already showed a confirmed M150 n-day from July 13, before this flag was captured on August 5. The rules normally allow only the first eligible n-day for a deployed version. Second, the exploit was nowhere near the required 80% reliability. The final direct package succeeded in 1 of 5 fresh local runs. A separate tunnel-hosted tuning batch reached 5 of 10 . Those were different delivery conditions, so I am keeping the numbers separate rather than combining them into one nicer-looking lie. one successful flag proves exploitability. it does not magically turn the other failed runs into successes. Some old notes said . The preserved raw summary said . The raw logs win that argument. Even would only have been 60% anyway. The reclaim depended on GC timing, heap occupancy, allocation order, JIT tiering, native resource placement and startup noise. Successful runs were fast, often around four to seven seconds. They simply did not happen often enough. So the honest scoreboard is: Was I disappointed? Obviously. I am a security researcher, not a monk. But “got the flag” and “won the competition” are not interchangeable sentences. This project taught me that in a very expensive dialect of JavaScript. The complete PoC and reproduction notes are available on GitHub. Everything is tied to Chrome on Linux x86-64. This is an exact-build historical exploit, not a paste-into-current-Chrome script. When people hear “V8 exploit”, they normally picture a malicious website opening in Chrome. That is the dramatic version, but V8 exists in more places than one browser tab. The surrounding security boundary changes in every environment. A browser has renderer and process sandboxes. An Electron app may expose privileged preload APIs. A server runtime may hold cloud credentials. An isolate platform may place code from several tenants in one process. This exact historical chain does not compromise all those systems. The broader questions still travel: V8 exploitation is interesting because language semantics, compiler optimization, garbage collection, object representation, WebAssembly, native ABI details and operating-system security all collide in one process. It is several different security disciplines wearing one trench coat. Pin the exact binary first. Not the milestone. Not a nearby patch. Exact binary, source revision, platform and launch flags. Prove one primitive at a time. An address-leak marker is better than a browser crash that might have happened six stages later. Treat every allocation after corruption as hostile. Logging allocates. Errors allocate. Compilation allocates. First-time typed-array use can allocate. Any of them can trigger the collection that destroys the fake object. Use legitimate runtime machinery when possible. A real tagged slot that GC knows how to update is much more stable than hoping a malformed interior object survives forever. Separate disclosure from control. The leak defeated ASLR. JSPI supplied native control. I did not need one perfect native arbitrary read/write primitive. Count every failure. Retrying until one flag appears proves exploitability. It says nothing about reliability. Make LLMs pass evidence gates. Ask for source paths, hypotheses, harnesses and competing explanations. Do not let a fluent paragraph replace a successful run. I keep coming back to the live transcript. No bounty No new CVE No Chrome process-sandbox escape. Still one of the coolest things I have built. The best part of having free time is finally learning the things you kept postponing. The dangerous part is that occasionally the learning project starts printing signed Google flags. If you are learning V8 exploitation, do not begin by memorizing every pointer table. Pick one boundary. Build one observable capability. Read the source. Read other researchers’ work. Use the LLMs, but make them show their work. Then keep moving one box to the right. If you are still reading this, you are awesome. Thanks for sticking with me! If you want to discuss the exploit, V8 internals or the painful economics of getting a flag without getting a bounty, find me on Twitter/X . Thanks for reading. The exploit has to recover a real flag from Google’s infrastructure. Only the first submission for a given initial memory corruption bug is eligible. Normally only the first submission for a deployed V8 version gets that version’s slot. A 0 day is exempt from that separate version limit. An n-day flag must be captured after Google opens the nday window. Average runtime has to stay below five minutes. Success rate has to be at least 80%. Trigger a use-after-free or overflow. Spray until controlled data lands where the old object lived. replace a pointer or vtable. Leak a module address to defeat ASLR. Build ROP to work around DEP. Jump somewhere useful. Mapping public fixes to the exact vulnerable V8 revision. Comparing object layouts and source paths. Generating small diagnostic pages and local harnesses. Reading long debugger transcripts. Suggesting alternatives when a route died. Keeping track of which security boundary a primitive had actually crossed. Fact-checking this post against the exploit logs and official rules. Chrome and other Chromium-based browsers. Node.js server applications. Electron desktop applications. Multi-tenant systems built around V8 isolates . Embedded Chromium environments, CEF applications and WebViews. Official v8CTF overview Official v8CTF rules Chrome for Testing 150.0.7871.46 manifest Exact V8 source snapshot CVE-2026-15903 fix CVE-2026-15776 fix Serotav: From Regex to RCE V8 pointer compression The V8 sandbox V8 sandbox source documentation Orinoco garbage collector Introducing JSPI JSPI/JDT fixed-arity fix Start Your Engines: Capturing the First Flag in Google’s v8CTF Fuzzing to Zero-Day: Pwning v8CTF

0 views
Jim Nielsen 1 weeks ago

Have You Heard the Good News About Microlighter?

Dave Rupert wrote about shipping microlighter : a tool for handling syntax highlighting using the CSS Custom Highlights API . I saw his post the day he released it, and I had an implementation PR up for my blog by end of day. Then, like I do with so many things, I let it sit there. This is the period where my subconscious takes over. It does the work of, “How do I actually feel about that? Do I want to merge it? Do I have any regrets about what I did?” If I still want to merge it after a few days, that’s usually a good sign that I’ll be happy with the work. (Sometimes after a few days I say, “What the hell was I thinking?” and then it’s easy to simply close the PR with zero regrets.) Well it’s a few days later and I still feel good about it, so time to ship! My PR for this is pretty straightforward: Granted, there are trade-offs to this approach. I get it. Dave’s explainer for this tool on The ShopTalk Show vibed with me because I’ve been in his shoes many times: “Whoops, somehow syntax highlighting on my blog is broken again. Guess I need to fix it. Ugh. I’ve done prism , I’ve done highlight.js , I’ve done shiki . What should I do this time? Could I do this in a way that’s just less ?” He clarifies: I’m not coming at this like, “Everyone is doing it wrong!” I was just kind of like, “Could I do this in a way that suited me?” Well, this approach suites me. There’s a kind of conceptual elegance to it where syntax highlighting lives in the realm of a styling operation rather than a content transformation plus styling. In short: syntax highlighting, i.e. styling text, is a styling concern so solve it with CSS — no DOM manipulation required! Plus, I mean, how cool is it that the code on the website is the same as the code in the DOM?!? I guess this is how I know I still like working on the web, because seeing browsers do stuff like this that they couldn’t do before still feels really cool! Reply via: Email · Mastodon · Bluesky Remove dependency (and related plumbing) On paths that 1) match my post pages (i.e. ), and 2) have code on them, pull microlighter deps from a CDN and run it.

0 views

Concurrent Servers: Part 8 - Go

This is part 8 in a series of posts on writing concurrent network servers. In this part, we'll switch to Go and see how it tackles the challenges described earlier in the series. All posts in the series: This post assumes a basic familiarity with the Go programming language. As before, we'll start with a sequential server for the basic state machine protocol presented in part 1 . This is the main function: As in the previous parts, the server is "infinite"; it never stops serving new connections until it's explicitly killed. This is the function implementing the protocol for a single client; it takes a net.Conn value that represents a socket with a client connected on the other end: Rather than directly exposing OS threads, the Go runtime implements its own M:N scheduling of lightweight goroutines on top of OS threads. Using goroutines in Go is cheap - both in terms of syntax and developer effort, and in terms of system resources . Here's a version of our serial protocol server that serves clients concurrently by launching a goroutine for each client. The part of the code that's different from the previous sample is highlighted: The concurrent modification in this case is particularly simple because the server is infinite; there's no point waiting for these goroutines to finish (and hence no need for a sync.WaitGroup ). The parameters for server.ServeSerialProtocol are lexically captured from the enclosing scope and its return value is handled by the surrounding closure. Because goroutines are very cheap, this server is very unlikely to run out of resources due to launching too many goroutines; in fact, it will probably run out of something else - like file descriptors for sockets - first. However, sometimes it's still useful to limit the degree of concurrency - even in Go, and we'll discuss some approaches to do so in the following sections. Here are some scenarios in which it makes sense to limit the degree of concurrency in Go programs, even though goroutines are cheap to launch and operate: Let's switch to the primality testing server from part 4 for the rest of the post, because it represents a somewhat more realistic workload. As a reminder: the server receives numbers, simulates blocking by sleeping, and returns "prime" or "composite". The unbounded one-goroutine-per-client version looks almost identical to the previous code sample, except that the goroutine invocation calls another function: Where ServePrimeProtocol is [1] : The simplest way to limit concurrency in Go is by using a counting semaphore, implemented with a channel: The channel sem serves as a semaphore; note that it's a bounded channel with a maximal size. A token is acquired by sending to the channel, and released by receiving from the channel. When the channel is full, the send operation sem <- struct{}{} blocks until a token was removed by some other goroutine [2] . The type of the channel is struct{} which means "empty", or "no data". This is idiomatic in Go for channels that are used solely for their semantics, not to send/receive any actual data. Since launching goroutines is cheap and limiting concurrency is easy as shown above, the "worker pool" pattern is often unnecessary for scenarios like our server. Still, it has occasional uses (such as when workers have to maintain some non-trivial state across tasks) so it's worth discussing it here. Here's a variant of our primality testing server that uses a worker pool: A fixed number of worker goroutines is launched; these goroutines all receive "jobs" from the same channel. In the Accept loop, each client connection is sent to this channel as a new job and is picked up by the next available worker. As mentioned before, you would typically see a sync.WaitGroup somewhere to ensure clean shutdown of goroutines, but in our case it isn't necessary because we have a server that never exits. Do programmers have to resort to async / event-driven programming in Go? In my experience, almost never. Go was designed from the bottom up to be suitable for large-scale concurrency; goroutines are very cheap to create, have a tiny memory footprint and switching happens very quickly, all in user space. Measurements I ran back in 2018 have shown switching times of ~170 ns, as compared to 1-2 microseconds for threads on Linux. Moreover, Go already uses event-driven loops like epoll underneath for I/O. Goroutines that wait for I/O like sockets are effectively "parked" and consume no resources (beyond their small memory footprint); they are woken up by Go's runtime when their I/O descriptors are ready - this is very similar to how asynchronous programming works! That said, some people certainly do try to stretch their resources even more with direct asynchronous programming in Go when millions of streams are handled concurrently. All I'll say is that this is very rare, and an overwhelming majority of users never have to do this. In 2018, I wrote a post named Go hits the concurrency nail right on the head , and after several more years of active coding, I fully stand behind that statement. Go is extremely powerful and ergonomic for concurrent programs; while other environments go to great lengths to implement async-await style event loops in libraries, in Go it's already baked into the core language and runtime. You want event-driven I/O with very lightweight green threads that can also execute blocking tasks without worrying about the function coloring problem ? Go has you covered. All the code for this post is available on GitHub . Careful readers will note two issues with this code: (1) the protocol assumes the complete number is read from the socket in a single conn.Read call, and there's no framing - separation between distinct numbers; (2) the prime checking loop uses i*i which may overflow for large numbers. These issues are consistent across all the versions of the prime server in C, Python, JavaScript and Rust in earlier parts, because my focus was on the simplest possible code to demonstrate a point about concurrency. Part 1 - Introduction Part 2 - Threads Part 3 - Event-driven Part 4 - libuv Part 5 - Redis case study Part 6 - Callbacks, Promises and async/await Part 7 - Rust Part 8 - Go (this part) Tasks may be compute intensive, and the CPU capacity of any server is inherently limited. If too many concurrent goroutines compete for limited CPUs, they will all make very little progress. It may make more sense to have fewer tasks that complete in a reasonable time. Protecting potentially limited downstream resources, such as concurrent DB connections or other services. For example, if the server has to send requests to other services for each task, and these are rate-limited, concurrency will have to be carefully managed. Security reasons when work is dictated by clients; malicious clients can overload and crash a service that's too eager to serve, making it unavailable for legitimate clients.

0 views
Sean Goedecke 2 weeks ago

You should never be angry at work

I try not to give a lot of prescriptive advice about working in tech companies 1 . There are many ways to be successful, and every company works differently. If you’re shipping projects and your management chain is happy, it doesn’t really matter how you’ve accomplished it. However, there’s one thing that I do think is solid advice: you should never be angry at work . Anger in the workplace is toxic. An angry colleague immediately becomes a new problem to be managed, not a professional helping you manage problems. When someone is visibly angry in a meeting or in Slack, it kills the entire atmosphere: other engineers will often go quiet entirely, not wanting to make the situation worse. If you routinely “get heated” at work, the best-case scenario is that you’re part of a tight-knit team of confident people who aren’t put off by it 2 . No harm, no foul. But the second someone comes onto your team who’s not so confident, or you have to communicate outside of your team, it becomes a big problem. Healthy workplaces route around anger in the same way that networks route around damage. Emotionally unreliable engineers will get left out of conversations that might cause them to blow up. Decision-making will get done around them in backchannels. I’ve seen this become a self-reinforcing cycle: angry engineers aren’t consulted on key decisions, which makes them angrier, which pushes them even further away from the spaces where decisions get made, and so on. You can often find these engineers bitterly complaining that they keep the company together, but nobody ever listens to them. In my experience 3 , this is almost never true. Engineers who are highly effective tend to get listened to — at minimum by their colleagues, and eventually by managers and product managers who want to extract as much value as possible from them. (One reason this is true is that all successful projects involve working with other people, and if nobody listens to you, you can’t do that.) Why do angry engineers believe they’re important? Paradoxically, anger can be really useful to a software engineer . Angry engineers are rarely the ones holding the company together, but they’re also rarely useless . One surprising thing about working for big tech companies is that some engineers are not just unproductive, but actively net-negative : either because they’re incapable of doing useful work on their own, or because they’re sloppy enough that they create more work than they do, or because they’re so checked out that they literally do nothing. Angry engineers might be net-negative in a cultural sense, but in terms of literally solving tickets and shipping features, they’re usually well above average. Why is this? Anger often comes from caring about your work, and caring a lot is sufficient to make you a competent engineer . I’ve never worked with someone who genuinely cared about their work who wasn’t (or didn’t eventually become) competent. I actually think it’s healthy for an early-career engineer to sometimes get angry about their work, because it means they care a lot: it’s still a mistake in the moment, but it’s a “good mistake” . I certainly used to get angry — in fact, I wrote about the angriest I’ve ever been at work here 4 . But you have to move past it . Think of “caring about your work” as a vertical tube, unsealed at either end. You fill the tube by pumping in emotional investment from the bottom 5 . If you have too little, it drains away and you end up as a useless coaster. But if you have too much, it overflows and you end up as an angry engineer that people have to work around. One solution is to try and care the exact right amount: be invested in work a bit, but also have hobbies and a family and whatever else gives you perspective about your work problems. If you have a rich and healthy personal life, it’s hard to find yourself yelling at somebody about React state management. However, this is a tricky balance to maintain over time. Another solution is to care about different things. The reason too much caring overflows into anger is because what you care about is misaligned with what the organization cares about . If your interests are perfectly aligned with your company’s (for instance, if you primarily care about delivering shareholder value ), you can fit way more emotional investment into the tube before it overflows. Here’s some dangerous advice : showing a little bit of anger at work can sometimes be useful. It can be a good way to signal that you care, or to build rapport with certain people, or to draw attention to something you think is important. However, it’s still always a mistake to be angry. You need to be able to drop back to a friendly mode at will, which is very difficult when you’re genuinely angry. Being able to show a full range of emotion at work is good. It makes you more persuasive and more human. Being a fully professional robot is fine — you can have a successful career this way — but there’s always going to be some kind of uncanny-valley HR-ness to your work persona that will make it hard to connect with your colleagues. If in doubt, don’t show anger. It’s never wrong to be professional. However, if you can signal that you’ve got enough distance to separate your professional feelings from your real feelings, and enough perspective to realize that the stakes of a technical decision are fundamentally not that high in the grand scheme of things, it can sometimes be okay to show visible frustration so that people know you’re still human. Well-known software engineering personalities are often angry. It feels unfair to give too many negative examples, but obviously Linus Torvalds’ rants about Linux are a great example. Some of my favourite engineering talks are from Bryan Cantrill, who is sometimes visibly furious at his subject matter. There are too many well-known angry blog posts to list, but I’ll cite one I genuinely like: my Australian blogging colleague Nikhil’s post titled I Will Fucking Piledrive You If You Mention AI Again . Anger is a part of the general image of a competent software engineer. Many junior engineers learn from this that it’s okay to be angry. However, taking your emotional cues from engineering celebrities is a big mistake, for a few reasons. First, you are not Linus Torvalds or Bryan Cantrill . Torvalds is the BDFL of the most important software system in the world. Cantrill is the cofounder and CTO of his company. When these people are angry at work, people will not work around them, because they are the ones deciding what gets worked on . Once you’re the one in charge, you can get away with being emotional in the workplace 6 . Second, you don’t know what it’s like to work with these engineers . People give talks and write blog posts because they’re emotionally worked up about something. If your only exposure to a celebrity is via their conference talks and blog posts, you’re seeing them at something like their maximum emotional intensity. If you then take that level of emotion into your normal everyday work, you’re almost certainly overshooting. I’ve been reorged into dysfunctional teams, have had projects I enjoyed cancelled, and have worked on systems that were extremely chaotic. I can’t remember the last time I was actually angry at work. To be clear, I’m not successfully hiding my anger (unless it’s so repressed it’s invisible to me as well) 7 . Nor am I naturally a chill person. I’ve just reached a point in my career where I genuinely don’t get upset about work stuff. A cynical person might say here that I’ve stopped caring about my work, so of course I don’t get angry anymore. I’ve left the side of the “real engineers” — the Linus Torvalds and Bryan Cantrills of the world — and sold out for that sweet, sweet big tech money. I mean, maybe! It’s true that I’m less invested in specific technical decisions than I used to be. But I still care a lot about doing a good job, I still spend a lot of time tweaking and reading code, and I certainly get more done than I did when I was more emotionally volatile. Being angry at work feels good. It feels like proof that you’re working on something that matters, and that you’re personally having an impact. If you’re angry, nobody can call you a coaster. But anger is only a local maximum. If you can find your way to a different style of working, you’ll not only be more effective, but you’ll be in a far better place to have impact on problems that actually matter. Mostly, I fail . As I understand it, this is the work environment that most famously angry engineers came up in. My experience is certainly limited (a handful of companies, and maybe ten different teams or organizations). I can certainly believe it happens! About halfway down, in the section titled “it’s not your manager’s fault”. Emotional investment is a liquid with the viscosity of water. To a point. Even Torvalds famously said he’d gone too far with the anger and decided to turn it down a bit. I suppose I’m not the best person to judge whether this is true. If you work with me and I do come across as an angry guy, please do tell me. Mostly, I fail . ↩ As I understand it, this is the work environment that most famously angry engineers came up in. ↩ My experience is certainly limited (a handful of companies, and maybe ten different teams or organizations). I can certainly believe it happens! ↩ About halfway down, in the section titled “it’s not your manager’s fault”. ↩ Emotional investment is a liquid with the viscosity of water. ↩ To a point. Even Torvalds famously said he’d gone too far with the anger and decided to turn it down a bit. ↩ I suppose I’m not the best person to judge whether this is true. If you work with me and I do come across as an angry guy, please do tell me. ↩

0 views
Sean Goedecke 2 weeks ago

Readers can't identify watermarked AI text

In the last few weeks, I’ve been complaining that everyone is wrong about AI watermarking: it isn’t really anti-consumer and it doesn’t make the outputs any worse. The watermarking papers demonstrate 1 that this is true, but I thought it might be interesting to put it to a practical test. Given examples of watermarked and unwatermarked answers to the same prompt, could readers tell which is which? To find out, I vibed up 2 https://sgoedecke.github.io/watermark-quiz/ , a static site that quizzes readers. I used Qwen3-30B-A3B-Instruct-2507 on a rented H200 to generate thirty responses: three responses per question, one of which was secretly watermarked with SynthID-Text. The rented GPU cost around two dollars. To measure results, I just sent users to a different page for each score, and aggregated visitors-per-page in my analytics 3 . This would be easily spoofable if anyone cared enough to do so, but for a casual test I think it’s acceptable. The first round of traffic I got to the quiz (278 participants) had these slightly puzzling results: Pure random choice would lead to an average score of 3.33/10. However, the mean score here is 3.92. There is indeed a spike around 3/10, as expected, but there’s also a second weird spike at 6/10. Why is that? It turned out that the SynthID response was option A in six of the ten questions, so users who just selected the first answer for every question would get 6/10. Oops. I re-shuffled the questions and got these results: Now the mean is 3.4/10, much closer to the expected 3.333. There’s no spike around 6. We only had 73 people take the quiz after I shuffled the questions — most people saw it and took it immediately after I posted it to my LinkedIn and Hacker News — but given the previous results, I think that’s still enough to feel confident that people were just guessing randomly. So no, people can’t identify the presence of AI watermarks . Obviously this wasn’t exactly a scientific study, but it’s still pretty suggestive. If watermarks were really choosing random words that the model would never pick, you’d be able to sometimes tell from three side-by-side responses which one went down the weird watermarked road, right? I also hope that something like this can serve as a persuasive tool: if you’re worrying about what impact watermarking is going to have, and your intuition is unmoved by the mathematical explanations, having a read of the watermarked and unwatermarked responses might convince you that there’s really no difference in quality. The one-sentence explanation for why is that AI models already randomly select from a handful of top tokens, and watermarking just replaces that random choice with a bias that is predictable while still being equivalently “random”: as a simple example, instead of “pick randomly from the top three tokens”, you could do “count the letters in the previous ten tokens, take mod three, then pick that token”. Some notes from the vibing: GPT-5.6-Sol put extraneous text all over the page I had to get it to remove, it chose the now-very-recognizable styling that I had to rip out, and it built some kind of weird Javascript-driven static site instead of just the cross-linked pure HTML thing I would have built by hand. It took me about an hour (although I did maybe ten minutes of actual work). Umami, hosted on PikaPods. For my blog, I do also pay for Netlify analytics because I find JS-based analytics misses >50% of technical users, but for stuff like this Umami is fine. The one-sentence explanation for why is that AI models already randomly select from a handful of top tokens, and watermarking just replaces that random choice with a bias that is predictable while still being equivalently “random”: as a simple example, instead of “pick randomly from the top three tokens”, you could do “count the letters in the previous ten tokens, take mod three, then pick that token”. ↩ Some notes from the vibing: GPT-5.6-Sol put extraneous text all over the page I had to get it to remove, it chose the now-very-recognizable styling that I had to rip out, and it built some kind of weird Javascript-driven static site instead of just the cross-linked pure HTML thing I would have built by hand. It took me about an hour (although I did maybe ten minutes of actual work). ↩ Umami, hosted on PikaPods. For my blog, I do also pay for Netlify analytics because I find JS-based analytics misses >50% of technical users, but for stuff like this Umami is fine. ↩

0 views
マリウス 2 weeks ago

Flipper BUSY Bar

Yes, it is in fact real, I’m holding it in my hands, and after what feels like years of Flipper teasing everyone with this ominous device in various online posts, I can finally confirm that it is real. The BUSY Bar is a 250 gram desk device by Flipper Devices , the company behind the Flipper Zero and the still very much in-development Flipper One . It’s basically a little display that shows various things on a 72x16 RGB LED matrix, and as of writing this it’s main selling point is that can run a Pomodoro-style focus timer , and that it has a ful-blown HTTP API that’s available over USB, over the local network and over the internet, that let’s you control this thing. The BUSY Bar has a five-position selector on the top, that switches between the two focus modes ( BUSY and CUSTOM , which are functionally identical and only differ in their defaults), a OFF position that in reality is more of a sleep mode which turns both screens off, an apps position that currently only holds a clock, and a settings position for, well, the settings. A large mechanical button in the middle starts and pauses a session, a scroll wheel adjusts the timer and doubles as an OK button, and last but not least there’s a back button for when you have to navigate back. Speaking of back, the backside of the device has a 1.54 inch monochrome OLED that shows the timer, the battery percentage and the Wi-Fi, Bluetooth and USB indicators. This way the device remains usable to its own user as well, even when clipped to the top edge of a monitor using its built-in mount, pointing its primary matrix display away from its user. The device measures 168.6 x 55.2 x 40.8mm and weighs 250g/8.82oz. The body is made out of PC/ABS with a PC front and back panel, and the monitor mount padding is TPE. The bar fits monitors up to 21mm thick and I can confirm that it works on curved displays as well. However, if you have a particularly thin monitor (say, one of these portable displays) it won’t be able to sit on top of it. The full specifications, as published in Flipper’s own documentation , are as follows: The 72x16 matrix is driven by the ICND2153 , a 16-channel constant-current PWM sink driver with a 16-bit grayscale shift register, LED open detection and a pre-charge circuit for ghosting reduction, and the ICN2012 8-channel power switch. One thing that is a bit sad in 2026 is the 2.4 GHz limitation for Wi-Fi. In an office environment full of devices and microwaves the bar is on the most congested spectrum available. The USB side is also kept, let’s say lightweight , with its 12 Mbit/s maximum speed, which, however, is certainly enough for a virtual ethernet interface serving a web UI and an HTTP API. On the charging side the documentation asks for an 18 W or higher PD charger for the 2.5 hour figure, while the device itself only appears to use 5V⎓3A (15 W) and 9V⎓1.5A (13.5 W) as its PD modes. There is one discrepancy with regard to the display brightness, where the tech specs page lists no brightness figure at all, the product page currently says 400 nits, and the launch coverage from CNX Software and XDA both quote 800 nits. I don’t have the equipment to measure it, so I can’t really tell which it is, but I can assure you that even in a brightly lit space it’s plenty bright. Flipper published an official disassembly guide on iFixit , which is awesome. Its 21 steps describe a device that’s designed with repairability in mind. The back cover is held by 8 clips and comes off with a plastic card. Below it are 5 Phillips PH1 screws, one on the bottom and four on the back. The battery has a press-latch connector and needs to be disconnected before anything else. The display flex cables use spudger-release latches, the main PCB is held by 3 screws, the control PCB by 5 latches, the front display back cover by 6 latches and the button stabilizer by 3 screws. The monitor mount legs are friction fits. Nothing is glued and the battery is a standard 18650 cell on a 4-pin connector, which means a replacement is easily and cheaply available from most electronics shops. For a 2026 consumer device this is probably something that my fellow Right to Repair advocates will love. The firmware sources are on GitHub as . Most first-party code is GPL, the library is MIT, graphical assets are CC-BY 4.0 and fonts are OFL 1.1, all of which are declared in a REUSE manifest. The build system is FBT , the same SCons-based Flipper Build Tool used for the Flipper Zero , and the dependency list is a usual embedded stack with FreeRTOS underneath Flipper’s own abstraction, lwIP for TCP/IP, TinyUSB for the USB device side, Mongoose as the embedded HTTP and WebSocket server, mbedTLS for TLS and LVGL for the UI. The bar also includes JerryScript in , wired up through and a service. That is the same JavaScript engine the Flipper Zero uses for its scripting apps. With the engine already in the firmware the only thing that still seems missing is the documented way to load your own scripts onto the device. The BUSY Bar runs an HTTP server and speaks the same API over three transports, documented as OpenAPI 3.1 . Plugging the device into a computer over USB brings up a virtual ethernet interface with the device at a fixed , printed on the back of the unit. is the local web interface, is the API reference generated by the firmware currently on the device, and is the base URL for said API. No authentication is used over USB, but it can be used via Wi-Fi and it must be used when going through Flipper’s cloud. This request responds with the current power status. The battery current is in mA, and both battery and USB voltage are in mV, which means that you can graph the device’s own power consumption without any extra hardware. Note: Access over Wi-Fi is disabled by default and has to be turned on from the local web interface over USB first. Once enabled, you can pick a token for authentication, which would go into an header, if you decide to set one: Access over the internet goes through Flipper’s cloud with a bearer token generated at , scoped either to a single device or to the account: Flipper maintains for Python with both a synchronous and an client. It maps method names onto API paths directly, so becomes and becomes . That makes the OpenAPI document usable as the library’s reference documentation: The library also has a module that scales and re-encodes images and audio for the device, an mDNS discovery helper for , and a firmware compatibility check. On top of that there is an official TypeScript library for all the soydevs, and a community-maintained .NET client . And there is also a Zig library, but… more on that in just a moment . :-) The BUSY Bar presents itself to Matter as a single on/off endpoint, an emulated switch with a configurable startup state of , , or . Turning it on starts the BUSY timer and turning it off ends it, making the integration is a trigger. Reporting the state back to Matter requires switching on Settings ➔ Smart home , at which point focus sessions can power automations like dimming lights or locking a door when a timer is turned on. Pairing is done using a QR code on the back screen or in the web interface, and the device can be commissioned into multiple fabrics at once. The Home Assistant integration is done through the HTTP API using the generic REST facilities, which works in both directions, meaning the device as an automation trigger, and the device as an output for anything else in the house. The BUSY Bar comes with mobile apps for your smartphones. I have tested its iOS app and, well, it was okay, I guess. I’m not a huge smartphone app user to begin with, but I’ll give my two cents here. The app basically mirrors the current state of the bar and offers rudimentary control over it. When you start a timer and you have the app set up (via Flipper’s cloud) you’ll see the app pushing a permanent notification that displays the timer on your smartphone’s lock screen. It’s also possible to configure a Do not Disturb mode that prevents other apps from interrupting your focus session whenever a timer is currently running. To me these are gimmicks, but to others these features might be worth something. Having that said, the apps aren’t rated particularly highly and while I didn’t encounter any issues during the few days that I’ve tested the iOS version, the app did leave a somewhat cheap impression by the way it looks and functions. It felt like one of these apps that corporate boomers at large hardware manufacturers would come up with, falsely believing that they are in-line with what today’s generations might want. There are a few things that bother me, however none of them are actual dealbreakers. The Wi-Fi authentication is a single shared numeric key, constrained by the API schema to , sent in a plain header over unencrypted HTTP on the local network. At the four digit minimum that is a 10,000 value keyspace, and I have found no documentation of rate limiting. The access mode enum also includes an value alongside , which means that the API can be opened on the LAN with no key at all. Hence, it’s probably a good idea to use a ten digit key and keep the device off networks you don’t control. Then there’s all the coming soon . Installing user apps, the JS SDK, the Windows application, and the expanded app library, those are all future promises. I don’t doubt the Flipper team that they will eventually arrive, but I could imagine that for a non-technical user it is probably very frustrating to have bought a device that can barely do anything at all at the moment, especially on a Windows machine. The device that arrives today is a focus timer, a clock, and a status display. Lastly, the price. It launched at USD 179 for waiting list members, then USD 199 for the first 3,000 units, with USD 249 quoted as the eventual retail price. At 249 it is a very hard sell, especially in the current software state. If you’re buying this because you’re a technical user and you really want to fiddle with it, it might be worth the Pesos, but as I’ve demonstrated in the past you can build a similar device significantly cheaper yourself, especially if you’re already deep into the tinkering rabbit hole. Flipper built the device I would have expected them to build, which I mean as a sincere compliment. The hardware is over-engineered for a status light in the same way that Flipper hardware always seems to be, with a real mechanical switch, a real encoder, a replaceable 18650, an official teardown guide and no glue anywhere in it. Whether it is worth the money depends entirely on what you intend to do with it. As a device that tells your coworkers to go away, it is way too expensive and not at all effective, because people who interrupt you are not deterred by a sign that tells them not to. Let me put it this way: For roughly $50 below the BUSY Bar ’s retail price you could place one of several Smith and Wesson models on your desk and it would likely be a more effective way to deter co-workers from talking to you. However, as a small, well-built, fully scriptable RGB matrix with an 8 GB filesystem, a WebSocket, and an elaborate priority system, so that several programs can share one screen without overwriting each other, it is the most open and probably best thing in its class, and I expect the community will find uses for it that Flipper hasn’t thought of yet. PS: Turning off the BUSY bar is like quitting Vim, in the sense that it doesn’t offer an obvious way to do so. Yes, the switch on top has an “OFF” position. However, that simply turns off the displays, but it keeps the busy bar running and connected to WiFi. If you want to fully shut down the device so that it won’t consume any battery, you will have to put the switch into the “Settings” position, navigate to System , Power , and Shutdown , and confirm the poweroff with Yes . Only then the device actually turns off. As mentioned before, I have a little bonus that I’d like to share with this review, which is a Zig library that implements the BUSY Bar ’s current OpenAPI specification as closely as possible, and that brings a command line tool that lets you control the device over its HTTP API. The library supports all of Zig’s platform targets as it only uses Zig’s library, and it is fairly lightweight and easy to use. I’m using it with my BUSY Bar and it has been working great for me. The command line tool contains a few quality-of-life features like simple commands for starting and stopping the busy mode, which would otherwise require manually writing JSON payloads. Long story short, if you’re one of the people that have ordered the BUSY Bar and are maybe looking to integrate it into Zig tools, or even just into your desktop environment using your own scripts, I invite you to check out the repository . If you’d only want the CLI tool to play around with your BUSY Bar you can find builds for every supported platform over on the release page on GitHub .

0 views
James Stanley 2 weeks ago

Foiling a Protohackers email spam bot

I've been receiving lots of "Undeliverable Mail Returned to Sender" lately for Protohackers signup attempts. Protohackers login is via a "magic link", so attempting to sign up or log in results in sending an email. But none of the email body is user-controlled, so I don't really see the logic in abusing this form to spam people. One email address has been put in over 100 times over the last 3 days, and I received "Undeliverable Mail Returned to Sender" each time, because it is a GMail address that doesn't exist. What's the logic in this? Most of the email addresses did exist however and presumably the spam either reached them or was filtered by GMail. Some ideas I can think of: someone griefing particular users by bombarding them with signup spam for hundreds of services they don't use someone trying to get me specifically banned from GMail by making me send lots of unsolicited emails to GMail addresses some grey-hat chaos-monkey type operation trying to nudge all website operators into locking down forms that can cause email sending a weird botnet communicates internally by triggering Protohackers signup emails to itself, and the timestamp of the email allows them to reliably communicate about 10 bits at a time?? I think the first one is the best idea but I still don't really see why you would do this. Although it's a better reason than the others, it still doesn't seem like a good enough reason to actually bother. I did already have a rate limit of 60 emails per recipient per day, and a burst limit of 5 per recipient per minute. I don't really want to stop people from being able to log in as many times as they need to, but getting 60 spam emails per day for a service you don't use is obviously too much. I did tighten the rate limits to 10 per day and 2 per minute, but really we don't want to be sending any spam. At any rate, I wanted to stop this. The goal is to stop whatever bot is sending these emails, without impacting legitimate users ( be they man or machine ). I noticed that all of these signup attempts were originating from the same netblock: 169.58.0.0/17 , apparently operated by Contabo . I'd rather not specifically discriminate against particular netblocks, both because legitimate users could be using the same netblock, and because a bot can easily change its hosting or use proxies. But the fact that it always used the same netblock makes it easy to identify, and the fact that it comes back every few minutes makes it easy to investigate. So my first mitigation was to add a tiny JavaScript proof-of-work, on the basis that a simple bot is probably not executing JavaScript. I was surprised to find that this actually didn't help. As an experiment, I kept ramping up the difficulty on the proof-of-work, and the bot was still successfully submitting the form even when it was taking over a minute to calculate the proof-of-work. So I've left the proof-of-work in place, but back down to a trivial level so as not to inconvenience real users. The next thing I did was selectively put the Bot Forensics collector script on the page only for clients within 169.58.0.0/17, with the idea that this would quickly reveal identifying features of this particular bot that I might be able to filter on without causing collateral damage. I was disappointed to learn that the bot never posted off the Bot Forensics beacon. If you were using Bot Forensics as general-purpose bot detection, this would kind of be the ideal case. If you refuse to send emails for any session that has not posted a good beacon, then this misbehaving bot is blocked and you don't really care what the beacon would have contained. But Bot Forensics is a bit too invasive for me to want to put it on the page for every user, and by this stage I was mainly motivated to learn more about this particular bot. And in any event, I don't actually have a problem with bots using the form in principle, I only have a problem with abuse of the form, whether by bot or by human. I wondered if the reason the bot wasn't sending the beacon was simply because the proof-of-work blocked the page so it couldn't compute the beacon. So my next experiment was to put a 10-second timeout between completing the proof-of-work and sending off the email. The idea was that the page would then have a good 10 seconds in which to send off the Bot Forensics beacon. Surprisingly, the 10-second timeout inhibited sending the email! Even though it previously spent over a minute calculating the proof-of-work. The bot must be waiting for inactivity and then closing the page after something less than 10 seconds. A 10-second delay is still a bit much to be imposing on legitimate users though, so I tried reducing it to 3 seconds, and then the bot was back to successfully sending emails. Although we weren't getting the full beacon content from Bot Forensics, we could still see: the bot is fetching the collector HTML for the iframe it's fetching other resources included inline in the HTML it's fetching resources requested by the JavaScript code it is able to send POST requests for exception logging but it is not POSTing the full beacon (The exception that we log is expected, it's just a failure trying to fetch a resource which doesn't exist.) I have a list of all of the User-Agent headers seen from the Contabo netblock . I'm not saying all of these are the malicious bot, but I suspect the majority are. ChatGPT points out that this list is probably from UserAgentString.com , good find ChatGPT. Despite seemingly choosing a User-Agent at random from that list, the sec-ch-ua header always lists "HeadlessChrome", example: So this does give us one way to block this bot with extremely low chance of causing collateral damage to legitimate users: we refuse to send email for any request that has "HeadlessChrome" in the sec-ch-ua header but not in the User-Agent header. That way we still don't block legitimate users even if they are using headless Chrome, as long as they're not messing with the User-Agent header. Let's keep that one in our back pocket, I'd really like to get a bit more of a smoking gun. I made the Bot Forensics collector send back a much smaller beacon, synchronously, and discovered: timezone is set to Europe/Berlin screen size is 1280x720 it doesn't have any custom functions injected into the page, that's disappointing, they're normally my favourite thing to look at navigator.platform is "Linux x86_64" but navigator.userAgentData.platform is edited to suit the User-Agent header So apart from having "HeadlessChrome" in sec-ch-ua but not User-Agent , the mismatch between navigator.platform and navigator.userAgentData.platform is another thing we could filter on. This bot does sometimes use a real headless Chrome User-Agent , and it is its most common one, but the vast majority of requests use the other weird ones. At this point I noticed one other bizarre behaviour from this bot: shortly after sending the signup email, it tries to load the user profile page, even though that page is not linked from the signup page. What's the angle there? Maybe this is some kind of automated vulnerability scanner that thinks it might be able to access random people's accounts simply by sending the email and speculatively browsing to the profile page? I literally don't understand why you would even check this. Even if it worked, which it doesn't, even if they click on the link, because that only authenticates the session that clicked the link and not the one that sent the email... but even if it worked, what benefit do you get from hacking someone's Protohackers account? Anyway, I'm out of time and stopping for now. So changes in response to this bot are: email sending now requires a (tiny) proof-of-work, and the JavaScript code includes a 1-second sleep; this doesn't stop this bot but might stop others rate limits reduced from 60/day and 5/minute to 10/day and 2/minute backend now refuses to send email for clients who have inconsistent "HeadlessChrome" and "Linux x86_64"; this blocks almost all emails from this particular bot And the Bot Forensics collector is now removed, even for clients from Contabo. If you find you now have trouble logging in to Protohackers, I'm sorry, please let me know. Also if you can work out what this bot is actually trying to achieve I'd be really interested to know. If we have to do any more on this, I think I might try a proof-of-work system that starts out easy but drastically ramps up in difficulty based on how many emails have been sent to that recipient, or from that client netblock, in the past day. someone griefing particular users by bombarding them with signup spam for hundreds of services they don't use someone trying to get me specifically banned from GMail by making me send lots of unsolicited emails to GMail addresses some grey-hat chaos-monkey type operation trying to nudge all website operators into locking down forms that can cause email sending a weird botnet communicates internally by triggering Protohackers signup emails to itself, and the timestamp of the email allows them to reliably communicate about 10 bits at a time?? the bot is fetching the collector HTML for the iframe it's fetching other resources included inline in the HTML it's fetching resources requested by the JavaScript code it is able to send POST requests for exception logging but it is not POSTing the full beacon timezone is set to Europe/Berlin screen size is 1280x720 it doesn't have any custom functions injected into the page, that's disappointing, they're normally my favourite thing to look at navigator.platform is "Linux x86_64" but navigator.userAgentData.platform is edited to suit the User-Agent header email sending now requires a (tiny) proof-of-work, and the JavaScript code includes a 1-second sleep; this doesn't stop this bot but might stop others rate limits reduced from 60/day and 5/minute to 10/day and 2/minute backend now refuses to send email for clients who have inconsistent "HeadlessChrome" and "Linux x86_64"; this blocks almost all emails from this particular bot

0 views

Concurrent Servers: Part 7 - Rust

This is part 7 in a series of posts on writing concurrent network servers. In this part, we discuss how the challenges described in earlier parts are tackled in the Rust programming language. All posts in the series: Several years have passed since the previous parts were published. I've recently went over them to make sure the information presented is still relevant and all the code samples build and run using modern toolchains. I strongly recommend reviewing the previous parts before reading this one. This post assumes a basic familiarity with the Rust programming language. It will only explain Rust constructs when we encounter code that wouldn't appear in an introductory book or tutorial. The first few parts in the series focused on a socket server that implements a simple state machine protocol. See part 1 for a complete description of the protocol. Let's start by showing how this protocol is implemented in a basic sequential Rust server: With the function serve_connection defined as: As a reminder, this server version is sequential because it accepts clients one by one; the main loop blocks on serve_connection until it's done (the client closes the connection), and only then goes back to accept the next client. Clearly, handling clients one by one won't do. In part 2 , we've discussed approaches that use OS threads to handle clients concurrently. Let's start with the unbounded one-thread-per-client solution in Rust: The spawn method returns a Result<JoinHandle<T>> ; on success, we allow the handle to be dropped at the end of the loop iteration. In Rust, this detaches the thread; we don't actually wait for it to complete. This is reasonable for our code sample, because the loop is infinite ; it never terminates anyway. The potential for runaway threads is just one of the issues with the unbounded threads approach discussed in part 2. The solution is to use a fixed thread pool. Before diving into the code, a quick note on the design: the thread pool is a fixed set of threads that await "jobs" and handle them to completion. In our case a "job" is serve_connection for a specific client. There are many ways to implement a thread pool; for our use case, I went with a set of threads that all get a shared channel to which the main thread sends jobs. A worker thread picks up the next job from the channel, serves it to completion, and goes back to waiting for the next job. Here's how this looks in code: What is Receiver ? It's a type from the crossbeam_channel crate: Rust's builtin channels in std are mpsc - multi producer, single consumer, but what we need for our job queue is a channel that supports multiple consumers (the worker threads). While std does have mpmc , this is an experimental API only available in nightly versions at the time of writing. Therefore, I've opted to include the crossbeam_channel crate that provides well-tested mpmc channels for this sample [1] . And here's the main function: Note that our job channel is bounded - it has a fixed size. This helps naturally implement a backpressure mechanism - if too many clients connect, the following clients will have to wait - the main loop blocks on tx.send and won't accept additional clients on the socket until jobs are cleared from the channel. In parts 4, 5 and 6 of the series we've discussed event-driven , or asynchronous servers. Let's see how it's done in Rust. Specifically, part 6 presented a gradation from callbacks to promises to async/await mechanisms; Rust supports all of these and - as you'd expect - modern code is usually written with async/await while hiding all the details of promises (called futures in Rust) underneath. Without further ado, here's our simple state machine protocol in asynchronous Rust: Rust takes an interesting approach to async programming: it supports some of its fundamental building blocks (like futures and the async and await keywords) in the core language, but leaves the actual async engine implementation (the thing that implements the event loop) to external crates. By far the most popular crate for async programming in Rust is is tokio , so that's what we're using here. After reading the JS code in part 6, the Rust snippet above should appear fairly familiar, except perhaps the explicit tokio task "spawn". Instead of enqueuing a callback on the connection returned by listener.accept , the code spawns a tokio task, which can be seen as a green thread , and hence uses similar terminology [2] . These tasks must not issue blocking calls; therefore, they are supposed to use tokio's I/O utilities instead of the usual, blocking std utilities. In fact, we have to implement an async version of serve_connection to make this work: Note how similar this code is to serve_connection from earlier; the only real differences are the await calls on socket reads and writes [3] , and the types involved. For example, instead of a std::net::TcpStream used in the synchronous samples, here we're using tokio::net::TcpStream . Tokio has an underlying dependency called mio to handle non-blocking APIs for all kinds of I/O. It wraps OS-specific event loops like epoll to do so efficiently. While most of the series has been using a simple state machine server as the driving example, part 6 switched focus to a server for primality testing which simulates long compute tasks. Let's see how this is done in Rust with tokio: This code is very similar to the previous snippet conceptually; isprime is: Note that this sample demonstrates a job that can block (simulated with a sleep in this case). This can be problematic in an async context, as the tokio documentation explains . One potential solution would be to dispatch a blocking task to a separate thread pool and use tokio channels to communicate with it; this is similar to the approach we've taken in the thread pool sample above. Part 6 also included a version of this server that caches data on a local Redis instance; the goal was to demonstrate the complexity of event-driven code when additional layers of callbacks are added and how async/await can help mitigate that. Here's our Rust version of this server, using the redis crate (that has a tokio component enabled explicitly to support async calls): In conclusion, while Rust provides excellent support for async programming, it doesn't solve its inherent issues like function colors and the need for careful separation between blocking and non-blocking tasks. These issues are typically surmountable with some extra care, and async programming with Tokio in Rust is very popular due to its performance benefits. All the code for this post is available on GitHub . Part 1 - Introduction Part 2 - Threads Part 3 - Event-driven Part 4 - libuv Part 5 - Redis case study Part 6 - Callbacks, Promises and async/await Part 7 - Rust (this part) Because of the function color problem , the redis crate has a connection constructor specifically for async: get_multiplexed_async_connection . Here we have an example of shared state between tokio tasks - the Redis connection. Note that we don't require any particular synchronization because MultiplexedConnection is Clone ; cloning it to different tasks is safe - and in fact that's what we do for each new task. There's no magic here; if you look inside MultiplexedConnection , you'll see that it already has all the synchronization mechanisms implemented internally, as needed. Due to the magic of async/await, the code in serve_client is nice and linear. We simply await on the Redis call, and once it's back we continue with the rest of the handler. Since we're using an async Redis connection, in case waiting is required, control will be ceded to some other task that's not currently blocked on I/O.

0 views
Pete Warden 3 weeks ago

Why I ported Moonshine to Javascript

One of the most common requests I’ve heard from developers is an in-browser version of Moonshine that can run on a web page. In theory this should be straightforward – we already built MoonshineJS for the previous generation of models, and the core library is written in portable C++, so emscripten can compile it into WASM. There have even been some interesting community porting projects but I held off on official support until I had time to do it justice. I knew that porting the C++ core was just the beginning. Building something that would be straightforward for web developers to use required a lot more: After a lot of work, I finally have a version ready for feedback. The easiest way to try it is on the new moonshine.ai home page, where you can now see everything from a minimal transcription example to a full-blown Granola-style meeting note taker . As an open-source project, all the code for these is available and the simple examples include code snippets in-line too. Here’s one that shows how to run speech to text on a web page, to give you a flavor of the API: You may still be asking yourself why I made supporting Javascript in the browser such a priority? A lot of “X ported to WASM” stories end up being Hacker News bait without having any practical uses. The evidence that drove me was: I’m excited to get feedback on how to improve the initial version, and I’m looking forward to hearing about what people build with it, so please come by our Discord channel if you’d like to join our community. High-level APIs that were both idiomatic for browser Javascript and consistent with the other Moonshine language bindings. Infrastructure for testing from units to full web pages. Integration with the existing CI and deployment process. Examples that were interactive and showed the key capabilities of the library, with interactive inline code. Larger applications that demonstrated and tested how the framework runs in real-world conditions. Improved support for in-memory models and data files. This was involved a lot of changes to the core library, because while there had always been some methods that took memory buffers, coverage was patchy compared to loading from files. Clear developer demand . It came up frequently as a wishlist item when talking to users. Javascript’s dominance . Python rules machine learning, but JS is the most common language for applications, web and server-side. Advantages over alternatives . Voice interfaces are clearly only going to grow in importance over the next few years, but browser APIs are neglected and server-based alternatives are slow and costly compared to our on-client framework. Obvious applications . Dictation and meeting note taking are popular use cases for speech technology already, and talking with AI bots is becoming a lot more common too. Technical alignment . Deep in my bones I know that voice interfaces want to run on the client. The current status quo of streaming audio data to a server just to get text and intent back only exists because models used to be too large to run on consumer hardware. Today even household appliances have enough compute horsepower for local voice agents . It offends my engineering sensibilities to see old approaches linger on purely out of inertia. Speech wants to be free to use and local, just like all our other input devices like keyboards, mice, touchscreens, and cameras. Porting makes that possible on the web. Options . These days a lot of us have to frequently switch between languages and operating systems, and the power of AI coding assistants only increases the pressure to rapidly port applications. A library dependency is a big commitment, and knowing that it will be available anywhere you’re likely to run in the future makes the risk of betting on a framework much lower, even if you don’t need the option in the end.

0 views

Who’s Tracking You? Use This New Service to Find Out

It can be daunting to determine who’s responsible for showing ads on the websites we visit, or who’s harvesting data from the mobile apps we use every day. That information is already semi-public, but it is not easily parsed and traditionally much of it has remained walled away in the hands of large advertising platforms. Not anymore: A powerful and free new service called DecryptAds scrapes and correlates this adtech data and makes it simple to quickly learn a great deal about the entities that are tracking you. A Decryptads summary of the advertising partnerships declared by espn.com. The newly launched decryptads.com says it is constantly scraping the files that websites and apps make publicly available to disclose the companies that are permitted to run ads or collect user data. These files include: – ads.txt : all of the adtech companies and data brokers that may run ads or harvest data from the site; – app-ads.txt : entities that can harvest data from or display ads on mobile and smart TV apps; – buyers.json/sellers.json : the entities buying, selling or reselling ad inventory for a given site or app. Zach Edwards is chief research officer for DecryptAds and a threat researcher at the security company Infoblox . Edwards said he and two other founders decided the service was needed because the adtech data in these files is generally only useful when it can be cross-referenced to build a more complete picture of the advertising ecosystem for each website or app. “It’s an adtech tool but we’re trying to approach adtech from a security perspective,” Edwards said. “It’s really built for a lot of privacy and security use cases that have been dramatically underserved.” Those use cases, he said, include tracking down the source of malicious ads that try to foist malware on targeted users, identifying ad networks located in adversarial nations, and detecting the fast growing swarms of AI-generated slop websites and apps. And as decryptads.com demonstrates, these potential security and privacy threats are near impossible to detect just by viewing a single apps.txt or app-ads.txt file. “Supply-chain integrity issues rarely live in a single file,” the site explains . “They show up as broken cross-references between ads.txt, app-ads.txt, and sellers.json files; as cloned declaration sets across unrelated domains; as seller removals that only make sense when viewed across exchanges; and even as supply paths in bid logs that never actually appear in any given publisher’s authorized-seller list.” A search in DecryptAds for the hugely popular sports network espn.com reveals 143 ad partners and 19 registered data broker domains are listed within its ads.txt and app-ads.txt files. That data broker information is gradually becoming available because four states — California, Oregon, Texas and Vermont — have recently passed laws requiring data brokers to register if they buy or sell data on consumers from those states. DecryptAds reports that almost half of those data brokers are collecting geolocation data from espn.com visitors who aren’t blocking ads, while another three disclose that they collect device fingerprints and sensitive personal information. A visual representation of the complex ad supply chain declared by espn.com. Image: decryptads.com. DecryptAds also makes it easy to learn the beneficiaries and national origins of the advertising firms lurking in apps and websites, displaying a conspicuous warning when adtech partners of an app or website are based in “geo-risk” areas like China and Russia, or in countries with strong financial and political ties to both — such as Cyprus and the United Arab Emirates (UAE). According to DecryptAds, espn.com works with four different advertising entities that are based in either Russia, China or the UAE, including the adtech firm Between Digital , which lists a New York address. However, the dossier on Between Digital flags them as a Russian firm, showing that their publisher offers (PDF) are processed through Alfa Bank , Russia’s largest private commercial bank and one of several financial institutions placed under U.S. sanctions in 2022 after Russia invaded Ukraine. KrebsOnSecurity sought comment from both Between Digital and the company’s founder, and will update this story in the event that either replies. A search for several top U.S. military news websites — including armytimes.com , airforcetimes.com , defensenews.com , navytimes.com , marinecorpstimes.com and federaltimes.com — shows they all allow Between Digital to serve ads and track users, as well as two entities in the UAE and another in the ownership secrecy haven of Panama. DecryptAds reports that Between Digital is collecting ad data on approximately 55,000 partner websites. The “Geo Risk” section of decryptads.com. Pivoting on Between Digital’s app-ads.txt file reveals hundreds of domains featuring simple web-based games that are frequently interrupted by ads. Edwards said Between Digital’s own declarations show the company is listed as both a publisher and a reseller on approximately two-thirds of their portfolio. “It means they are basically playing both sides of the bidding equation, which creates opportunities to direct client spend at your owned and operated properties or client infrastructure, essentially creating opportunities for conflicts of interest,” Edwards told KrebsOnSecurity. “The problem we have right now is that for years we’ve had almost no one policing these ads.txt and app-ads.txt files.” The Opera Web browser remains quite popular, and probably many users are unaware that since 2016 it has been majority owned and controlled by the Chinese company Kunlun Tech (the operational headquarters of Opera remain in Oslo, Norway). Opera.com’s profile at DecryptAds identifies 27 registered data brokers collecting information, including 15 adtech partners in the UAE, six in China, three in Cyprus, two in Russia and one each in Hong Kong and Ukraine. DecryptAds makes clear, however, that these companies represent just seven percent of the adtech partners specified in Opera.com’s ads.txt and app-ads.txt files. One feature of DecryptAds that sent this author down multiple hours-long research rabbit holes is its Legal Dossier lookup , which takes several minutes for each search but eventually churns out oodles of useful information about who owns a particular domain or app, when it was registered, and any aliases or relationships it may have to adtech companies and other websites or apps. For example, last month KrebsOnSecurity wrote about researchers from Bitsight who found that an extremely popular line of TV streaming sticks called H96 quietly rent out each user’s Internet connection to strangers. Bitsight also discovered that when these devices aren’t being used to stream pirated video content, they are spoofing themselves as mobile phones clicking ads on AI-generated slop websites . Bitsight concluded that the same Chinese company that made several of the malicious apps common to all of these H96 streaming sticks — the Fengwo Group — also also ran the network of ads and AI slop websites being clicked on by tens of thousands of these devices that are pretending to be mobile phones. Examples of ad landing pages linked to the Fengwo Group. These sites were designed to show ads only to H96 devices that were spoofing their device type as mobile phones. Image: Bitsight. A DecryptAds legal dossier on the (now dormant) Fengwo Group domain name for the AI slop website pictured on the left in the screenshot above ( medicalbeautyhub dot com ) shows it shares a seller ID ( 1674071 ) with a gaming website — giacoloredstones[.]com — which features yet another seller ID ( 103488000 ). Pivoting on that latter seller ID reveals hundreds of active websites within Russia’s Yandex ad system featuring extremely low-quality games or simple utilities that pepper visitors with ads. Edwards said that when advertising networks suspect a given advertiser is engaged in unauthentic clicks or displaying malicious ads, very often those networks will quietly remove the offender from their list of approved partners without letting anyone else know about their suspicions. This practice, he said, makes it easier for dodgy adtech firms to avoid accountability and continue victimizing others. To address that visibility gap, DecryptAds features a quiet removals feed that records and correlates all of the sellers.json removals across ad exchanges for the same seller domain or name. A screenshot of the Quiet Removals Feed at decryptads.com. “The way the adtech industry works, someone will write a report about ad fraud and only share it with their own clients and they won’t make it public,” Edwards said. “The ban is just removing them from the sellers.json file, but they told nobody. One day it was there, the next it was gone. So if you’re trying to navigate who is suspicious, that’s usually tough to do because there are a lot of adtech companies removing things all at once.” Malvertising, the term given to the practice of inserting malicious ads that foist malware or redirect visitors to phishing pages, remains an all-too-frequent occurrence in the modern adtech industry. But Edwards said these malicious ads are far more commonly found now on newly generated AI slop websites than on high traffic destinations that typically employ a variety of technologies and third party tools to quickly flag bad ads. “None of these slop AI content farms are paying for that kind of protection,” he said. “They’re just signing up the lowest quality partners, and it essentially becomes a greased rail to target the users of those sites with malicious ads. Most malvertising attacks don’t happen on espn.com or huffpost.com, but rather [on] some lower quality content farm and someone just went there because it came up in a search.” Edwards said the AI slop websites are populated with machine-generated blog posts and images, and cover a wide array of themes from home improvement and decorating to food recipes, hunting, cars and consumer technology. He said organizations that get hit with malicious ads are often at a loss for what to do next, unaware that in most cases the answer is one of the entities listed inside the website’s ads.txt or app-ads.txt file. “A lot of serious organizations are starting to understand that if we’re not breaking down this ad data, we’re not going to know who’s targeting government people with zero-click payloads on an almost daily basis,” he said. Edwards maintains that truly getting a handle on the malvertising and AI slop problems will require more data-sharing by the major ad networks. Specifically, he says those platforms do not broadly share what’s known as the “supply chain object” or SCO, structured data attached to each advertising bid request that lets buyers see every seller, reseller and intermediary involved in passing an ad impression from the publisher to the final buyer. “That SCO tells you who sold it or resold it, and who was the final entity that bought the impression that served that malware payload,” Edwards explained. “You may see the malicious zero-click redirection, but without the supply chain object — which is only served server side — you won’t know who targeted your people with malware and won’t have a way to try and prevent it properly. But if we can encourage the adtech industry to expose that SCO, it will get easier to find the culprit behind any one bad ad.” DecryptAds also offers an application programming interface (API) that allows researchers to automate queries and integrate the site’s functionality into popular AI platforms. The only sane reaction to the examples described above is to block all online ads outright. This approach is broadly endorsed by security experts because it also makes it more difficult for adtech firms and data brokers to build detailed profiles on you and track your movements around the web and in the real world. However, much depends on how you normally prefer to browse the Internet, and how much trust you place in third party browser plugins and extensions. For those primarily surfing via a regular desktop or laptop Web browser, uBlock Origin Lite is an excellent free and well-maintained open source option. uBlock Origin also should work with mobile browsers like Firefox, but apparently only on Android-based devices. Adblock Plus is a decent option for iPhone and iPad users. For power users, Adblock and uBlock Origin both support custom blocking rules from easylist.to , which publishes a frequently updated list that removes most advertisements from webpages. The well established browser extension NoScript blocks all non-approved Javascript code, and it generally does a fine job blocking most ads from loading. However, script blockers like NoScript may not be suitable for average users who don’t enjoy constantly having to referee which scripts should be allowed to load so that each site displays properly. More technically inclined/adventuresome readers should strongly consider a hardware approach to blocking ads at the local network level, because that is easily the cheapest, most secure and scalable way to do it. A tiny, low-cost and broadly available computer known as a Raspberry Pi can be turned into a powerful ad blocker for all devices on a local network when fitted with a microSD memory card and a free program called Pi-hole . Once you’ve set it up properly and changed your router’s network settings to use the Pi-hole’s DNS sinkhole and DHCP servers, it should prevent ads from displaying on any devices connected to that network. Bear in mind that ad blockers often do little to block ads and/or tracking that occurs from within mobile apps that users have chosen to install on their devices. Many websites now push users to install a mobile app, supposedly in order to more fully access and enjoy the site’s services and content. But in my experience, they’re not doing this because the user experience is somehow way better on the app (as LinkedIn tries to convince us non-app users several times a week via email). On the contrary, I find most mobile apps to be horribly designed, annoying, and/or completely unnecessary, and when given the option I will almost always choose to interact with a website or service directly in a Web browser. No, the cold truth is that big web destinations tend to get pushy with their apps because they make it easier for these companies to keep you on their platforms longer and to collect (and in many cases resell) far more precise data about who, what and where their users are. Also, companies pushing customers the hardest to install mobile apps always seem to liberally opt everyone in to having their data used to train large language models these days. So be cautious about the apps you install on your mobile devices ( including any smart TVs! ), and poke around their listings at DecryptAds if you want to learn more about their privacy practices and any relationships they may have to adtech firms.

0 views
daniel.haxx.se 3 weeks ago

curl performance

tldr: the live version is here: https://curl.se/perf/ How fast is “fast” and is it good enough? Does it run as fast now as it did before or was there a regression? What exactly needs to be fast? How fast is it? These are questions that many projects and products face, and in curl we are no different. Yet, performance testing and comparisons are hard and full of landmines and time-wasting efforts. For many years we have occasionally brought up the idea of a performance test suite for curl only to shut it down again because the challenges seemed hard and no one was volunteering to do this. This week it changed. I started out trying to find existing projects that host performance results for Open Source projects so that we could just feed our results something else and get great visualizations and data management. I did not find any such. I then took a look at what existing tools there are for this purpose, and most pointers seemed to suggest that Grafana is a popular and maybe even a good solution to build something like this with. But man, that is a complicated machine and it felt more than a little overwhelming just figure out where or how to start with it. I decided to postpone that take as well. I decided that instead of trying to do this the best and optimal way – I shouldn’t let perfect be the enemy of good – I would start out by doing the things I know how to do and take it as far as I can one step at a time. Something should be better than nothing . Performance testing needs decently stable system conditions so that repeated runs produce reasonably similar results, when all involved factors remain identical. This is basically impossibly to accomplish using most cloud infrastructure since those are almost always shared with countless other users. At least on the cheap and free tiers we use. We probably need our own dedicated hardware for this, but instead of trying to figure out where to get that and arrange for that, I would start by running performance tests on my own local development machine. I am a single user on this and it has many cores and runs decently fast. It should be good enough to get this going on. I created a first shell script that updates the curl source code from git, it configures and builds it. Then it runs a bunch of tests, outputs a bunch of data and logs all the output in a single log file. I started out with a few simple tests. How fast does curl download a 100 GB file from localhost, how many allocations and how big allocations does it need for a single HTTP download? My second script parses all the test log files from the previous builds and generates summaries and graphs for them. To make it possible for humans to see how the performance changes between builds and ideally to automatically detect when something changes more than what should be tolerated. As I am a graph addict already since before , and that journey has taught me a little gnuplot , I decided that even while there probably are much better tools and fancy JavaScript things that could be used, I don’t know them and learning them now is an endeavor I rather avoid. So I stick to what I know and can get results with quickly. A third script is invoked from a crontab every twenty minutes, sets up some variables and invokes the runner script. Once the basics started to work, I showed my curl friends the early versions and I soon created a new git repository for the code . After a little more poking, I soon made my locally produced performance test summary get packaged and automatically transferred to the curl website after each build, and voila, the first public curl performance tests were live and public. Getting this data available immediate triggered curl developers. It only took hours until we had the first proposed changes to improve some numbers, and soon we had a few merges to that affect. Visibility really helps! The performance numbers we get are still varying to a certain degree, partially of course because I still use my machine for my daily development things, but also because most of them do real (localhost) networking and that is by its nature a little… varying . The system builds and runs a new round every twenty minutes and it does that using the latest commits from git. This setup makes it sometimes run many rounds on the same commit and it might also mean that it sometimes updates and get several new commits at once, so it might skip a round for some commits. I might reconsider this design later, but since it is still a twenty minute time window, the number of commits is still limited. When the script makes multiple build rounds on the same commit, it accumulates the numbers and for the graph it stores the maximum, the median and the minimum value. It helps show the variation per commit and allows us to cram more into the graphs. It is still early days, but there will be a maximum limit to how many commits that can be displayed in a single graph and still be helpful. HTTP/2 parallel download speed through 261 builds spread over 31 build rounds Distribution To help visualize the distribution and data spread per test, I created a separate illustration that shows the minimum, maximum, P25, P75, medium and mean values in a Box-and-Whisker Plot . A Box-and-Whisker Plot showing the HTTP/2 parallel download speed data distribution. Changing conditions An obvious downside with me just storing build logs in files, is that it will not scale up to the millions. I did however decide that I’m not designing this system for that. At least not now. Performance tests are highly specific and dependent on the exact machine it runs on, the exact third party libraries and their versions that are used, the other components involved in the tests, such as the servers, and more. I expect that we will change conditions for the tests every once in a while that makes it hard to compare the current numbers with past numbers. Therefore I think the performance test numbers and values are primarily useful in the short term. To help us spot if we land something that subtly and unintentionally degrades something. To detect extremely slow and long-term changes in performance and even making sure we can better survive wiping all the existing build logs etc, I introduced a concept I call stakes . As in a stake pole. A marker. An arbitrary threshold set manually for each specific test. This value can be used to measure performance test results against, now and later. As conditions change and maybe something makes the results go up or down and we are fine with those changes because they are motivated and expected, then we just change the stakes. If it works out, I might try to have the system automatically detect and maybe highlight tests that deviate too much from its set stake (at least if done in the wrong direction) . It could be a signal that something bad was merged. As with everything in life, things are often balanced out. We already ran into this when we eagerly merged several changes to reduce the number of allocations done for a single HTTP download, only to realize that one of the optimizations we did had the side-effect that it expanded the size one of the main structs maybe a little too much… Improvements in one area might come at an expense in another. With sufficient tests and data we can improve curl for users, and at the same time make sure that our changes don’t come with a cost we are not prepared to pay. Exactly how to make the balance is of course a question we need to deal with, discuss and decide. Possibly for every change we do! As I write this, we have 24 tests and a full test round completes in about six minutes on my machine. We can of course do multiple builds using different hardware, different operating systems, different build options, different third party libraries and different test servers to check more angles of performance, and I am certainly open for and prepared to do that going forward. I will however first let this single-flavor run for a while so that we get more data, get a change to tweak it and make it as usable as possible for curl developers. As with everything there is no end to what we can make this do. This is a start. I sure we can take it further as we move along. In particular if people join in and help out. Both with ideas and proposals for visualizations, graphs and new tests to add, but also with actual pull-requests and code. Over the last year, we have merged, on average, about 10 commits per day. If we keep this pace up and this performance test setup can show 100 build rounds conveniently into a single graph, that is just ten days of development. Probably not enough. Once we reach one hundred builds or so in the first graphs I need to consider adding separate long term graphs that use select data-points to display data development over a longer time. Some googling told me the Largest-Triangle-Three-Buckets, or LTTB for short, is a fine algorithm to use for this. I now do a separate “long term” graph that “downsamples” the full range down to something that can be shown in a reasonable way. I suppose we will see properly in the future how this works. The stake thing I mentioned is one way to help us spot gradual performance changes over time. Another googling told me that there’s a Mann-Kendall Test + Sen’s Slope algorithm to use to identify trends in graphs like this and it can be used to plot a trend. It might work as a helper to better identify… yeah, the data trend for each test. The HTTP/2 parallel download speed trend at a specific moment Developing This setup has only existed for a few days. There is lots to do, lots to learn and much more to experiment with. Your comments, help and pull-requests will be appreciated!

0 views
NULL on error 3 weeks ago

As gambiarras mais impiedosas que já fiz: parte 1

Gambiarra, de modo geral, é conhecida como uma espécie de quebra-galho ou atalho para conseguir algo usando a criatividade, muitas vezes de forma pejorativa. Ressalto que, neste texto, a ideia é justamente enfatizar a criatividade diante de grandes desafios. Certa vez, enquanto trabalhava com aplicativos mobile e livros digitais, fui encarregado de renderizar um livro em um aplicativo Android nativo. React Native ainda não existia. Talvez o Sencha Touch já existisse, mas, de qualquer forma, os tablets-alvo eram muito lentos e tinham pouquíssimos recursos. Pois bem, o que você faria nessa situação? Fácil, não é? Renderizaria as páginas do PDF como imagens JPEG e criaria um aplicativo para paginá-las, a.k.a. um livro digital. Não, claro que não! Seu gerente gosta de desafiar você e não gostou nem da qualidade das imagens nem do espaço ocupado em disco. Então, ele propôs usar Adobe Flash. Sim, naquela época ele ainda existia, embora já estivesse no fim da vida. Mas como? Ninguém sabia. Foi então que tive a ideia de criar uma WebView de um pixel por um pixel e embutir o Adobe Flash nela para renderizar as páginas sob demanda e com a máxima qualidade. As páginas viriam de um arquivo , pois o software usado para criar os livros exportava a arte vetorial para SWF. Nos PDFs, por algum motivo, tudo era convertido em bitmap. Mas surgiu outro problema: como transferir dados entre o aplicativo Android, escrito em Java, a WebView, em JavaScript, e o Adobe Flash? Criei uma WebView de um pixel por um pixel com o Flash Player rodando dentro dela. Na época, essa era a única maneira de executar Flash no Android, pois o Adobe AIR ainda não existia. Fazendo o Java chamar , eu conseguia executar uma função JavaScript e passar o bitmap renderizado da página solicitada. Sim, o bitmap inteiro era transmitido como uma string. Por sorte, a WebView não tinha uma limitação de 4.096 caracteres, ou algo semelhante às limitações comuns em servidores HTTP. Portanto, era possível transmitir páginas muito grandes e em alta resolução. Feito isso, bastava repassar os dados para o Flash. Mas como? Exemplo simplificado: No lado do Flash, em ActionScript: Então, no lado da WebView, em JavaScript: Feio? É, eu sei. Mas funcionou perfeitamente. Passamos a ter páginas com alto DPI, zoom, rotação e tudo mais. Como bônus, ficou bem rápido, pois o aparelho precisava renderizar cada página apenas uma vez. Isso acontecia em menos de meio segundo. Depois, bastava desenhar a imagem na tela. :-)

0 views
Martin Fowler 1 months ago

Fragments: August 4

There’s been a fair bit of publicity of the Open AI “rogue agent” that hacked into Hugging Face . This prompted Anthropic to check what their models were up to and, to my complete lack of surprise, discovered three incidents where models had gained unauthorized access to data in other organizations. Simon Wilison concluded : It’s abundantly clear now that running evals of cyberattack potential in models is a spectacularly risky business. Every AI lab needs to pay attention to this. Keeping a close eye on what’s happening in those sandboxes is crucial It strikes me that this is akin to a virus escaping from a laboratory. It makes clear that the model builders are not putting sufficient controls in place to prevent these lab escapes. They are morally responsible for any consequences of this, and that should extend to legal liability too. The bigger concern however is that this same kind of thing can happen with any organization running open-weight models. Lots of labs playing around with dangerous tools and little idea how to contain them. We are sitting in state that Johann Rehberger describes as the Normalization of Deviance in AI . No big disasters have occurred yet, despite all of these worrying signs. But when does our Challenger-moment appear? ❄                ❄                ❄                ❄                ❄ If the sense that we’re in the calm before a storm of rogue AIs worming their way into sensitive software systems isn’t enough, there’s also knowledge that AI is also a financial bubble. Big advances in technology, whether it be railways or the internet, come with bubbles, and those of us old enough to remember the dotcom bubble see all the signs of that now - only bigger. The problem is that bubbles may be obvious, but the way they grow and pop, particularly when they pop, isn’t as clear. The dotcom bubble was widely understood to be one, indeed the chairman of US Federal Reserve talked of irrational exuberance . The trouble is that he said this in 1996, and the bubble took years to grow and burst. Even after the bubble popped, an investor would have experienced an excellent 10% per year gain since 1995. So with that in mind, what to make of the warning signs of this bubble? There are various folks calling out flashing red lights, but I confess I’m not enough into financial and economic analysis to gauge how reasonable these warning signs are, or how seriously to treat the sources pointing to them. Those caveats aside, I’ll mention a couple A substack called “Groundbreaker” calls out a parallel to mortgage crisis of 2008/9 . They say the key indicator of that event was “the second derivative” - that is the point when the rate of increase of prices started going down. The point being that the fuel for this bubble, like many bubbles, was that people believed prices were going to keep increasing, and thus it was good to invest. Once the rate of price increases started slowing, then that was a sign that this confidence was starting to ebb, and an early signal of the crash to come. They see the AI bubble as similar, a credit driven asset cycle, where the assets are data centers rather than houses. The article’s argument seems sensible, but the problem with an argument like this is that it’s all very well to say this flashing red light flashed before the last financial crisis, but it doesn’t talk about how often the light has flashed without a following disaster. Another anonymous Cassandra-wannaby is “Hedgie” a financial X-poster pretending to be an intelligent hedgehog. They noted that Alphabet’s revenue is up, but they are spending even more on capital investments . Much of their gains came from paper increases in the value of their stock in Anthropic, which is highly dependent on the bubble’s continuing expansion. Is this a sign that Google is resting on increasingly shaky financial foundations? Chatting to some of my friends closer to all this, they don’t think Google or Anthropic are the weakest link. They think OpenAI and Oracle are the companies most exposed. We’ll need powerful magnifying glasses to find a suitably sized violin for those companies should they collapse. But is this motivated reasoning? After dodgy sounding anonymous people on the internet, here’s a story from a more trustworthy source giving lots of details on Oracle’s investments in AI , much of it for building data centers that power China and Middle East efforts. “Well-respected A.I. analysts” indicate that Oracle provides over 20% of China’s known A.I. computing power. Doing all of this has created a mountain of debt: Oracle’s debt-to-equity ratio is 500%, compared to 15% for Alphabet. Also on more concrete and less anonymous grounds, there’s been a crash in South Korean memory stocks . Is this a leading sign of a wider collapse? Or should we remember that the late 90s saw five stock market corrections of over 10%, each time recovering, before the bubble finally popped. ❄                ❄                ❄                ❄                ❄ All this talk of rogue AIs and popping bubbles sounds rather dreadful, and John Prideaux made perceptive analysis of this dread risk . Pundits like to point out risks of disaster: A good way to sound smart is to predict that there is a 20 or 30% chance of something awful happening. A p(doom) of 20% is big enough to avoid charges of complacency, but small enough so that you probably won’t be called on it. This is what came to mind when Mr Musk told our editor-in-chief that the probability of ai wiping out humankind was 20%. These are worse odds than Russian roulette with a typical revolver. Anyone who truly believes that should be doing everything they can to prevent the construction of data centres. If they are not, that’s an indication that on some level they do not really believe what they are saying. I grew up with a steady dread of nuclear war, thinking our chances of making it to the end of the 20th Century weren’t terribly good. That fear seems quaint now. Here’s hoping that I’ll feel that way about AI in thirty years time. But meantime, as Eric Evans said in a recent talk: “be nice to your AI, just in case”. ❄                ❄                ❄                ❄                ❄ It’s common to disparage government services, including those on the internet. So I feel compelled to mention an efficient interaction with the government. In this case the credit goes to gov.uk , where I just filled in an online form to renew my electoral registration. The process was quick, and everything was explained clearly. (Gov.uk publishes their Design System , which is worth reading for anyone who is gathering information like this.) ❄                ❄                ❄                ❄                ❄ I had a conversation with a colleague who had used AI to get data out of an otherwise closed package system. The system contained product data for a client, some 6 million SKUs with hundreds of attributes on each SKU. It was our client’s data, but was locked in the package, and the vendor was increasing their prices and made it hard to support new features. The client could copy the database, but the database structure was so complex, they couldn’t make sense of it, and had been working for ten months with limited progress. My colleague’s idea was to use an AI to build JavaScript scripts that scraped the UI. Since the data was presented from the UI, it was in a form that we could understand. It took him a week to extract all the data. I’m hoping we can get a proper description of this story, I think this approach is one that could be used elsewhere. I know lots of people are very frustrated with package vendors locking up their data. ❄                ❄                ❄                ❄                ❄ Any seller faces fraud, and a little industry has sprung up to get fraudulent access to tokens . The idea is to abuse free-trial schemes, play games with chargebacks, and find places that have any kind of open access to inference. The tokens go through a couple of layers and are then sold on to users - commonly done in China. Matt Lenhard’s post includes some tips to limit the abuse, but “the truth is that there’s no clean fix” ❄                ❄                ❄                ❄                ❄ I’ve never had any desire to live in Clacton, but I now find it temporarily appealing. Here’s hoping its residents do the right thing and elect Britain’s first recyclon MP .

0 views
Giles's blog 1 months ago

How I use AI on this blog

Inspired by this LessWrong post , I thought I'd write about how I use AI here. This is less in the interest of disclosure, more to provide a snapshot of what I'm doing right now so that I can revisit it in the future and see how it changes. And hey, maybe it'll be of interest to you, dear readers. If I were to summarise my working philosophy in fewer than ten words, it would be: AIs identify problems and I fix them myself. With a very specific kind of exception (which I always flag), the text and code on this blog are human-generated. That's not a moral stand, but more a constraint imposed by what this blog is meant to be -- a place for me to learn in public . Every post here is based on an idea I had, and work that I've done. For many posts -- for example, the large-scale coding projects like this one -- I'll have multiple chat sessions ongoing while I do the work, normally with either ChatGPT or Claude, or sometimes both. The amount of input they have varies, but because the value of these projects is in what I learn when I'm doing them, letting an AI do my thinking for me would make the whole thing pointless -- so I take steps to stop that from happening. AIs are, of course, trained to be helpful, and will often explain things in their replies that I would have better learned on my own through experimentation. I'm generally pretty good at spotting when that happens before I've read more than a sentence or two, though, so I can skip reading that part, scroll straight down to the input field, and ask it to operate in more of a rubber duck mode. With the most complicated projects, where each step has a hard dependency on having got the previous one just right, I do use AIs for code review. Let's say that I've built a model that I intend to extend. I'll test it myself (does the loss go down when training, is it generating plausible-looking results?), but if I want to be really cautious, then I'll run the code past an AI. I'll paste it into a chat session and tell the LLM what it's meant to do, and ask it to check if I've screwed up 1 . Again, though, I make it clear that I don't want it to make fixes -- just to point out any bugs. As things progress with a project, I keep detailed notes. When I'm done, I write them up without AI assistance, getting the post to a level where it might be a little messy in terms of how things are explained, but all of the important information is in there. I read it through and make sure I'm reasonably happy with it, and then it's time for what I've taken to calling the editorial board. I paste the draft post into a fresh chat session with an LLM -- right now, this is normally Claude -- and ask for comments. It already has enough information in its memory of earlier conversations to know that what I'm looking for: places where I'm confidently wrong or other technical errors, places where my explanations are missing a step, or where I'm overexplaining things, conclusions that don't really follow from the results of an experiment, and that kind of issue. It tends to spot a few silly grammatical errors and typos at the same time. An important standing instruction is that I do not want it to rewrite anything. Just as with the code, it should tell me where there is a problem, and let me fix it. We iterate on that for a while until we have something that we're both happy with, and then I feed it to the next LLM -- normally ChatGPT. ChatGPT has a much more pernickety attitude than Claude does. I often use metaphors, and it will generally want me to replace them with mathematically rigorous prose. This is still very useful, though. Sometimes the metaphors aren't flagged as such well enough -- or even worse, there are times when the terms I've hit on for a metaphor happen to clash with a technical term, making what I've written misleading at best. I don't always address all of the issues that ChatGPT raises, as otherwise every post would be a mess of hedges and overexplanations and what-have-you, but I like to get to a stage where I'm comfortable that I have a good understanding of specifically why I'm rejecting the remaining points it raises. One other point where ChatGPT has helped a lot is that it's very diligent about checking supporting materials that I link to. When I was recently about to post an article on running an eval on a model, it followed the link to the training code and spotted a silly bug. It wasn't something that materially changed the eval's outcome, which is probably why I'd not noticed it, but it was something that was important to get right if I wanted later runs of the same evals to be solid. Definitely helpful. With that done, I run it past a cast of other LLMs. The exact set varies over time; for the last few posts it has been (in this order) DeepSeek, Grok, GLM-5.2 and Kimi K3. I did use Gemini in the past, but over time it became less effective and just started complimenting me on the post and suggesting related topics to chat about, which was kind of pointless. I'll wait until the next release and then try it again. Because the Claude and ChatGPT passes have generally got rid of anything particularly nasty, this second group of AIs often don't have much to add. However, occasionally they will spot something the others have missed, or have other suggestions, so it's worth spending the five minutes or so it takes to use them. It also helps to keep me up to date with what the other models out there are like. 2 When all of that's done, I run it past Claude one final time, tidy up any remaining issues, then publish it on a private staging site, and read through it carefully myself. The best time for that final readthrough is after dinner, ideally after a glass of wine; the goal is to smooth out the prose, and remove anything overly formal. To make it as close to being fun to read as I can manage. Once I'm happy, I can promote it to the live site and hit the publish button. That probably all sounds much more complicated than it actually is. A short post will normally go through all of that in half an hour -- less if I skip the full editorial board, which I sometimes do. The longer ones can take an hour or two, but given that they're normally the result of a week of work, on and off, in percentage terms it's not that much, and it's worth it for the polish. So, there's no AI-generated text here, but I do lean on AIs to make it the best version I can of what I have to say. How about the code? Again, the goal of the projects I document here is to learn in public. If I'm learning some concept that is expressed in code, then I need to write that code. So that means that anything non-trivial will be something I've written by hand, with AI input limited to code review -- the same rule as I have for the text. Of course, sometimes there are things I'd like to publish that I wouldn't learn anything by writing. Coding up stuff to chart loss curves, or writing a fancy JavaScript visualiser to show what models' parameters are used for would teach me nothing. So for that kind of thing, I just let the AIs get on with it (and even then, for the parameter visualisation, I hacked a first version together in a spreadsheet to check my understanding, and then tested the visualiser against it). I do always mention in the text when a particular bit of code was AI-generated, though. So, my rule is: if I would learn something by writing the code, I'll write it. If not, I'm happy to delegate to an AI. But even then, I apply one restriction: if it's for the blog, I'll ask for the code in a chat session, rather than using a more agentic system like Claude Code or Codex. This is to add friction. If you're using an agent, it's easy for a task to grow, and what started as a throwaway idea can come to consume more and more time and cognitive space. Keeping it in the chat interface keeps things minimal -- or at least, that's how it works for me. Does that mean that I'm against coding agents? This blog is where I post about experiments I've done and what I've learned. At the moment, what I'm learning is all pretty low-level. How does an LLM work? What factors make it smarter or dumber? It's all pretty hands-on, and involves code that I need to understand. I do other things apart from writing this blog, of course :-) And for that I'm keen on agentic tools; I have an OpenClaw agent to help me run my life generally, and use Codex and Claude Code for projects where I'm trying to achieve a specific goal, rather than trying to learn something. But by their very nature, those are not projects that will wind up here on the blog right now. That might change in the future! When I feel that I have a solid, large enough foundation, perhaps I'll be running experiments that I want to write about, where it would make sense for AIs to handle the details, while I focus on the broader strokes. But that time is not now, so right now, you can be sure that every word 3 , and almost every line of code, was written by hand. Even if I do need the AIs to keep me on track and at least borderline coherent. If you're wondering "why not use Claude Code or Codex", I get into why I avoid them for blog-related work towards the end of this post.  ↩ Current thoughts: ChatGPT, being wonderfully true to form, thinks I should clarify here that I'm not including quotes from models here (like the ones here ) when I say that.  ↩ If you're wondering "why not use Claude Code or Codex", I get into why I avoid them for blog-related work towards the end of this post.  ↩ Current thoughts: DeepSeek used to be close to Claude and ChatGPT, but has been left somewhat behind. I have been hearing rumours on X of an upcoming update, though. Grok used to have a propensity to try to turn my posts into clickbait. It would always want to rewrite things, and would suggest titles that were not a million miles away from "Ten things you never knew about RNNs -- number four will shock you!" Recent releases have been much better, though, and I might experiment with moving it further forward in the sequence. GLM-5.2 recently complimented me on my "science fiction" blogpost that mentioned ChatGPT 5.6 Sol. I probed it a bit on that and it said that because the publication date on the post was in 2026, it understood that I was writing near-future SF. From its perspective, the real date was sometime in late 2024. Surprising! I think the last time I saw that kind of behaviour from a model was, well, sometime in 2024... Kimi K3 is really quite impressive. I will be using it more. I particularly like the way it shows a fairly detailed chain of thought -- something it shares with DeepSeek and GLM-5.2, but there seems to be more depth there. It's a pity that Claude and ChatGPT only show summaries in the chat interface, though I understand their reasoning. ChatGPT, being wonderfully true to form, thinks I should clarify here that I'm not including quotes from models here (like the ones here ) when I say that.  ↩

0 views