Skip to content

Clean up partial remote package artifact downloads on failure #220

@GrahamCampbell

Description

@GrahamCampbell

Summary

Remote S3 package artifact downloads can leave a partially written temp file behind when the download stream or destination write stream fails.

This is pre-existing robustness debt, not a regression from the AWS SDK v3 S3 data-plane migration. The previous SDK v2 implementation streamed S3.getObject(...).createReadStream() into fs.createWriteStream(filePath) and rejected on stream errors without deleting filePath. The SDK v3 implementation now uses stream/promises.pipeline(response.Body, fs.createWriteStream(filePath)), which improves error propagation but preserves the same partial-file cleanup behavior.

Impact

  • Failed remote artifact downloads can leave partial files in the framework temp directory.
  • The service/package artifact path is preserved on failure, so this should not affect deployment correctness.
  • This is robustness/cleanup behavior, not currently known to be a security issue.

Suggested Fix

In lib/plugins/aws/package/compile/functions.js, wrap only the streamed download write in cleanup logic:

try {
  await pipeline(response.Body, fs.createWriteStream(filePath));
} catch (error) {
  try {
    await fsp.unlink(filePath);
  } catch (unlinkError) {
    if (unlinkError.code !== 'ENOENT') {
      // Do not mask the original download failure.
    }
  }
  throw error;
}

The exact implementation should avoid masking the original download/write error if cleanup fails.

Test Coverage

Add coverage under test/unit/lib/plugins/aws/package/compile/functions.test.js for:

  • read stream failure rejects with the original error
  • write stream failure rejects with the original error
  • function/service artifact path remains unchanged on failure
  • partial temp file is removed after failure
  • cleanup ENOENT is ignored
  • cleanup failure does not mask the original download/write error

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions