Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/pentesting-ci-cd/cloudflare-security/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,41 @@ For a practical abuse of Workers as pass-through proxies (IP rotation, FireProx-
cloudflare-workers-pass-through-proxy-ip-rotation.md
{{#endref}}

### workerd / Code Mode native attack surface

Cloudflare Workers and Cloudflare Code Mode both execute attacker-influenced JavaScript/TypeScript inside `workerd`. Even when V8 isolates, the V8 cage and the L2 process sandbox are present, the native JSG / Node-compatible bindings are still a separate review surface because their C++ objects can live on the shared `tcmalloc` heap outside the isolate-focused protections.<sup>[[1]](#references)</sup>

#### Interesting bug classes to review

- **Parallel metadata/value count mismatches:** if one component counts regex captures or fields while another component independently builds the related names/metadata list, make sure both lengths always match. Nested captures are a good edge case. A one-element mismatch can make native code reinterpret the next heap object as a descriptor such as `{ptr, size, disposer}`, upgrading a small OOB read into an arbitrary-address read.<sup>[[1]](#references)</sup>
- **Managed/native lifetime bugs:** look for native structs that keep raw pointers borrowed from GC-managed buffers after the wrapper drops its temporary references. In `node:zlib`-style code, a safe-looking `write()` path may refresh `next_in` / `next_out`, while a later reconfiguration API such as `params()` may reach the same `z_stream` without clearing the stale pointers first.<sup>[[1]](#references)</sup>
- **Iterator invalidation over resizable native arrays:** if an iterator stores a raw pointer into a growable container, repeated mutation (`setAttribute()`, `push()`, etc.) can reallocate the backing array and turn the next iterator access into a UAF read.<sup>[[1]](#references)</sup>
- **Reserved-table rename bypasses:** SQL authorizers must validate not only referenced tables but also the destination of `ALTER TABLE ... RENAME TO`. If a protected KV layer auto-deserializes BLOBs from an internal table, renaming an attacker-controlled table into that reserved namespace becomes a deserialization bridge into internal structured-clone handlers.<sup>[[1]](#references)</sup>

A quick lab probe for the rename pattern is:<sup>[[1]](#references)</sup>


```sql
CREATE TABLE kv_tmp (key TEXT, value BLOB);
INSERT INTO kv_tmp VALUES ('k', X'41414141');
ALTER TABLE kv_tmp RENAME TO _cf_KV;
```

#### Exploitation patterns worth remembering

- If attacker input controls the number of native vector elements, use padding to select a `tcmalloc` size class and spray same-sized objects beside the vulnerable allocation.<sup>[[1]](#references)</sup>
- When a corruption primitive cannot fully control the written bytes, target a **length/size field** instead of a pointer. Inflating the logical length of a VFS-backed buffer or file often upgrades the bug into precise OOB reads/writes through legitimate APIs that accept an explicit position argument.<sup>[[1]](#references)</sup>
- A first forward-only OOB write can often be upgraded into repeatable arbitrary read/write by corrupting the backing pointer of a second object and then using that second object's normal read/write API against attacker-selected addresses.<sup>[[1]](#references)</sup>
- In agentic runtimes such as Code Mode, **prompt injection is exploit delivery**: the model is intentionally generating the TypeScript that will exercise low-level bindings, so untrusted prompt/tool content must be treated as a path to native bug reachability, not just to logic abuse.<sup>[[1]](#references)</sup>

#### Review / detection ideas

- Grep for code that builds **two parallel arrays/vectors** from different parsers or engines and later zips them by index.<sup>[[1]](#references)</sup>
- Grep for persistent native fields like `next_in`, `next_out`, cached iterators, or raw pointers into `ArrayBuffer` / `Buffer` storage that survive beyond the current call frame.<sup>[[1]](#references)</sup>
- Review SQL authorizer callbacks to confirm rename destinations such as `_cf_*` are denied, not only direct `SELECT` / `INSERT` / `UPDATE` access.<sup>[[1]](#references)</sup>
- During runtime review, suspicious sequences include nested raw-regex groups in `URLPattern`, low-level zlib writes using `Z_NO_FLUSH` followed by `params()`, large `HTMLRewriter.setAttribute()` loops while an iterator is alive, and SQL attempts to rename tables into `_cf_*`.<sup>[[1]](#references)</sup>
- For self-hosted deployments, update `workerd` / Code Mode to `v1.20260619.1` or later.<sup>[[1]](#references)</sup>

## R2

On each R2 bucket check:
Expand Down Expand Up @@ -137,6 +172,10 @@ cloudflare-zero-trust-network.md

[Check this part](cloudflare-domains.md#cloudflare-ddos-protection).

## References

- [1] [When Agentic Glue Melts: Exploiting Cloudflare Code Mode and Workers](https://research.checkpoint.com/2026/when-agentic-glue-melts/)

{{#include ../../banners/hacktricks-training.md}}


Expand Down