docs+chore: add README Security section; fix lint regressions on main

- README: add a visible ## Security section (official sources, vuln reporting via SECURITY.md, GateGuard/IOC/AgentShield guardrails, security guide); make stats line a plain paragraph to clear MD028
- eslint: empty catch comment in run-with-flags.js; drop unneeded escape in github-coordination/parsing.js; remove unused execFileSync import in its test (#2236 follow-ups)
- markdownlint: wrap bare URLs in rules/vue/*.md (#2250 follow-up)

npm run lint green; full suite 2836/2836.
This commit is contained in:
Affaan Mustafa
2026-06-16 02:08:14 -04:00
parent d90d921137
commit 351ccc5a3c
9 changed files with 180 additions and 171 deletions
+4 -7
View File
@@ -100,9 +100,8 @@ function getPluginRoot() {
return path.resolve(__dirname, '..', '..');
}
//Safely extract target context from hook stdin JSON for dry-run preview.
function extractTargetContext(raw) {
const result = { tool: '', filePath: '', command: '' };
if (!raw || typeof raw !== 'string') return result;
@@ -118,18 +117,16 @@ function extractTargetContext(raw) {
}
}
} catch {
// best-effort field extraction; ignore malformed input
}
return result;
}
// Build the [DryRun] preview line for stderr.
function buildDryRunPreview(hookId, relScriptPath, profilesCsv, raw) {
const ctx = extractTargetContext(raw);
const parts = [
`[DryRun] Hook "${hookId}" would execute: ${relScriptPath}`,
`(enabled=true, profiles=${profilesCsv || 'default'})`,
];
const parts = [`[DryRun] Hook "${hookId}" would execute: ${relScriptPath}`, `(enabled=true, profiles=${profilesCsv || 'default'})`];
if (ctx.tool) {
parts.push(`tool=${ctx.tool}`);
+11 -25
View File
@@ -7,17 +7,12 @@ function escapeRegExp(str) {
}
function normalizeBodyForComparison(body) {
return (body || '').replace(/"lastSyncAt"\s*:\s*[^,\}\n]+/g, '"lastSyncAt": NORMALIZED');
return (body || '').replace(/"lastSyncAt"\s*:\s*[^,}\n]+/g, '"lastSyncAt": NORMALIZED');
}
function extractCoordinationState(body, policy = DEFAULT_POLICY) {
const marker = escapeRegExp(policy.sectionMarker || DEFAULT_SECTION_MARKER);
const regex = new RegExp(
`<!--\\s*${marker}:start\\s*-->\\s*` +
'```json\\s*([\\s\\S]*?)\\s*```' +
`\\s*<!--\\s*${marker}:end\\s*-->`,
'm'
);
const regex = new RegExp(`<!--\\s*${marker}:start\\s*-->\\s*` + '```json\\s*([\\s\\S]*?)\\s*```' + `\\s*<!--\\s*${marker}:end\\s*-->`, 'm');
const match = String(body || '').match(regex);
if (!match) {
@@ -28,9 +23,7 @@ function extractCoordinationState(body, policy = DEFAULT_POLICY) {
const parsed = JSON.parse(match[1]);
return parsed && typeof parsed === 'object' ? parsed : null;
} catch (error) {
throw new SyntaxError(
`Malformed coordination JSON in body: ${error.message} — raw: ${match[1].slice(0, 120)}`
);
throw new SyntaxError(`Malformed coordination JSON in body: ${error.message} — raw: ${match[1].slice(0, 120)}`);
}
}
@@ -40,7 +33,9 @@ function extractIssueReferences(text) {
for (const match of source.matchAll(/(?:^|[^\d])#(\d+)\b/g)) {
refs.add(Number.parseInt(match[1], 10));
}
return Array.from(refs).filter(Number.isFinite).sort((a, b) => a - b);
return Array.from(refs)
.filter(Number.isFinite)
.sort((a, b) => a - b);
}
function extractTasks(body) {
@@ -62,7 +57,7 @@ function extractTasks(body) {
if (taskMatch) {
tasks.push({
title: taskMatch[2].trim(),
done: taskMatch[1].toLowerCase() === 'x',
done: taskMatch[1].toLowerCase() === 'x'
});
}
}
@@ -98,26 +93,17 @@ function renderCoordinationState(state, policy = DEFAULT_POLICY) {
lastAction: state.lastAction || 'sync',
lastActionAt: state.lastActionAt || new Date().toISOString(),
lastSyncAt: state.lastSyncAt || new Date().toISOString(),
notes: state.notes || null,
notes: state.notes || null
};
return [
`<!-- ${marker}:start -->`,
'```json',
JSON.stringify(payload, null, 2),
'```',
`<!-- ${marker}:end -->`,
].join('\n');
return [`<!-- ${marker}:start -->`, '```json', JSON.stringify(payload, null, 2), '```', `<!-- ${marker}:end -->`].join('\n');
}
function mergeIssueBody(issue, nextState, policy = DEFAULT_POLICY) {
const body = String(issue.body || '');
const markerEscaped = escapeRegExp(policy.sectionMarker || DEFAULT_SECTION_MARKER);
const rendered = renderCoordinationState(nextState, policy);
const regex = new RegExp(
`\\n?<!--\\s*${markerEscaped}:start\\s*-->[\\s\\S]*?<!--\\s*${markerEscaped}:end\\s*-->\\n?`,
'm'
);
const regex = new RegExp(`\\n?<!--\\s*${markerEscaped}:start\\s*-->[\\s\\S]*?<!--\\s*${markerEscaped}:end\\s*-->\\n?`, 'm');
if (regex.test(body)) {
return body.replace(regex, `\n${rendered}\n`).trim() + '\n';
@@ -139,5 +125,5 @@ module.exports = {
mergeIssueBody,
normalizeBodyForComparison,
parseStringList,
renderCoordinationState,
renderCoordinationState
};