Skip to content

Commit e6e146c

Browse files
authored
fix: use Object.hasOwn for action name lookup (#15721)
1 parent 4000aaa commit e6e146c

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes action route handling to return 404 for requests to prototype method names like `constructor` or `toString` used as action paths

packages/astro/src/core/base-pipeline.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ export abstract class Pipeline {
198198
}
199199

200200
for (const key of pathKeys) {
201-
if (!(key in server)) {
201+
if (!Object.hasOwn(server, key)) {
202202
throw new AstroError({
203203
...ActionNotFoundError,
204204
message: ActionNotFoundError.message(pathKeys.join('.')),

packages/astro/test/actions.test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,19 @@ describe('Astro Actions', () => {
166166
assert.equal(data.code, 'NOT_FOUND');
167167
});
168168

169+
it('Returns 404 for prototype methods used as action names', async () => {
170+
for (const name of ['constructor', '__proto__', 'toString', 'valueOf']) {
171+
const res = await fixture.fetch(`/_actions/${name}`, {
172+
method: 'POST',
173+
body: JSON.stringify({}),
174+
headers: {
175+
'Content-Type': 'application/json',
176+
},
177+
});
178+
assert.equal(res.status, 404, `Expected 404 for /_actions/${name}`);
179+
}
180+
});
181+
169182
it('Should fail when calling an action without using Astro.callAction', async () => {
170183
const res = await fixture.fetch('/invalid/');
171184
assert.equal(res.status, 500);
@@ -606,6 +619,20 @@ describe('Astro Actions', () => {
606619
const data = await res.json();
607620
assert.equal(data.code, 'NOT_FOUND');
608621
});
622+
623+
it('Returns 404 for prototype methods used as action names', async () => {
624+
for (const name of ['constructor', '__proto__', 'toString', 'valueOf']) {
625+
const req = new Request(`http://example.com/_actions/${name}`, {
626+
method: 'POST',
627+
headers: {
628+
'Content-Type': 'application/json',
629+
},
630+
body: JSON.stringify({}),
631+
});
632+
const res = await app.render(req);
633+
assert.equal(res.status, 404, `Expected 404 for /_actions/${name}`);
634+
}
635+
});
609636
});
610637
});
611638

0 commit comments

Comments
 (0)