Skip to content

fix: skip ACL params when bucketObjectsACL is false#5411

Closed
ghost wants to merge 1 commit into
mainfrom
unknown repository
Closed

fix: skip ACL params when bucketObjectsACL is false#5411
ghost wants to merge 1 commit into
mainfrom
unknown repository

Conversation

@ghost

@ghost ghost commented May 13, 2026

Copy link
Copy Markdown

Summary

Fixes uploads failing with AccessControlListNotSupported on S3 buckets
with BucketOwnerEnforced policy. Since April 2023, AWS S3 creates all new
buckets with ACLs disabled by default, but lib/storage/s3.js always sent
ACL headers in every request with no way to disable them.

When bucketObjectsACL: false is passed, ACL headers are now skipped
entirely in copyIn, enable, and disable calls.

Closes #5366

What are the specific steps to test this change?

  1. Create an AWS S3 bucket with ObjectOwnership: BucketOwnerEnforced (default since April 2023)
  2. Configure uploadfs with bucketObjectsACL: false and disabledBucketObjectsACL: false
  3. Try uploading a file — it should succeed without ACL errors
  4. Verify existing users without these options still get public-read default behavior

What kind of change does this PR introduce?

  • Bug fix

Make sure the PR fulfills these requirements:

Other information:

Note: I have not updated the changelog or tests yet —
happy to do so if the maintainers approve this approach first.

@boutell

boutell commented May 13, 2026

Copy link
Copy Markdown
Member

This eliminates the ability to enable or disable files entirely, or makes it only pretend to do those things, which would not meet the need.

A better approach would be to look at what's done in the local and azure storage backends, both of which handle disabling access by hashing the filename in a secure way.

Ideally that approach should be made available globally with reusable logic.

@boutell boutell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for contributing!

Unfortunately this eliminates the ability to enable or disable files entirely, or makes it only pretend to do those things, which would not meet the need.

A better approach would be to look at what's done in the local and azure storage backends, both of which handle disabling access by hashing the filename in a secure way.

Ideally that approach should be made available globally with reusable logic.

@boutell

boutell commented May 13, 2026

Copy link
Copy Markdown
Member

(Submissions must also pass the test suite.)

@ghost

ghost commented May 16, 2026

Copy link
Copy Markdown
Author

Hi @boutell — I've refactored the approach based on your feedback:

disable() and enable() now use filename hashing via utils.getDisabledPath() when disabledFileKey is set — same pattern as the local and azure backends
Old ACL-based path kept as fallback for backward compatibility
copyIn now also skips ACL param when bucketObjectsACL: false

Please let me know if this approach looks good and I'll update the changelog and tests too!

@boutell

boutell commented May 17, 2026 via email

Copy link
Copy Markdown
Member

@ghost ghost force-pushed the fix/s3-skip-acl-when-disabled branch from 7d318cf to c6ea971 Compare May 18, 2026 07:27
@ghost

ghost commented May 18, 2026

Copy link
Copy Markdown
Author

Hi @boutell — I've updated the PR with the filename hashing approach using utils.getDisabledPath() for disable/enable, same as the local and azure backends, with ACL fallback for backward compatibility.
Changelog and tests will be added once you confirm this looks good.
Enjoy your vacation!

@boutell boutell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We'll need test coverage showing the tests work with or without this option. Also a minor nitpick about code formatting.

We're also going to need to think about a migration path, but this is fine for new projects as written, so I won't hold you up for that.

if (self.options.disabledFileKey) {
const dPath = utils.getDisabledPath(path, self.options.disabledFileKey);
return self._copyObject(dPath, path, function(err) {
if (err) return callback(err);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please follow the convention (no single-line statements in if, use {})

@ghost ghost closed this by deleting the head repository Jun 23, 2026
This pull request was closed.
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.

S3: uploads fail with AccessControlListNotSupported on buckets with BucketOwnerEnforced

1 participant