phishingThe URL bar is not lying to you. The window around it is.
Browser-in-the-browser phishing draws a convincing fake popup inside the attacker's page. Why checking the URL does not protect users, and what does.
Writing
Technical write-ups from real engagements and research, what we found, how it was exploited, and what closes it.
phishingBrowser-in-the-browser phishing draws a convincing fake popup inside the attacker's page. Why checking the URL does not protect users, and what does.
linux securityEDR on Linux runs through eBPF. So do the rootkits. How they hide from ls, ps and bpftool, what the hook can and cannot reach, and what constrains it.
web securityA docx, xlsx or SVG is a bundle of XML, and an XML parser that resolves external entities will fetch files and URLs on the attacker's behalf. CVE-2019-12415 in Apache POI is the office-document case. How XXE reaches an upload endpoint, how to find it, and how to turn it off.
web securityPrototype pollution lets an attacker set a property on every object in a Node process by writing through __proto__. CVE-2019-10744 in lodash is the canonical case. How the merge goes wrong, how to find it, and how it differs from Python class pollution.
web securityWeb cache deception stores a victim's private response for anyone to fetch; cache poisoning stores an attacker's response for everyone. Both come from the cache and the origin disagreeing about a URL. CVE-2024-46982 in Next.js is the current, well-documented case.
web securityCL.TE and TE.CL desync happen when two servers disagree about where a request ends. CVE-2019-18277 in HAProxy is the clean example: how the disagreement forms, how to find it safely, and how to shut it down.
detection engineeringlogin failure for user -2 via ssh in a RouterOS log means the MikroTrick chain reached your router. What the -2 means, how to triage it, and what rebuild means.
web securityNo 'Access-Control-Allow-Origin' header is present on the requested resource. The two fixes developers copy do not fix CORS, they delete it. One is account takeover.
cryptographyCERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate means no path to a trusted root. The five real causes, and why verify=False is not a fix.
cve analysisCOPY ... TO PROGRAM is a documented PostgreSQL feature that runs shell commands. Why Cisco's CVE-2026-76461 grep turns SQL injection into root, and how to hunt it.
cloud securityService accounts, API keys, OAuth grants and CI/CD secrets hold broader access and longer-lived credentials than any employee would be permitted to carry, and none of them appear in an access review. Inventory, short-lived tokens, and the IAM calls that give the game away.
ai securityA crafted email sitting unread in an inbox was enough to make Microsoft 365 Copilot exfiltrate internal data. The injectable surface is every document the model reads, and the control that bounds it is least privilege on tools.
active directoryESC1 turns a low-privileged domain account into a domain admin certificate. Strong certificate mapping was supposed to end that, and since September 2025 it cannot be switched off. Here is what still works, what does not, and how to check your own templates.
web securityWeb race conditions were dismissed as theoretical because network jitter made the window unhittable. Then HTTP/2 removed the jitter. The technique, the sub-states nobody models, and how to build code that cannot race.
linux privilege escalationCapabilities split root into 40+ pieces, and about a dozen of them are still root. Which ones matter, how CVE-2022-0492 turned a cgroup detail into a container escape, and how to audit a host and an image.
linux privilege escalationA 9.3 in sudo itself, plus twenty ways a single sudoers line hands over root. How to read sudo -l like an attacker, why the chroot bug worked, and what a safe sudoers policy looks like.
cryptographyIf an application encrypts your input concatenated with a secret, and does it in ECB mode, you can extract that secret one character at a time. A complete walkthrough with runnable code. The clearest demonstration of why ECB is not encryption.
cryptographyCBC without a MAC lets an attacker decrypt and forge ciphertext using nothing but the server's error behaviour. The mechanism from first principles, the Telerik and ASP.NET cases, and the one rule that removes the class.
ssrfIMDSv2 closed the famous SSRF target. The internal network is still full of unauthenticated control planes that will run a container for anyone who asks, and crypto-mining crews have been scanning for them since 2020.
ssrfOne HTTP request to 169.254.169.254 turned an SSRF into 100 million records. Seven years on, IMDSv2 fixes it and adoption is roughly half. How the attack works, why v2 stops it, and how to enforce it.
api securityA JSON Web Token is only as good as the verification code. Five failure modes with concrete examples, including CVE-2022-21449, where an all-zero ECDSA signature validated against any key on Java 15 through 18.
api securityEvery API inventory is a snapshot of what someone remembered to document. The gap between that list and what your servers actually answer is where breaches live, how to find zombie, shadow and orphaned endpoints, and how to stop creating them.
api securityGraphQL moves authorisation from the route to the resolver, and most teams only notice half of them. Introspection, alias multiplication, batched mutations against rate limits, and the complexity-DoS CVEs, with the fixes that actually hold.
api securityOptus lost roughly 10 million customer records to an API with sequential IDs and no authorisation check. Here is how to tell the three authorisation failures apart, how to test each one, and why automated tools are structurally blind to them.
web securityPython has no prototypes, so it cannot have prototype pollution, except it can. A walkthrough of class pollution: the vulnerable merge function, the four attribute chains that matter, and how to spot it in a code review.
web securityYou escaped the shell metacharacters and the command still ran. Argument injection is the bug that survives shell-safe APIs, here is the mechanism, the PHP-CGI case that got mass-exploited, and the one-character fix.
insecure deserializationtorch.load(weights_only=True) was the recommended safe path, and it was bypassable. A practical look at Python deserialization, pickle, PyYAML and jsonpickle, how one gadget works, and what actually stops it.
web securityMost SSTI write-ups teach one Jinja2 payload and stop. Here is the actual bug class, the per-engine probe table, a lab you can build in ten minutes, and the code-review rule that removes it entirely.
active directoryThe phishing chain that still works against companies with MFA switched on. A reverse proxy sits in front of the real login page, the victim authenticates for real, and the attacker keeps the session cookie.
ai securityWe built a kids' chat app where a language model decides which messages are safe, then attacked the decision. Prompt injection is OWASP's number one LLM risk for the second edition running, and the reason is structural.
active directoryDomain compromise is almost never a memory-corruption bug. It is a graph traversal across permissions somebody granted on purpose. Here are the three routes that keep working, and what to check tonight.