Skip to content

fix(skills): stage media downloads in private directories - #3787

Merged
jrusso1020 merged 1 commit into
mainfrom
fix/security-media-download-temp
Sep 8, 2026
Merged

jrusso1020 merged 1 commit into
mainfrom
fix/security-media-download-temp

Conversation

@jrusso1020

Copy link
Copy Markdown
Collaborator

Problem and change

Addresses CodeQL #778: the shared freeze helper receives predictable temporary filenames from the HeyGen video and online LUT providers. Another process can preplant those names before a download writes them.

Create a private mkdtemp directory per download. HeyGen writes video.mp4 inside its directory and removes the directory on download failure while preserving the existing null/error behavior. Online LUT downloads stage inside the destination directory, validate the cube, atomically rename to the reserved final path, and remove staging afterward.

The shared freeze helper, download limits, returned metadata shape, successful video lifetime, LUT final path/validation/fallback behavior, and offline LUT path remain unchanged. A successful generated video remains available at its returned localPath, as before. This does not claim to sandbox hostile same-user ancestor renames. No workflow changes; only the media-use manifest fingerprint changes.

Validation

  • 21 provider tests pass, including private-directory permissions, fixed-clock uniqueness, planted legacy filenames, successful bytes/metadata, and failure cleanup.
  • Provider tests fail against the original implementation.
  • Full skills suite: 610 passed, 2 skipped, 0 failures.
  • oxlint, oxfmt, manifest generation, and signed commit hooks pass.

@miguel-heygen miguel-heygen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head security/lifecycle review at 5f6d4cb0a4c1a4b835c03c197adfce1ad865c6f5.

  • skills/media-use/scripts/lib/heygen-video-provider.mjs:110-125 gives the provider clear ownership: mkdtempSync atomically creates the private directory; every download failure attempts recursive cleanup but preserves the original diagnostic/null contract if cleanup itself fails. Success deliberately skips cleanup and returns the still-readable video.mp4; the production resolver copies that localPath only after the provider returns, matching the previous successful-file lifetime.
  • skills/media-use/scripts/lib/lut-preset-provider.mjs:218-232 stages under dirname(fullPath), so validation and the final rename stay on one filesystem. The reserved final path remains the publication owner; download, validation, rename, and staging-cleanup failures all pass through withReservedFile rollback, while URL+params failures still enter the existing deterministic fallback.
  • All four freezeUrl call sites are accounted for: the two temporary callers are now private-directory paths, while both resolve.mjs callers write to withReservedFile's durable exclusive reservation rather than a shared temp name. The planted legacy video and LUT sibling paths therefore have no remaining route into freezeUrl.
  • Focused provider tests pass 21/21 at head. Running the head tests against the original two provider implementations produces three failures, including both planted-path discriminators. A separate invalid-remote-LUT probe produced via=params-fallback, reused lut_001.cube, validated the final cube, and left only that final file—no staging residue. The manifest check is byte-current.

No blocking findings. The JavaScript CodeQL scan completed successfully with no PR alerts; skills tests, manifest, project-skill checks, format/title, and the applicable regression context are green. Broader build/render jobs are path-filtered as the PR states. The disclosed hostile-ancestor boundary is unchanged.

Verdict: APPROVE
Reasoning: Private atomic staging closes both planted-name paths, cleanup ownership is complete on failures, success retains the generated video contract, and LUT validation/publication/fallback remain correctly ordered.

— Magi

@jrusso1020
jrusso1020 merged commit efe2404 into main Sep 8, 2026
46 checks passed
@jrusso1020
jrusso1020 deleted the fix/security-media-download-temp branch September 8, 2026 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants