Note
web
javascript
liquidjs
template-injection
prototype
oracle
exfiltration
Leak an inherited secret by observing how a LiquidJS sort filter orders attacker probe values around it.
Prototype-Inherited Secret Leak through LiquidJS sort_natural
The template engine promises ownPropertyOnly, but some filters still look up inherited properties while
sorting or comparing values. Relative order then leaks the hidden inherited secret.
Why It Works
- A sort filter compares an inherited property; the resulting order tells you where the secret sits relative to your probes.
Vulnerable Pattern
- Server-side JS templating with
LiquidJS, prototype-based secret storage, and sorting filters applied to attacker-controlled arrays/objects.
Exploit Flow
- Place controlled probe values around the unknown inherited value.
- Observe the sort order to learn whether the secret is before, after, or between your probes.
- Repeat as a binary/ternary search until the full secret is reconstructed.
Variations
- Other filters that compare or stringify inherited properties, not just
sort_natural.
Common Blockers
- Engine patched to enforce own properties consistently, or templates not exposing enough control over the compared values.
PoC Sketch
{{ users | sort_natural: "apiKey" | map: "name" | join: "," }}
{# add probe values aaa, mmm, zzz around the inherited secret #}
Good Situations To Use It
- LiquidJS renders attacker-influenced collections.
- A secret is stored on a prototype.
- A comparison/sort filter touches inherited properties.
Sources
plfanzen2026/web/thank_you_javascript