mirror of
https://github.com/github/awesome-copilot.git
synced 2026-08-09 02:29:13 +00:00
daily-focus-board: reject inherited-property-name task ids (prototype safety)
Resolves the Copilot review on board-core.mjs: task ids like `toString` /
`constructor` passed validId and, used as object keys, could resolve to
Object.prototype members. Now validId also rejects any inherited name (`s in {}`),
and the progress maps (counters, t) are null-prototype so a task id can never
resolve to an inherited member. (`__proto__` was already blocked by the id grammar.)
Headless test 43/43 (adds inherited-name rejection, drop-on-normalize, and an
Object.prototype-intact check).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cb356aa8-0af2-48f3-b3c6-8086c69d5308
This commit is contained in:
@@ -46,7 +46,12 @@ const BOARD_MARKER = "daily-focus-board";
|
||||
// delete routing, so a task may not claim them as an id — otherwise deleting a
|
||||
// task note could splice the shared feed instead.
|
||||
const RESERVED_IDS = new Set(["day", "brain"]);
|
||||
export function validId(s) { return typeof s === "string" && ID_RE.test(s) && !RESERVED_IDS.has(s); }
|
||||
// Reject reserved sentinels AND any inherited Object.prototype name (toString,
|
||||
// constructor, hasOwnProperty, __proto__, ...) via `s in {}` — task ids are used
|
||||
// as object keys, so an inherited name could otherwise resolve to a prototype
|
||||
// member. With the null-prototype progress maps in normalize(), a task id can
|
||||
// never touch the prototype.
|
||||
export function validId(s) { return typeof s === "string" && ID_RE.test(s) && !RESERVED_IDS.has(s) && !(s in {}); }
|
||||
function text(s, max = 2000) { return typeof s === "string" ? s.slice(0, max) : ""; }
|
||||
function num(v) {
|
||||
if (v === undefined || v === null || v === "") return undefined;
|
||||
@@ -89,8 +94,10 @@ export function normalize(doc) {
|
||||
doc.tasks = Array.isArray(doc.tasks) ? doc.tasks.filter(t => t && validId(t.id)).map(normalizeTaskDef) : [];
|
||||
|
||||
const p = doc.progress && typeof doc.progress === "object" ? doc.progress : {};
|
||||
p.counters = p.counters && typeof p.counters === "object" ? p.counters : {};
|
||||
p.t = p.t && typeof p.t === "object" ? p.t : {};
|
||||
// Null-prototype maps so a task id can never resolve to an inherited member
|
||||
// (e.g. reading p.t["toString"] returning Object.prototype.toString).
|
||||
p.counters = Object.assign(Object.create(null), p.counters && typeof p.counters === "object" ? p.counters : {});
|
||||
p.t = Object.assign(Object.create(null), p.t && typeof p.t === "object" ? p.t : {});
|
||||
p.day = Array.isArray(p.day) ? p.day : [];
|
||||
p.brain = Array.isArray(p.brain) ? p.brain : [];
|
||||
p.focus = validId(p.focus) ? p.focus : null;
|
||||
|
||||
Reference in New Issue
Block a user