openvibers/openvibe.codes Commits

Cancelling a task refuses a cross-site post, as starting one does (#268)

OP OpenVibers committed 10 days ago · 8d35591d1e · 2 files, +6 −0

POST /api/v1/me/tasks checks the Origin; POST /api/v1/me/tasks/:id/cancel did not, so a page on another site could
cancel a signed-in person's running task.

Changes

ddiff --git a/server/http/me-api.js b/server/http/me-api.js
iindex 0992465..089d546 100644
---- a/server/http/me-api.js
++++ b/server/http/me-api.js
@@@ -123,6 +123,8 @@ function createMeApi({ config, store, sso, run, harnesses, actorLimits, tasks =
r.post('/me/tasks/:id/cancel', actorLimits.budget('codes.task.start'), async (req, res) => {
if (!signedIn(req)) return problem(req, res, 401, 'auth.required', 'sign in to cancel your tasks');
++ // As starting a task: a cross-site post from a signed-in browser cannot cancel one (REVIEW-0, 11-03).
++ if (!sameOrigin(req)) return problem(req, res, 403, 'cross_site', 'cross-site posts are refused');
let row = await own(req, req.params.id);
if (!row) return problem(req, res, 404, 'codes.task_not_found', 'no such task of yours');
if (row.job_id && !TERMINAL.has(row.state)) {
ddiff --git a/test/me-api.test.js b/test/me-api.test.js
iindex b35739b..23e6d36 100644
---- a/test/me-api.test.js
++++ b/test/me-api.test.js
@@@ -71,6 +71,10 @@ const { boot, check, done } = require('./helpers/boot');
await check('cancel reaches Run and returns the final state', async () => {
const list = await call('GET', '/tasks', { as: ada });
const id = list.json().tasks[0].id;
++ // REVIEW-0 (11-03): a cross-site post cannot cancel it, as it cannot start one.
++ const cross = await call('POST', `/tasks/${id}/cancel`, { as: ada, origin: 'https://evil.example' });
++ assert.strictEqual(cross.status, 403);
++ assert.ok(!calls.some((x) => x[0] === 'cancel'), 'nothing reached Run');
const c = await call('POST', `/tasks/${id}/cancel`, { as: ada });
assert.strictEqual(c.status, 200);
assert.strictEqual(c.json().state, 'cancelled');