mirror of
https://github.com/prompt-security/clawsec.git
synced 2026-06-15 06:21:21 +03:00
4dbac421ab
* feat(advisories): add provisional ghsa feed * fix(workflows): include advisory signatures in checksums * fix(workflows): mirror ghsa feed at release root * feat(advisories): consolidate ghsa into agent feed * ci(advisories): consolidate ghsa during nvd poll * fix(advisories): retain unreplaced ghsa feed entries * chore(skills): bump advisory feed consumers * fix(release): resolve ts import closure dry run * fix(release): preserve urls while stripping comments * fix(release): ignore skill test-only changes * fix(advisories): follow ghsa pagination links * test(advisories): add nvd ghsa pipeline dry run
89 lines
3.6 KiB
JavaScript
89 lines
3.6 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
|
|
const workflowPath = new URL('../.github/workflows/poll-nvd-cves.yml', import.meta.url);
|
|
const workflow = await readFile(workflowPath, 'utf8');
|
|
const ciWorkflowPath = new URL('../.github/workflows/ci.yml', import.meta.url);
|
|
const ciWorkflow = await readFile(ciWorkflowPath, 'utf8');
|
|
|
|
function requiredIndex(snippet, message) {
|
|
const index = workflow.indexOf(snippet);
|
|
assert.notEqual(index, -1, message);
|
|
return index;
|
|
}
|
|
|
|
assert.match(
|
|
workflow,
|
|
/GHSA_FEED_PATH:\s+advisories\/ghsa-without-cve\.json/,
|
|
'NVD workflow must write the provisional GHSA source feed',
|
|
);
|
|
assert.match(
|
|
workflow,
|
|
/GHSA_FEED_SIG_PATH:\s+advisories\/ghsa-without-cve\.json\.sig/,
|
|
'NVD workflow must sign the provisional GHSA source feed',
|
|
);
|
|
assert.match(
|
|
workflow,
|
|
/node scripts\/ghsa-without-cve-feed\.mjs[\s\S]*--output "\$GHSA_FEED_PATH"[\s\S]*--consolidated-feed "\$FEED_PATH"[\s\S]*--existing-feed "\$GHSA_FEED_PATH"[\s\S]*--nvd-feed "\$FEED_PATH"/,
|
|
'NVD workflow must merge GHSA advisories into the signed agent feed',
|
|
);
|
|
assert.match(
|
|
workflow,
|
|
/id: feed_changes[\s\S]*ghsa_changed=\$GHSA_CHANGED[\s\S]*agent_changed=\$AGENT_CHANGED[\s\S]*changed=true/,
|
|
'NVD workflow must detect GHSA and consolidated agent feed changes separately',
|
|
);
|
|
assert.match(
|
|
workflow,
|
|
/if: steps\.feed_changes\.outputs\.ghsa_changed == 'true'[\s\S]*input_file: \$\{\{ env\.GHSA_FEED_PATH \}\}[\s\S]*signature_file: \$\{\{ env\.GHSA_FEED_SIG_PATH \}\}/,
|
|
'NVD workflow must sign the provisional GHSA feed when it changes',
|
|
);
|
|
assert.match(
|
|
workflow,
|
|
/if: steps\.feed_changes\.outputs\.agent_changed == 'true'[\s\S]*input_file: \$\{\{ env\.FEED_PATH \}\}[\s\S]*signature_file: \$\{\{ env\.FEED_SIG_PATH \}\}/,
|
|
'NVD workflow must sign the consolidated agent feed when it changes',
|
|
);
|
|
assert.match(
|
|
workflow,
|
|
/git add "\$FEED_PATH" "\$FEED_SIG_PATH" "\$GHSA_FEED_PATH" "\$GHSA_FEED_SIG_PATH" "\$SKILL_FEED_PATH" "\$SKILL_FEED_SIG_PATH"/,
|
|
'NVD workflow PR must include both NVD and GHSA feed artifacts',
|
|
);
|
|
assert.match(
|
|
ciWorkflow,
|
|
/name: NVD \+ GHSA Pipeline Dry Run[\s\S]*node scripts\/test-nvd-ghsa-pipeline-dry-run\.mjs/,
|
|
'CI must run the deterministic NVD + GHSA pipeline dry run before merge',
|
|
);
|
|
|
|
const updateFeedIndex = requiredIndex('name: Update feed.json', 'NVD workflow must update the CVE feed first');
|
|
const pollGhsaIndex = requiredIndex(
|
|
'name: Poll GHSA without CVE and consolidate feed',
|
|
'NVD workflow must poll GHSA before signing',
|
|
);
|
|
const detectChangesIndex = requiredIndex(
|
|
'name: Detect advisory feed changes',
|
|
'NVD workflow must detect combined feed changes before signing',
|
|
);
|
|
const signGhsaIndex = requiredIndex(
|
|
'name: Sign GHSA feed and verify',
|
|
'NVD workflow must sign the GHSA source feed',
|
|
);
|
|
const signAgentIndex = requiredIndex(
|
|
'name: Sign advisory feed and verify',
|
|
'NVD workflow must sign the consolidated agent feed',
|
|
);
|
|
const upsertPrIndex = requiredIndex(
|
|
'name: Upsert NVD advisory PR',
|
|
'NVD workflow must upsert a PR for any feed change',
|
|
);
|
|
|
|
assert.ok(
|
|
updateFeedIndex < pollGhsaIndex,
|
|
'GHSA consolidation must run after the NVD update step so matured advisories can reconcile against new CVEs',
|
|
);
|
|
assert.ok(
|
|
pollGhsaIndex < detectChangesIndex,
|
|
'Combined feed change detection must run after GHSA consolidation',
|
|
);
|
|
assert.ok(detectChangesIndex < signGhsaIndex, 'GHSA signing must run after change detection');
|
|
assert.ok(detectChangesIndex < signAgentIndex, 'Agent feed signing must run after change detection');
|
|
assert.ok(signAgentIndex < upsertPrIndex, 'The PR must be created after feed signing');
|