Skip to content

Commit 46659af

Browse files
committed
fix(spec): address CodeQL alerts in gen:schema/gen:docs scripts (#3012)
- build-schemas.ts: read the ratchet manifest directly and treat ENOENT as first-run bootstrap instead of existsSync-then-read (TOCTOU). - build-docs.ts: escape backslashes before pipes in table-cell descriptions — an existing `\|` would otherwise decay into an escaped backslash followed by a live pipe, splitting the GFM cell. No output changes: regenerated json-schema/ and references/ are byte-identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn6qMKtJeVbs2KzouWDHhB
1 parent 7da8743 commit 46659af

2 files changed

Lines changed: 14 additions & 8 deletions

File tree

packages/spec/scripts/build-docs.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,13 @@ function generateMarkdown(schemaName: string, schema: any, category: string, zod
213213
for (const [key, prop] of Object.entries(props) as [string, any][]) {
214214
const typeStr = formatType(prop).replace(/\|/g, '\\|');
215215
const isReq = required.has(key) ? '✅' : 'optional';
216-
// Escape literal pipes last — this cell lives in a GFM table row, where
217-
// an unescaped `|` (even inside a code span) splits the cell.
218-
const desc = escapeMdxDescription((prop.description || '').replace(/\n/g, ' ')).replace(/\|/g, '\\|');
216+
// Escape for the GFM table cell last: backslashes first (so an existing
217+
// `\|` in a description can't decay into an escaped backslash + live
218+
// pipe), then pipes — an unescaped `|` (even inside a code span)
219+
// splits the cell.
220+
const desc = escapeMdxDescription((prop.description || '').replace(/\n/g, ' '))
221+
.replace(/\\/g, '\\\\')
222+
.replace(/\|/g, '\\|');
219223
t += `| **${key}** | \`${typeStr}\` | ${isReq} | ${desc} |\n`;
220224
}
221225
return t + '\n';

packages/spec/scripts/build-schemas.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,13 @@ interface SchemaManifest {
281281
}
282282

283283
let manifest: SchemaManifest | null = null;
284-
if (fs.existsSync(MANIFEST_PATH)) {
285-
try {
286-
manifest = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf-8')) as SchemaManifest;
287-
} catch (error) {
288-
console.error(`\n❌ Failed to parse ${MANIFEST_PATH}: ${error}`);
284+
try {
285+
manifest = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf-8')) as SchemaManifest;
286+
} catch (error) {
287+
// A missing manifest just means first run (bootstrap below); anything else
288+
// (unreadable, invalid JSON) must fail rather than silently drop the ratchet.
289+
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
290+
console.error(`\n❌ Failed to read ${MANIFEST_PATH}: ${error}`);
289291
process.exit(1);
290292
}
291293
}

0 commit comments

Comments
 (0)