@clear-capabilities/agentic-security-scanner 0.161.0 → 0.163.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/bin/agentic-security.js +98 -2
- package/dist/1340.index.js +1871 -0
- package/dist/3477.index.js +727 -0
- package/dist/3499.index.js +23 -3
- package/dist/4113.index.js +59 -8
- package/dist/5014.index.js +833 -0
- package/dist/5756.index.js +2 -2
- package/dist/6257.index.js +1 -1
- package/dist/6907.index.js +248 -0
- package/dist/6994.index.js +1 -1
- package/dist/7033.index.js +33 -5
- package/dist/7439.index.js +1822 -0
- package/dist/7838.index.js +38 -2
- package/dist/8798.index.js +1 -1
- package/dist/9207.index.js +5 -0
- package/dist/9560.index.js +2336 -27
- package/dist/957.index.js +1 -1
- package/dist/{1905.index.js → 9999.index.js} +306 -13
- package/dist/agentic-security.mjs +12 -12
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +39 -7
- package/src/capabilities/CLAUDE.md +114 -0
- package/src/capabilities/address.js +73 -0
- package/src/capabilities/attack-coverage.js +93 -0
- package/src/capabilities/decide.js +256 -0
- package/src/capabilities/delegate.js +69 -0
- package/src/capabilities/egress.js +20 -0
- package/src/capabilities/hook-advice.js +50 -0
- package/src/capabilities/index.js +32 -0
- package/src/capabilities/manifest.js +344 -0
- package/src/capabilities/outbound.js +189 -0
- package/src/capabilities/paths.js +57 -0
- package/src/capabilities/probes.js +211 -0
- package/src/capabilities/proxy.js +182 -0
- package/src/capabilities/reasons.js +67 -0
- package/src/capabilities/receipts.js +356 -0
- package/src/capabilities/records.js +58 -0
- package/src/capabilities/recovery.js +367 -0
- package/src/capabilities/report.js +81 -0
- package/src/capabilities/runner.js +236 -0
- package/src/capabilities/secrets.js +26 -0
- package/src/capabilities/tool-gate.js +119 -0
- package/src/capabilities/tool-registry.js +60 -0
- package/src/dataflow/CLAUDE.md +29 -0
- package/src/dataflow/catalog.js +21 -0
- package/src/dataflow/engine.js +20 -0
- package/src/dataflow/guard-dominance.js +352 -0
- package/src/discovery/CLAUDE.md +18 -0
- package/src/discovery/index.js +43 -1
- package/src/discovery/lenses.js +18 -0
- package/src/discovery/memory.js +7 -5
- package/src/engine.js +80 -15
- package/src/fix/apply-fix-service.js +33 -3
- package/src/integrations/index.js +5 -2
- package/src/ir/CLAUDE.md +14 -0
- package/src/ir/implicit-handler-params.js +74 -0
- package/src/ir/parser-cs.js +20 -0
- package/src/ir/parser-go.js +30 -13
- package/src/ir/parser-java.js +11 -0
- package/src/language/nix-eval-isolation.js +33 -5
- package/src/lineage/CLAUDE.md +31 -0
- package/src/lineage/deployment/adapter-cloud.js +202 -0
- package/src/lineage/deployment/adapter-compose.js +90 -0
- package/src/lineage/deployment/adapter-kit.js +142 -0
- package/src/lineage/deployment/adapter-kubernetes.js +247 -0
- package/src/lineage/deployment/attack-paths.js +443 -0
- package/src/lineage/deployment/boundaries-run.js +223 -0
- package/src/lineage/deployment/boundary-graph.js +567 -0
- package/src/lineage/deployment/cross-repo.js +253 -0
- package/src/lineage/deployment/drift.js +383 -0
- package/src/lineage/deployment/ingest.js +221 -0
- package/src/lineage/deployment/projection.js +244 -0
- package/src/lineage/deployment/trace-correlation.js +541 -0
- package/src/lineage/source-registry.js +19 -0
- package/src/mcp/CLAUDE.md +14 -3
- package/src/mcp/invariant-tools.js +64 -0
- package/src/mcp/portfolio-tools.js +79 -0
- package/src/mcp/redact.js +15 -0
- package/src/mcp/server.js +24 -3
- package/src/mcp/tools.js +30 -5
- package/src/posture/CLAUDE.md +505 -0
- package/src/posture/accuracy-scorecard.js +95 -4
- package/src/posture/assurance/baseline-inventory.js +218 -0
- package/src/posture/assurance/baseline.js +322 -0
- package/src/posture/assurance/bounded-io.js +145 -0
- package/src/posture/assurance/config.js +299 -0
- package/src/posture/assurance/contracts.js +315 -0
- package/src/posture/assurance/identity.js +62 -0
- package/src/posture/assurance/migrations.js +259 -0
- package/src/posture/assurance/rollback.js +214 -0
- package/src/posture/assurance/rollout.js +200 -0
- package/src/posture/assurance/schema-kit.js +111 -0
- package/src/posture/assurance/verification-record.js +258 -0
- package/src/posture/attestation.js +5 -0
- package/src/posture/autopilot.js +28 -1
- package/src/posture/business-logic.js +26 -4
- package/src/posture/evaluation/bakeoff.js +148 -0
- package/src/posture/evaluation/custody.js +200 -0
- package/src/posture/evaluation/deployment-ablation.js +416 -0
- package/src/posture/evaluation/dev-cases.js +65 -0
- package/src/posture/evaluation/economics.js +85 -0
- package/src/posture/evaluation/gates.js +161 -0
- package/src/posture/evaluation/grouping.js +101 -0
- package/src/posture/evaluation/interval.js +132 -0
- package/src/posture/evaluation/invariant-ablation.js +325 -0
- package/src/posture/evaluation/labels.js +200 -0
- package/src/posture/evaluation/protocol.js +308 -0
- package/src/posture/evaluation/release-gate.js +209 -0
- package/src/posture/evaluation/report.js +158 -0
- package/src/posture/evaluation/runner.js +273 -0
- package/src/posture/evaluation/scan-child.js +80 -0
- package/src/posture/evaluation/score.js +174 -0
- package/src/posture/evaluation/synthetic.js +90 -0
- package/src/posture/evaluation/why-missed.js +219 -0
- package/src/posture/evidence-bundle.js +93 -7
- package/src/posture/execution-proof.js +11 -1
- package/src/posture/fix-verify-loop.js +20 -6
- package/src/posture/fix-verify.js +37 -2
- package/src/posture/fleet.js +11 -2
- package/src/posture/invariants/cli.js +95 -0
- package/src/posture/invariants/coverage.js +164 -0
- package/src/posture/invariants/export.js +178 -0
- package/src/posture/invariants/expressions.js +46 -0
- package/src/posture/invariants/lifecycle.js +289 -0
- package/src/posture/invariants/project-input.js +55 -0
- package/src/posture/invariants/repair.js +340 -0
- package/src/posture/invariants/run.js +45 -0
- package/src/posture/invariants/scenarios.js +311 -0
- package/src/posture/invariants/schema.js +167 -0
- package/src/posture/invariants/shrink.js +407 -0
- package/src/posture/invariants/state-assertions.js +165 -0
- package/src/posture/logic-claims.js +12 -0
- package/src/posture/model-routing.js +40 -0
- package/src/posture/oracles/adapters.js +531 -0
- package/src/posture/oracles/conformance.js +276 -0
- package/src/posture/oracles/oracle.js +453 -0
- package/src/posture/oracles/registry.js +76 -0
- package/src/posture/oracles/scenario-classes.js +223 -0
- package/src/posture/portfolio/backend.js +279 -0
- package/src/posture/portfolio/bundle.js +314 -0
- package/src/posture/portfolio/cli.js +142 -0
- package/src/posture/portfolio/manifest.js +263 -0
- package/src/posture/portfolio/progress.js +267 -0
- package/src/posture/portfolio/resume.js +130 -0
- package/src/posture/portfolio/retention.js +207 -0
- package/src/posture/portfolio/scheduler.js +488 -0
- package/src/posture/portfolio/signing.js +155 -0
- package/src/posture/portfolio/wording.js +59 -0
- package/src/posture/portfolio/work-units.js +405 -0
- package/src/posture/replay/replay.js +250 -0
- package/src/posture/routing/adapter.js +140 -0
- package/src/posture/routing/calibration.js +278 -0
- package/src/posture/routing/canary.js +141 -0
- package/src/posture/routing/control.js +35 -0
- package/src/posture/routing/decide.js +211 -0
- package/src/posture/routing/drift.js +137 -0
- package/src/posture/routing/economics.js +185 -0
- package/src/posture/routing/feedback.js +207 -0
- package/src/posture/routing/index.js +31 -0
- package/src/posture/routing/outcomes.js +281 -0
- package/src/posture/routing/promotion.js +291 -0
- package/src/posture/routing/receipts.js +59 -0
- package/src/posture/routing/report.js +142 -0
- package/src/posture/routing/shadow.js +53 -0
- package/src/posture/specification-mining.js +26 -0
- package/src/posture/verification/advisory-state.js +71 -0
- package/src/posture/verification/emit.js +257 -0
- package/src/posture/verification/hypothesis-promotion.js +211 -0
- package/src/posture/verification/patch-negative.js +226 -0
- package/src/posture/verification/patch-promotion.js +113 -0
- package/src/posture/verification/projection.js +183 -0
- package/src/posture/verification/repair-records.js +124 -0
- package/src/posture/verifier.js +16 -0
- package/src/report/index.js +100 -1
- package/src/sandbox/CLAUDE.md +51 -0
- package/src/sandbox/backend-namespace.js +7 -0
- package/src/sandbox/backend-userspace.js +151 -34
- package/src/sandbox/control-probes.js +215 -0
- package/src/sandbox/supervise.js +201 -0
- package/src/sandbox/trust-boundary.js +113 -0
- package/src/sandbox/trust-domains.js +171 -0
package/dist/3499.index.js
CHANGED
|
@@ -6,11 +6,13 @@ export const modules = {
|
|
|
6
6
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
7
7
|
|
|
8
8
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9
|
-
/* harmony export */
|
|
9
|
+
/* harmony export */ Hy: () => (/* binding */ lensByKey),
|
|
10
10
|
/* harmony export */ LENSES: () => (/* binding */ LENSES),
|
|
11
|
-
/* harmony export */
|
|
11
|
+
/* harmony export */ gj: () => (/* binding */ invariantProposalFor),
|
|
12
|
+
/* harmony export */ jM: () => (/* binding */ buildHunterPrompt)
|
|
12
13
|
/* harmony export */ });
|
|
13
|
-
/* harmony import */ var _egress_redact_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
|
|
14
|
+
/* harmony import */ var _egress_redact_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11723);
|
|
15
|
+
/* harmony import */ var _posture_invariants_lifecycle_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(80891);
|
|
14
16
|
//
|
|
15
17
|
// The seven hunting lenses. Each hunter run is one (focus area × lens) pair.
|
|
16
18
|
//
|
|
@@ -21,6 +23,7 @@ export const modules = {
|
|
|
21
23
|
// no single prompt reaches. `wildcard` exists because a fixed taxonomy is a
|
|
22
24
|
// ceiling, and the classes worth finding are the ones not on the list.
|
|
23
25
|
|
|
26
|
+
|
|
24
27
|
const LENSES = Object.freeze([
|
|
25
28
|
{ key: 'injection', title: 'Injection', family: 'injection', cwe: 'CWE-74',
|
|
26
29
|
brief: 'Untrusted input reaching an interpreter: SQL, shell, template, XPath, LDAP, or deserialization. Follow the value, not the function name.' },
|
|
@@ -38,6 +41,23 @@ const LENSES = Object.freeze([
|
|
|
38
41
|
brief: 'Anything the other lenses do not cover. Prefer the surprising and specific over the generic; report nothing rather than something already obvious.' },
|
|
39
42
|
]);
|
|
40
43
|
|
|
44
|
+
// X-402: the lenses that reason about who may do what to whose data can propose an INVARIANT for a candidate they raise. The
|
|
45
|
+
// proposal is a skeleton contract authored by the model (`proposed`, with the candidate as source evidence and a high uncertainty),
|
|
46
|
+
// advisory until a reviewer approves it in the signed ledger. A lens whose candidates are not about state (injection, crypto) has
|
|
47
|
+
// no mapping and proposes nothing.
|
|
48
|
+
const TENANT_HINT = /tenant|idor|ownership|object reference|cross[- ]?(?:account|user|org)|leak|another user|other user/i;
|
|
49
|
+
const WORKFLOW_HINT = /refund|order|status|workflow|state machine|out[- ]of[- ]order|step|approval|checkout|paid|ship/i;
|
|
50
|
+
|
|
51
|
+
function invariantProposalFor(candidate) {
|
|
52
|
+
const text = `${candidate?.title || ''} ${candidate?.description || ''} ${candidate?.rationale || ''}`;
|
|
53
|
+
let cls = null;
|
|
54
|
+
if (candidate?.lens === 'authz') cls = TENANT_HINT.test(text) ? 'tenant-isolation' : 'privilege-constraint';
|
|
55
|
+
else if (candidate?.lens === 'feature-abuse' && TENANT_HINT.test(text)) cls = 'tenant-isolation';
|
|
56
|
+
else if (candidate?.lens === 'business-logic' && WORKFLOW_HINT.test(text)) cls = 'workflow-order';
|
|
57
|
+
if (!cls || typeof candidate.file !== 'string') return null;
|
|
58
|
+
return (0,_posture_invariants_lifecycle_js__WEBPACK_IMPORTED_MODULE_1__/* .inferredInvariant */ .mB)({ class: cls, source: 'discovery-lens', evidence: { file: candidate.file, line: Number.isInteger(candidate.line) ? candidate.line : null, lens: candidate.lens }, uncertainty: 0.85 });
|
|
59
|
+
}
|
|
60
|
+
|
|
41
61
|
function lensByKey(key) {
|
|
42
62
|
if (typeof key !== 'string') return null;
|
|
43
63
|
return LENSES.find(l => l.key === key) || null;
|
package/dist/4113.index.js
CHANGED
|
@@ -531,6 +531,7 @@ __webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependen
|
|
|
531
531
|
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(73024);
|
|
532
532
|
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(76760);
|
|
533
533
|
/* harmony import */ var _fix_verify_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(27838);
|
|
534
|
+
/* harmony import */ var _verification_emit_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(85578);
|
|
534
535
|
var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_fix_verify_js__WEBPACK_IMPORTED_MODULE_3__]);
|
|
535
536
|
_fix_verify_js__WEBPACK_IMPORTED_MODULE_3__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];
|
|
536
537
|
// Closed-loop fix verification (v0.68).
|
|
@@ -559,6 +560,7 @@ _fix_verify_js__WEBPACK_IMPORTED_MODULE_3__ = (__webpack_async_dependencies__.th
|
|
|
559
560
|
|
|
560
561
|
|
|
561
562
|
|
|
563
|
+
|
|
562
564
|
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
563
565
|
|
|
564
566
|
// Test-runner discovery. Each entry: a sentinel-file check + a command +
|
|
@@ -666,20 +668,32 @@ async function verifyFixWithTests({
|
|
|
666
668
|
runTests = true,
|
|
667
669
|
testRunnerOverride,
|
|
668
670
|
testTimeoutMs,
|
|
671
|
+
patchNegative,
|
|
672
|
+
assuranceConfig,
|
|
669
673
|
} = {}) {
|
|
670
|
-
const scanLint = await (0,_fix_verify_js__WEBPACK_IMPORTED_MODULE_3__.verifyFix)({ scanRoot, originalFindingStableId, files, depFileContents });
|
|
674
|
+
const scanLint = await (0,_fix_verify_js__WEBPACK_IMPORTED_MODULE_3__.verifyFix)({ scanRoot, originalFindingStableId, files, depFileContents, patchNegative, assuranceConfig });
|
|
671
675
|
const legs = {
|
|
672
676
|
scan: { ok: scanLint.rescan?.ok ?? scanLint.ok, detail: scanLint.rescan ?? scanLint },
|
|
673
677
|
lint: { ok: scanLint.lint?.ok ?? true, detail: scanLint.lint ?? null },
|
|
674
678
|
tests: { ok: true, detail: null, skipped: true, reason: 'not-run' },
|
|
675
679
|
};
|
|
676
|
-
|
|
677
|
-
|
|
680
|
+
// X-201: the closed loop's own record (additive). It runs the detector, linter and project tests, never an exploit
|
|
681
|
+
// oracle, so it can say `not-run` or `error` and nothing stronger.
|
|
682
|
+
const withRecord = (res) => {
|
|
683
|
+
const e = (0,_verification_emit_js__WEBPACK_IMPORTED_MODULE_4__/* .emitVerification */ .T)('fix-verify-loop', res, { originalFindingStableId, files, scanRoot });
|
|
684
|
+
return { ...res, verificationRecord: e.ok ? e.record : null };
|
|
685
|
+
};
|
|
686
|
+
// X-204: the patch-negative leg is present only when it was requested and its feature is on. A patch the oracle did not verify
|
|
687
|
+
// is never `verified-clean`, whatever the other legs say.
|
|
688
|
+
const pn = scanLint.patchNegative && scanLint.patchNegative.status !== 'disabled' ? scanLint.patchNegative : null;
|
|
689
|
+
if (pn) legs.patchNegative = { ok: pn.verifiedFix === true, detail: { status: pn.status, incompleteStep: pn.incompleteStep, failureCode: pn.failureCode, reason: pn.reason } };
|
|
690
|
+
if (!legs.scan.ok || !legs.lint.ok || (pn && !legs.patchNegative.ok)) {
|
|
691
|
+
return withRecord({
|
|
678
692
|
ok: false,
|
|
679
693
|
verdict: 'verification-failed',
|
|
680
694
|
legs,
|
|
681
695
|
summary: _summarize(legs, 'verification-failed'),
|
|
682
|
-
};
|
|
696
|
+
});
|
|
683
697
|
}
|
|
684
698
|
if (runTests) {
|
|
685
699
|
const tests = runProjectTests(scanRoot, { runnerOverride: testRunnerOverride, timeoutMs: testTimeoutMs });
|
|
@@ -688,8 +702,8 @@ async function verifyFixWithTests({
|
|
|
688
702
|
const allOk = legs.scan.ok && legs.lint.ok && legs.tests.ok;
|
|
689
703
|
const verdict = !allOk
|
|
690
704
|
? 'verification-failed'
|
|
691
|
-
: (legs.tests.skipped ? 'untested-but-passes' : 'verified-clean');
|
|
692
|
-
return { ok: allOk, verdict, legs, summary: _summarize(legs, verdict) };
|
|
705
|
+
: pn ? 'verified-fix' : (legs.tests.skipped ? 'untested-but-passes' : 'verified-clean');
|
|
706
|
+
return withRecord({ ok: allOk, verdict, legs, summary: _summarize(legs, verdict) });
|
|
693
707
|
}
|
|
694
708
|
|
|
695
709
|
function _summarize(legs, verdict) {
|
|
@@ -697,6 +711,7 @@ function _summarize(legs, verdict) {
|
|
|
697
711
|
bits.push(`scan: ${legs.scan.ok ? 'pass' : 'fail'}`);
|
|
698
712
|
bits.push(`lint: ${legs.lint.skipped ? 'skip' : legs.lint.ok ? 'pass' : 'fail'}`);
|
|
699
713
|
bits.push(`tests: ${legs.tests.skipped ? 'skip' : legs.tests.ok ? 'pass' : 'fail'}`);
|
|
714
|
+
if (legs.patchNegative) bits.push(`patch-negative: ${legs.patchNegative.ok ? 'pass' : `fail (${legs.patchNegative.detail.incompleteStep})`}`);
|
|
700
715
|
return `${verdict} (${bits.join(' · ')})`;
|
|
701
716
|
}
|
|
702
717
|
|
|
@@ -722,6 +737,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
722
737
|
/* harmony import */ var _fix_honesty_gate_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(27785);
|
|
723
738
|
/* harmony import */ var _test_runner_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(35136);
|
|
724
739
|
/* harmony import */ var _fix_metrics_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(32238);
|
|
740
|
+
/* harmony import */ var _verification_emit_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(85578);
|
|
725
741
|
var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_engine_js__WEBPACK_IMPORTED_MODULE_3__]);
|
|
726
742
|
_engine_js__WEBPACK_IMPORTED_MODULE_3__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];
|
|
727
743
|
// Closed-loop /fix verification (Sentinel-parity FR-L4-4, FR-L4-5).
|
|
@@ -749,6 +765,7 @@ _engine_js__WEBPACK_IMPORTED_MODULE_3__ = (__webpack_async_dependencies__.then ?
|
|
|
749
765
|
|
|
750
766
|
|
|
751
767
|
|
|
768
|
+
|
|
752
769
|
const SEVERITY_RANK = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
|
|
753
770
|
|
|
754
771
|
// Run a focused re-scan over just the patched file(s) using the in-memory
|
|
@@ -913,6 +930,8 @@ async function verifyFix({
|
|
|
913
930
|
testTimeoutMs,
|
|
914
931
|
recordMetrics = true,
|
|
915
932
|
poc,
|
|
933
|
+
patchNegative,
|
|
934
|
+
assuranceConfig,
|
|
916
935
|
} = {}) {
|
|
917
936
|
// R5 (reporting half) — time each stage as it runs. Measured here rather
|
|
918
937
|
// than inside each stage because only this function knows the boundaries of
|
|
@@ -995,7 +1014,26 @@ async function verifyFix({
|
|
|
995
1014
|
}
|
|
996
1015
|
_lap('honesty');
|
|
997
1016
|
|
|
998
|
-
|
|
1017
|
+
// X-204: patch-negative verification, only when the caller asked for it AND the `patch-negative-verification` feature is
|
|
1018
|
+
// on. `patchNegative` is the requester's exploit scenario and functional cases ({ original, functional, commit?, ... }); the
|
|
1019
|
+
// candidate `files` are the proposed diff. With the flag off, or no request, nothing here runs and every field below is
|
|
1020
|
+
// exactly what it was before.
|
|
1021
|
+
let pn = null;
|
|
1022
|
+
if (patchNegative && typeof patchNegative === 'object') {
|
|
1023
|
+
try {
|
|
1024
|
+
const { verifyPatchNegative } = await __webpack_require__.e(/* import() */ 6907).then(__webpack_require__.bind(__webpack_require__, 26907));
|
|
1025
|
+
pn = await verifyPatchNegative({
|
|
1026
|
+
hypothesisId: originalFindingStableId, ...patchNegative, patch: { files },
|
|
1027
|
+
commit: patchNegative.commit ?? (0,_verification_emit_js__WEBPACK_IMPORTED_MODULE_7__.headCommit)(scanRoot),
|
|
1028
|
+
}, { config: assuranceConfig });
|
|
1029
|
+
} catch (e) {
|
|
1030
|
+
pn = { status: 'error', verifiedFix: false, incompleteStep: 'patch-negative', failureCode: 'harness-error', reason: `patch-negative verification failed to run: ${String(e?.message || e).slice(0, 200)}`, summary: '' };
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const pnActive = pn !== null && pn.status !== 'disabled';
|
|
1034
|
+
_lap('patchNegative');
|
|
1035
|
+
|
|
1036
|
+
const ok = rescan.ok && (lint.ok || lint.skipped) && testsOk && pocOk && (honesty ? honesty.ok : true) && (pnActive ? pn.verifiedFix === true : true);
|
|
999
1037
|
|
|
1000
1038
|
// FR-305 (assurance-hardening PRD): `ok` alone conflates "every leg
|
|
1001
1039
|
// genuinely ran and passed" with "passed, but a required leg was skipped
|
|
@@ -1037,6 +1075,7 @@ async function verifyFix({
|
|
|
1037
1075
|
: pocLeg.status === 'no-longer-proven' ? 'poc: PASS (ran against the patch and no longer demonstrates the vulnerability)'
|
|
1038
1076
|
: `poc: inconclusive — not counted either way (${pocLeg.reason || 'no detail reported'})`,
|
|
1039
1077
|
// FR-305: never let a degraded pass read the same as a full one.
|
|
1078
|
+
pnActive ? `patch-negative: ${pn.verifiedFix ? 'PASS (verified-fix)' : `FAIL - not verified-fix, incomplete step '${pn.incompleteStep}' (${pn.failureCode}): ${pn.reason}`}` : null,
|
|
1040
1079
|
ok && !verifiedFull ? `NOTE: PASSED, but NOT fully verified — ${degradedLegs.join('; ')}` : null,
|
|
1041
1080
|
].filter(Boolean).join('\n');
|
|
1042
1081
|
// Persist the attempt so the distribution can be reported from real runs.
|
|
@@ -1063,7 +1102,19 @@ async function verifyFix({
|
|
|
1063
1102
|
});
|
|
1064
1103
|
}
|
|
1065
1104
|
|
|
1066
|
-
|
|
1105
|
+
// X-201: the one verification record, ADDITIVE. `ok` and every field above stay exactly as they were; the record
|
|
1106
|
+
// says what was actually established (a static re-scan is not an exploit oracle, so without a PoC leg it is
|
|
1107
|
+
// `not-run`, and nothing here can reach `confirmed`/`refuted`: that takes a trusted oracle adapter).
|
|
1108
|
+
const emitted = (0,_verification_emit_js__WEBPACK_IMPORTED_MODULE_7__/* .emitVerification */ .T)('fix-verify', { rescan, lint, tests, poc: pocLeg }, {
|
|
1109
|
+
originalFindingStableId, files, scanRoot, finding: poc?.finding,
|
|
1110
|
+
});
|
|
1111
|
+
const verificationRecord = emitted.ok ? emitted.record : null;
|
|
1112
|
+
|
|
1113
|
+
return {
|
|
1114
|
+
ok, verifiedFull, degradedLegs, rescan, lint, tests, testedPrePatch: _testedPrePatch, honesty, poc: pocLeg, durations, summary, verificationRecord,
|
|
1115
|
+
// additive, present only when patch-negative verification was requested (X-204)
|
|
1116
|
+
...(pn ? { patchNegative: pn, ...(pnActive ? { fixStatus: pn.verifiedFix ? 'verified-fix' : 'not-verified-fix' } : {}) } : {}),
|
|
1117
|
+
};
|
|
1067
1118
|
}
|
|
1068
1119
|
|
|
1069
1120
|
__webpack_async_result__();
|