Skip to content

Commit

Permalink
patch vulnerability (#8117)
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Mar 14, 2024
1 parent 9658c7c commit c65b3f0
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 40 deletions.
22 changes: 7 additions & 15 deletions dist/livewire.esm.js
Expand Up @@ -1485,27 +1485,17 @@ var require_module_cjs = __commonJS({
}) {
deferHandlingDirectives(() => {
walker(el, (el2, skip) => {
if (el2._x_inited) {
if (el2._x_ignore)
skip();
return;
}
intercept(el2, skip);
initInterceptors.forEach((i) => i(el2, skip));
directives(el2, el2.attributes).forEach((handle) => handle());
if (el2._x_ignore) {
skip();
} else {
el2._x_inited = true;
}
el2._x_ignore && skip();
});
});
}
function destroyTree(root, walker = walk) {
walker(root, (el) => {
cleanupAttributes(el);
cleanupElement(el);
delete el._x_inited;
});
}
var onAttributeAddeds = [];
Expand Down Expand Up @@ -1648,6 +1638,8 @@ var require_module_cjs = __commonJS({
node._x_ignore = true;
});
for (let node of addedNodes) {
if (removedNodes.has(node))
continue;
if (!node.isConnected)
continue;
delete node._x_ignoreSelf;
Expand Down Expand Up @@ -1695,15 +1687,15 @@ var require_module_cjs = __commonJS({
has({ objects }, name) {
if (name == Symbol.unscopables)
return false;
return objects.some((obj) => Reflect.has(obj, name));
return objects.some((obj) => Object.prototype.hasOwnProperty.call(obj, name) || Reflect.has(obj, name));
},
get({ objects }, name, thisProxy) {
if (name == "toJSON")
return collapseProxies;
return Reflect.get(objects.find((obj) => Reflect.has(obj, name)) || {}, name, thisProxy);
},
set({ objects }, name, value, thisProxy) {
const target = objects.find((obj) => Reflect.has(obj, name)) || objects[objects.length - 1];
const target = objects.find((obj) => Object.prototype.hasOwnProperty.call(obj, name)) || objects[objects.length - 1];
const descriptor = Object.getOwnPropertyDescriptor(target, name);
if ((descriptor == null ? void 0 : descriptor.set) && (descriptor == null ? void 0 : descriptor.get))
return Reflect.set(target, name, value, thisProxy);
Expand Down Expand Up @@ -2848,7 +2840,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
get raw() {
return raw;
},
version: "3.13.6",
version: "3.13.7",
flushAndStopDeferringMutations,
dontAutoEvaluateFunctions,
disableEffectScheduling,
Expand Down Expand Up @@ -9242,7 +9234,7 @@ function fromQueryString(search) {
insertDotNotatedValueIntoData([second, ...rest].join("."), value, data2[first2]);
};
let entries = search.split("&").map((i) => i.split("="));
let data = {};
let data = /* @__PURE__ */ Object.create(null);
entries.forEach(([key, value]) => {
value = decodeURIComponent(value.replaceAll("+", "%20"));
if (!key.includes("[")) {
Expand Down
22 changes: 7 additions & 15 deletions dist/livewire.js
Expand Up @@ -867,27 +867,17 @@
}) {
deferHandlingDirectives(() => {
walker(el, (el2, skip) => {
if (el2._x_inited) {
if (el2._x_ignore)
skip();
return;
}
intercept(el2, skip);
initInterceptors.forEach((i) => i(el2, skip));
directives(el2, el2.attributes).forEach((handle) => handle());
if (el2._x_ignore) {
skip();
} else {
el2._x_inited = true;
}
el2._x_ignore && skip();
});
});
}
function destroyTree(root, walker = walk) {
walker(root, (el) => {
cleanupAttributes(el);
cleanupElement(el);
delete el._x_inited;
});
}
var onAttributeAddeds = [];
Expand Down Expand Up @@ -1030,6 +1020,8 @@
node._x_ignore = true;
});
for (let node of addedNodes) {
if (removedNodes.has(node))
continue;
if (!node.isConnected)
continue;
delete node._x_ignoreSelf;
Expand Down Expand Up @@ -1077,15 +1069,15 @@
has({ objects }, name) {
if (name == Symbol.unscopables)
return false;
return objects.some((obj) => Reflect.has(obj, name));
return objects.some((obj) => Object.prototype.hasOwnProperty.call(obj, name) || Reflect.has(obj, name));
},
get({ objects }, name, thisProxy) {
if (name == "toJSON")
return collapseProxies;
return Reflect.get(objects.find((obj) => Reflect.has(obj, name)) || {}, name, thisProxy);
},
set({ objects }, name, value, thisProxy) {
const target = objects.find((obj) => Reflect.has(obj, name)) || objects[objects.length - 1];
const target = objects.find((obj) => Object.prototype.hasOwnProperty.call(obj, name)) || objects[objects.length - 1];
const descriptor = Object.getOwnPropertyDescriptor(target, name);
if (descriptor?.set && descriptor?.get)
return Reflect.set(target, name, value, thisProxy);
Expand Down Expand Up @@ -2230,7 +2222,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
get raw() {
return raw;
},
version: "3.13.6",
version: "3.13.7",
flushAndStopDeferringMutations,
dontAutoEvaluateFunctions,
disableEffectScheduling,
Expand Down Expand Up @@ -7884,7 +7876,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
insertDotNotatedValueIntoData([second, ...rest].join("."), value, data3[first2]);
};
let entries = search.split("&").map((i) => i.split("="));
let data2 = {};
let data2 = /* @__PURE__ */ Object.create(null);
entries.forEach(([key, value]) => {
value = decodeURIComponent(value.replaceAll("+", "%20"));
if (!key.includes("[")) {
Expand Down
12 changes: 6 additions & 6 deletions dist/livewire.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/livewire.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/manifest.json
@@ -1,2 +1,2 @@

{"/livewire.js":"d76a01eb"}
{"/livewire.js":"5d8beb2e"}
5 changes: 4 additions & 1 deletion js/plugins/history/index.js
Expand Up @@ -261,7 +261,10 @@ function fromQueryString(search) {

let entries = search.split('&').map(i => i.split('='))

let data = {}
// let data = {} creates a security (XSS) vulnerability here. We need to use
// Object.create(null) instead so that we have a "pure" object that doesnt
// inherit Object.prototype and expose the js internals to manipulation.
let data = Object.create(null)

entries.forEach(([key, value]) => {
value = decodeURIComponent(value.replaceAll('+', '%20'))
Expand Down
45 changes: 45 additions & 0 deletions src/Features/SupportQueryString/BrowserTest.php
Expand Up @@ -760,6 +760,51 @@ public function render()
->assertQueryStringMissing('bar')
;
}

/** @test */
public function cannot_inject_js_through_query_string()
{
$this->tweakApplication(function() {
app('livewire')->component('foo', new class extends Component {
#[Url]
public $foo = 'bar';

public function render()
{
return <<<'HTML'
<div>
<div>Hi!</div>
<!-- We wrap the alert in a setTimeout so that the injection has a chance to run first... -->
<!-- <script>setTimeout(() => alert('foo'), 100)</script> -->
</div>
HTML;
}
});

\Illuminate\Support\Facades\Route::get('/foo', function () {
return app('livewire')->new('foo')();
})->middleware('web');
});

$this->browse(function ($browser) {
$browser->visit('/foo?constructor.prototype.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&__proto__.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&constructor[prototype][html]=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&constructor.prototype.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&__proto__.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&__proto__[html]=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E#constructor.prototype.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&__proto__.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&constructor[prototype][html]=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&constructor.prototype.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&__proto__.html=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E&__proto__[html]=%22%27%3E%3Cimg+src+onerror%3Dalert%281%29%3E');

try {
$alert = $browser->driver->switchTo()->alert()->getText();
} catch (\Facebook\WebDriver\Exception\NoSuchAlertException $e) {
$this->assertTrue(true);

return;
}

$browser->waitForDialog();
$browser->acceptDialog();
$browser->waitForDialog();
$browser->acceptDialog();

$this->assertTrue(false, 'Maliciously injected alert detected');
});
}
}

class FormObject extends \Livewire\Form
Expand Down

0 comments on commit c65b3f0

Please sign in to comment.