A walkthrough of prompt injection attacks against OopsSec Store's AI assistant, bypassing its input filters to extract a flag from the system prompt. OopsSec Store has an AI support assistant with a secret embedded in its system prompt. The only thing standing between us and the flag is a regex blocklist. Spoiler: four regexes are not enough. Initialize the OopsSec Store application: npx create-os
I have a confession. For years, when a developer proudly showed me their Python app — gray square buttons, a Listbox straight out of 1998 — I would politely nod. I've stopped doing that. Not because I turned mean. Because PyQt6 exists, and there's no excuse anymore. This article is my attempt to convince you — yes, you, the one still typing import tkinter out of habit — that something radically be
As a best-selling author, I invite you to explore my books on Amazon. Don't forget to follow me on Medium and show your support. Thank you! Your support means the world! I’ve spent years writing software, and one thing I’ve learned is that managing dependencies can turn a clean codebase into a tangled mess. Dependency injection (DI) containers help, but most are either too heavy or don’t handle c
If you're using a scraping API like ScraperAPI, Scrape.do, or ScrapingBee, you already solved the hard fetching problem — proxy rotation, CAPTCHA, JS rendering, IP blocks. But here's what happens after the fetch: const html = await scraperApi.fetch('https://example.com/products'); // now what? // cheerio? puppeteer? regex? // custom parser that breaks every time the site updates? You get raw HTML
TL;DR — One API call subscribes a customer endpoint. Centrali signs each delivery with HMAC-SHA256, retries 5 times over ~40 minutes on failure, logs every attempt, and exposes a one-line replay endpoint. No queue. No retry logic. No Svix. The whole subscribe call is right below — scroll to it if you just want the shape. Your customers want webhooks. You know the checklist: A queue so user request
J'ai un aveu à faire : pendant longtemps, quand un dev me montrait fièrement son app Python avec un bouton gris carré et une Listbox qui sentait Windows 95, je hochais la tête poliment. Aujourd'hui, j'ai arrêté. Pas parce que je suis devenu méchant. Parce que PyQt6 existe, et qu'il n'y a plus aucune excuse. Cet article, c'est ma tentative de te convaincre — toi qui ouvres encore tkinter par réflex
You ask Claude to "add caching to the user profile endpoint," and 30 seconds later you ship something that looks fine in review: SET user_42 <json> — flat key, no namespace, collides the moment a second service shares the cluster. No TTL — the entry lives forever until maxmemory evicts your hottest keys. KEYS user_* in a cleanup job — single-threaded Redis stalls every other client for hundreds of
In my last article, I mentioned that my SAST tool uses regex-based pattern matching instead of AST parsing, and that this was a deliberate tradeoff. A few people asked me to go deeper on that decision — because on the surface, it sounds like I took a shortcut. I didn't. Or rather — I did, but it was an informed shortcut, and there's a meaningful difference. Let me explain what AST parsing actually