Problem
openTemplateSource downloads the starter templates as a GitHub archive and extracts them into the
developer's new project (src/core/templates.ts). The extracted code is then
npm installed and docker buildt, so whatever lands on disk runs. Two weaknesses in that path:
The ref is mutable and the archive is unverified. The download is pinned to a tag
(SEAMLESS_TEMPLATES_REF, currently v0.4.0), and git tags can be moved. There is no checksum or
signature on the zip, so a moved tag or a compromised repository yields arbitrary code with nothing
to detect it.
Extraction does not constrain the output path. copyInto builds each destination as
path.join(destDir, rel) where rel comes from the archive entry name, with no check that the
result stays inside destDir. An entry containing ../ writes outside the project (zip slip).
Neither is exploitable today: the archive comes from our own repository over https. They matter
together, because the second turns a compromise of the first into writes anywhere the developer can
write.
Proposal
- Pin to an immutable ref, or verify what was downloaded. Either resolve
SEAMLESS_TEMPLATES_REF to
a commit SHA, or ship an expected digest alongside the ref in
src/core/images.ts and check the archive bytes before extracting.
- Reject any archive entry whose resolved destination escapes
destDir, and fail the scaffold rather
than skipping the entry silently.
SEAMLESS_TEMPLATES_DIR (a local checkout, for template development) is unaffected and should stay
unverified.
Priority
Deferred by agreement: no live exposure, and the fix is worth doing deliberately rather than
squeezing it alongside feature work. Filed so it is not lost.
Acceptance
- A scaffold verifies the archive it extracts, or resolves to an immutable ref.
- An archive entry that would write outside the destination fails the scaffold with a clear error.
- Both behaviors are covered by tests.
Problem
openTemplateSourcedownloads the starter templates as a GitHub archive and extracts them into thedeveloper's new project (src/core/templates.ts). The extracted code is then
npm installed anddocker buildt, so whatever lands on disk runs. Two weaknesses in that path:The ref is mutable and the archive is unverified. The download is pinned to a tag
(
SEAMLESS_TEMPLATES_REF, currentlyv0.4.0), and git tags can be moved. There is no checksum orsignature on the zip, so a moved tag or a compromised repository yields arbitrary code with nothing
to detect it.
Extraction does not constrain the output path.
copyIntobuilds each destination aspath.join(destDir, rel)whererelcomes from the archive entry name, with no check that theresult stays inside
destDir. An entry containing../writes outside the project (zip slip).Neither is exploitable today: the archive comes from our own repository over https. They matter
together, because the second turns a compromise of the first into writes anywhere the developer can
write.
Proposal
SEAMLESS_TEMPLATES_REFtoa commit SHA, or ship an expected digest alongside the ref in
src/core/images.ts and check the archive bytes before extracting.
destDir, and fail the scaffold ratherthan skipping the entry silently.
SEAMLESS_TEMPLATES_DIR(a local checkout, for template development) is unaffected and should stayunverified.
Priority
Deferred by agreement: no live exposure, and the fix is worth doing deliberately rather than
squeezing it alongside feature work. Filed so it is not lost.
Acceptance