{
  "root_cause": "User-controlled files extracted from published VSIX packages are served to HTTP clients with a Content-Type that the browser renders as active content (text/html, image/svg+xml) and without a Content-Security-Policy or Content-Disposition: attachment header, allowing inline script execution in the registry origin (open-vsx.org).",
  "parent_sink": {
    "files": [
      "server/src/main/java/org/eclipse/openvsx/storage/StorageUtilService.java",
      "server/src/main/java/org/eclipse/openvsx/storage/LocalStorageService.java",
      "server/src/main/java/org/eclipse/openvsx/storage/StorageUtil.java"
    ],
    "functions": [
      "StorageUtilService.getFileResponse(Path)",
      "LocalStorageService.getFileResponseHeaders(String)",
      "StorageUtil.getFileType(String)"
    ],
    "parent_entrypoint": "GET /vscode/unpkg/{ns}/{ext}/{ver}/{path} -> LocalVSCodeService.browse -> getWebResource -> getFileResponse(Path)"
  },
  "variant_sink": {
    "files": [
      "server/src/main/java/org/eclipse/openvsx/LocalRegistryService.java",
      "server/src/main/java/org/eclipse/openvsx/storage/StorageUtilService.java",
      "server/src/main/java/org/eclipse/openvsx/storage/LocalStorageService.java",
      "server/src/main/java/org/eclipse/openvsx/storage/StorageUtil.java",
      "server/src/main/java/org/eclipse/openvsx/ExtensionProcessor.java"
    ],
    "functions": [
      "RegistryAPI.getFile",
      "LocalRegistryService.getFile",
      "StorageUtilService.getFileResponse(FileResource)",
      "LocalStorageService.getFile(FileResource)",
      "LocalStorageService.getFileResponseHeaders(String)",
      "StorageUtil.getFileType(String)",
      "ExtensionProcessor.getIcon"
    ],
    "variant_entrypoint": "GET /api/{ns}/{ext}/{ver}/file/{iconName} -> LocalRegistryService.getFile -> getFileResponse(FileResource) -> LocalStorageService.getFile(FileResource) -> getFileResponseHeaders(name) -> StorageUtil.getFileType(name)"
  },
  "shared_insecure_primitive": "StorageUtil.getFileType(String fileName) -> URLConnection.guessContentTypeFromName(fileName) returns text/html for *.html; LocalStorageService.getFileResponseHeaders sets that Content-Type with no CSP and no Content-Disposition (attachment only for .vsix).",
  "equivalence_reasoning": "Both the parent repro (/vscode/unpkg/) and the variant (/api/.../file/) terminate at the SAME insecure primitive on v1.0.1: LocalStorageService.getFileResponseHeaders(name) calling StorageUtil.getFileType(name). They differ only in which call site feeds it - the on-demand web-resource Path overload (getFileResponse(Path)) vs the persisted-FileResource overload (LocalStorageService.getFile(FileResource)). The variant additionally abuses the un-validated ExtensionProcessor.getIcon to inject an HTML document into the persisted-FileResource serving path. Same trust boundary (unauthenticated publisher -> authenticated victim via registry origin), same impact class (info_leak / origin XSS), same exploitable header state (text/html, no CSP).",
  "same_root_cause_confidence": "high",
  "same_surface_confidence": "medium",
  "fix_commit": "9491f32a6d459a4d499c5028d37c0d0386771e9f",
  "fix_covers_variant": true,
  "fix_coverage_explanation": "v1.0.2 deletes StorageUtil.getFileType and routes BOTH serving overloads through HttpHeadersUtil.createFileResponseHeaders: getFileResponse(Path) at StorageUtilService.java:316 and LocalStorageService.getFile(FileResource) at LocalStorageService.java:92. Tika detects the HTML content as text/html (in TEXT_VIEWABLE_MEDIA_TYPES) and forces Content-Type to text/plain;charset=utf-8; a strict CSP, nosniff, and X-Frame-Options: DENY are always set. Verified on the running v1.0.2 server: the variant URL returns text/plain + CSP (inline_html=0). The fix is complete for the in-origin inline-rendering issue; no bypass found.",
  "is_bypass": false,
  "bypass_status": "not_a_bypass_alternate_trigger_on_vulnerable_only"
}
