{
  "artifact_id": "sample-3",
  "count": 4,
  "severity_spread": {
    "critical": 2,
    "high": 0,
    "medium": 1,
    "low": 0,
    "info": 1
  },
  "findings": [
    {
      "id": "sample-3/f-001",
      "rule": "SC-CVE-MINIMIST-001",
      "family": "supply-chain",
      "severity": "critical",
      "title": "Package `minimist@1.2.5` is affected by CVE-2021-44906 (prototype pollution)",
      "file": "package.json",
      "line": 3,
      "evidence": {
        "source_extract": "\"version\": \"1.2.5\"",
        "confidence": 1,
        "reasoning": "Version 1.2.5 predates the fix for CVE-2021-44906. The vulnerability is prototype pollution via a `constructor` key in the parsed arguments; the fix in 1.2.6 added a `constructor` guard to `setKey`. NVD score: 9.8 (critical).",
        "detector": "svp-dependency + OSV feed (GHSA-xvch-5gv4-984h)"
      },
      "reachable_from": [
        "import minimist → parse(args) → setKey(argv, keys, value)"
      ],
      "recommendation": "Upgrade to `minimist ^1.2.6` (patch-only upgrade, no API break)."
    },
    {
      "id": "sample-3/f-002",
      "rule": "SEC-PROTO-POLLUTION-001",
      "family": "security",
      "severity": "critical",
      "title": "`setKey` guards `__proto__` but not `constructor` — prototype pollution sink",
      "file": "index.js",
      "line": 69,
      "symbol": "setKey",
      "evidence": {
        "source_extract": "if (key === '__proto__') return;",
        "confidence": 0.95,
        "reasoning": "The `setKey` helper walks a user-controlled key path and assigns into the target object. Lines 73 and 82 guard the exact string `__proto__` — but not `constructor`, `prototype`, or `constructor.prototype`. An attacker who controls CLI arguments (or JSON parsed by minimist) can pollute Object.prototype through a `constructor.prototype` payload. This is the code-level root cause of the CVE in the previous finding.",
        "detector": "svp-verification (semantic check on argument-parser sinks)"
      },
      "reachable_from": [
        "parse(argv, opts) → argDefined() → setKey(argv, keys, value)",
        "parse(argv, opts) → defaults[key] fallback → setKey(argv, x.split('.'), defaults[key])"
      ],
      "recommendation": "Add `if (key === 'constructor' || key === 'prototype') return;` to setKey before the existing __proto__ check — or replace the guard set with a full disallow-list including all Object.prototype accessor names."
    },
    {
      "id": "sample-3/f-003",
      "rule": "QUAL-LONG-001",
      "family": "quality",
      "severity": "medium",
      "title": "File `index.js` is 246 lines — above the 200-line soft threshold",
      "file": "index.js",
      "line": 1,
      "evidence": {
        "source_extract": "module.exports = function (args, opts) { ... }",
        "confidence": 1,
        "reasoning": "index.js consolidates the entire parser plus 6 internal helpers in one file. Not a blocker on its own, but a smaller surface would make future audits cheaper.",
        "detector": "svp-parser (structural metric)"
      },
      "recommendation": "Consider extracting `setKey` and the flag-classifier helpers into siblings."
    },
    {
      "id": "sample-3/f-004",
      "rule": "META-LICENSE-MIT",
      "family": "supply-chain",
      "severity": "info",
      "title": "License = MIT (permissive, redistribution allowed)",
      "file": "LICENSE",
      "line": 1,
      "evidence": {
        "source_extract": "This software is released under the MIT license",
        "confidence": 1,
        "reasoning": "Vendored copy carries an MIT LICENSE file. Attribution preserved per the license terms in the manifest provenance block.",
        "detector": "svp-dependency (license fingerprint)"
      },
      "recommendation": "No action — informational."
    }
  ]
}
