MCPcopy Create free account
hub / github.com/chhoumann/quickadd / parseQuickAddPackage

Function parseQuickAddPackage

src/services/packageImportService.ts:125–198  ·  view source on GitHub ↗
(raw: string)

Source from the content-addressed store, hash-verified

123}
124
125export function parseQuickAddPackage(raw: string): QuickAddPackage {
126 let parsed: unknown;
127 try {
128 parsed = JSON.parse(raw);
129 } catch (error) {
130 throw new Error(
131 `Package content is not valid JSON: ${(error as Error)?.message ?? error}`,
132 );
133 }
134
135 if (!isQuickAddPackage(parsed)) {
136 throw new Error("Content is not a valid QuickAdd package.");
137 }
138
139 if (parsed.schemaVersion > QUICKADD_PACKAGE_SCHEMA_VERSION) {
140 throw new Error(
141 `Package schema version ${parsed.schemaVersion} is newer than this plugin supports (${QUICKADD_PACKAGE_SCHEMA_VERSION}).`,
142 );
143 }
144
145 // Reject duplicate asset paths at the untrusted-input boundary. The writer is
146 // last-write-wins per destination while the review pane resolves the FIRST
147 // match (decodeAssetPreview), so two assets at one path could show benign bytes
148 // in review while malicious bytes land on disk — a silent review-gate desync.
149 // Failing closed here keeps reviewed bytes identical to written bytes.
150 const duplicateAssetPath = findDuplicateAssetPath(parsed.assets);
151 if (duplicateAssetPath !== null) {
152 throw new Error(
153 `Package contains duplicate asset path "${duplicateAssetPath}". Each asset must have a unique path.`,
154 );
155 }
156
157 // Reject internally-inconsistent choices at the untrusted-input boundary. The
158 // same choice id can appear in MORE than one place in a package: as a flat
159 // `pkg.choices` entry AND inline inside a Multi's `choices` array (or as a
160 // NestedChoice/Conditional-branch embedded choice). The preview and the writer
161 // each pick ONE of those copies and assume the others are identical:
162 // buildPackagePreview's walk SKIPS an inline Multi child whose id is also an
163 // entry (trusting the entry's walk to cover it), while applyPackageImport's
164 // remapChoiceTree INSTALLS the inline copy and drops the standalone entry. A
165 // crafted package can make those copies DIVERGE — a benign top-level entry that
166 // the preview discloses, paired with a malicious inline child (e.g.
167 // runOnStartup:true) that actually installs — suppressing the capability
168 // disclosure and acknowledgement gate entirely. The structural validator
169 // (isQuickAddPackage) never checks this. A legitimately-exported package always
170 // clones every appearance of an id from one source choice, so all appearances
171 // are identical; divergence implies tampering. Fail closed so the copy the user
172 // reviews is provably the copy that installs.
173 const divergentChoiceId = findDivergentChoiceId(parsed.choices);
174 if (divergentChoiceId !== null) {
175 throw new Error(
176 `Package contains conflicting definitions for choice "${divergentChoiceId}". Each choice id must describe the same choice everywhere it appears.`,
177 );
178 }
179
180 // Reject a parented choice whose declared parent does not actually carry it
181 // inline. applyPackageImport installs a child SOLELY through its parent Multi's
182 // inline `choices` (remapChoiceTree keeps only the children listed there) and,

Calls 5

isQuickAddPackageFunction · 0.90
findDuplicateAssetPathFunction · 0.85
findDivergentChoiceIdFunction · 0.85
parseMethod · 0.80

Tested by

no test coverage detected