Repository navigation
Expand file tree
/
Copy pathvsixPolicy.mjs
More file actions
107 lines (98 loc) · 3.76 KB
/
Copy pathvsixPolicy.mjs
File metadata and controls
107 lines (98 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
const ROOT_METADATA_ENTRIES = new Set([
'[Content_Types].xml',
'extension.vsixmanifest',
]);
const REQUIRED_ENTRIES = [
...ROOT_METADATA_ENTRIES,
'extension/package.json',
'extension/out/extension.js',
'extension/out/webview.js',
'extension/out/codexView.js',
];
const FORBIDDEN_ENTRY_PATTERNS = [
/^extension\/(?:src|tests|docs|\.github|\.codex|\.claude|\.agents|\.superpowers)(?:\/|$)/i,
/^extension\/out\/test(?:\/|$)/i,
/^extension\/AGENTS(?:\.zh-CN)?\.md$/i,
/^extension\/node_modules(?:\/|$)/i,
/^extension\/issue87-.*\.cjs$/i,
/^extension\/out\/claudeIncrementalPrototype\.js$/i,
/^extension\/out\/adviceEffectiveness\/(?:evidencePreparation|feedback|legacyBridge|legacyPersonalization|modelExperiment)\.js$/i,
/^extension\/out\/(?:adviceDemoSample|adviceSummary)\.js$/i,
/^extension\/(?:AI-ADVICE-.*V2\.3\.1|V2\.3\.1-CANDIDATE-CONTRACT(?:\.zh-CN)?)\.md$/i,
/^extension\/CLAUDE-COLD-AB-V2\.3\.1(?:\.zh-CN)?\.md$/i,
/(?:^|\/)\.env(?:\.|$)/i,
/\.(?:pem|key|p12|pfx)$/i,
];
const REQUIRED_BUNDLE_MARKERS = [
{ label: "provider === 'codex'", present: (bundle) => bundle.includes("provider === 'codex'") },
{ label: 'renderTodayData(provider)', present: (bundle) => bundle.includes('renderTodayData(provider)') },
{ label: 'renderSessionData(provider)', present: (bundle) => bundle.includes('renderSessionData(provider)') },
{ label: 'renderSettingsPanel(provider)', present: (bundle) => bundle.includes('renderSettingsPanel(provider)') },
{ label: 'data-provider-target', present: (bundle) => bundle.includes('data-provider-target') },
];
const RETIRED_BUNDLE_MARKERS = [
'ccu.codex.ui.v1',
'data-codex-tab-button="recent"',
'data-codex-tab-button="7d"',
'data-codex-tab-button="30d"',
'data-codex-tab-button="all"',
'data-codex-tab-button="threads"',
'data-codex-tab-button="projects"',
'data-codex-tab-button="behavior"',
'data-codex-tab-button="settings"',
'data-codex-page="overview"',
'data-codex-page="explore"',
'data-codex-page="recommendations"',
'data-codex-action',
'hostState.codexUi = nextState',
];
function assertCanonicalEntry(entry) {
if (typeof entry !== 'string' || entry.length === 0 || entry.includes('\0') ||
entry.includes('\\') || entry.startsWith('/') || /^[A-Za-z]:/.test(entry) ||
entry.endsWith('/')) {
throw new Error(`unsafe VSIX entry: ${String(entry)}`);
}
if (entry.split('/').some((segment) => segment === '' || segment === '.' || segment === '..')) {
throw new Error(`unsafe VSIX entry: ${entry}`);
}
if (!ROOT_METADATA_ENTRIES.has(entry) && !entry.startsWith('extension/')) {
throw new Error(`unsafe VSIX entry: ${entry}`);
}
}
export function assertSafeVsixEntries(entries) {
if (!Array.isArray(entries)) {
throw new Error('VSIX entries must be an array');
}
const seen = new Set();
for (const entry of entries) {
assertCanonicalEntry(entry);
const collisionKey = entry.toLowerCase();
if (seen.has(collisionKey)) {
throw new Error(`duplicate VSIX entry: ${entry}`);
}
seen.add(collisionKey);
if (FORBIDDEN_ENTRY_PATTERNS.some((pattern) => pattern.test(entry))) {
throw new Error(`forbidden VSIX entry: ${entry}`);
}
}
for (const required of REQUIRED_ENTRIES) {
if (!seen.has(required.toLowerCase())) {
throw new Error(`missing required VSIX entry: ${required}`);
}
}
}
export function assertCodexBundleMarkers(bundle) {
if (typeof bundle !== 'string') {
throw new Error('bundle must be text');
}
for (const marker of REQUIRED_BUNDLE_MARKERS) {
if (!marker.present(bundle)) {
throw new Error(`missing bundle marker: ${marker.label}`);
}
}
for (const marker of RETIRED_BUNDLE_MARKERS) {
if (bundle.includes(marker)) {
throw new Error(`retired bundle marker: ${marker}`);
}
}
}