Two earlier sweeps taught momo’s S3 gateway to say “not implemented” for unsupported bucket and object subresources. This is the last sweep: the handful of operations that were not subresources at all but still slipped through to the wrong handler. With these six fixed, every unsupported S3 operation we know of now fails honestly.

The Real Problem

Three kinds of operation were still misrouting:

  • SelectObjectContent — a SQL-like query that filters an object’s contents and streams the matching rows back. Unsupported, it fell through to a plain GetObject and returned the whole object.
  • UploadPartCopy — a server-side copy that uses an existing object as one part of a multipart upload. Unsupported, it fell through to UploadPart and treated the copy request as an ordinary data upload.
  • Four bucket configuration subresources — analytics, inventory, metrics, and intelligent-tiering — that fell through to object listing.

Each returned either the wrong data or a 200 over an operation that never happened.

Why the Obvious Fixes Failed

There was no single mechanism to extend. SelectObjectContent is a query action on an object; UploadPartCopy is signalled by a request header, not a query parameter; the four configuration subresources are bucket-level. A fix had to cover all three shapes rather than lean on one router hook.

The tempting shortcut was to reject anything that looked unusual. That would have broken supported features that share the same URLs and headers — multipart uploads in particular.

The Solution: Complete 501 Coverage

We extended both rejection lists and added one targeted intercept:

OperationHow it is signalledWhere it is rejected
SelectObjectContentQuery on an objectObject-level rejection
UploadPartCopyX-Amz-Copy-Source header on a multipart PUTDedicated check in the PUT dispatch, before the part-upload handler
analyticsBucket configuration subresourceBucket-level rejection
inventoryBucket configuration subresourceBucket-level rejection
metricsBucket configuration subresourceBucket-level rejection
intelligent-tieringBucket configuration subresourceBucket-level rejection

The four configuration subresources joined the existing bucket-level list. SelectObjectContent is a query action, not a subresource, so it needed its own branch rather than a list entry. UploadPartCopy is distinguished by a header, so it is checked in the PUT dispatch before the ordinary multipart part handler can claim it — the one ordering-sensitive part of the change.

Complete 501 Coverage

PhaseTargetCount
P1SSE-KMS / SSE-C2
P3Bucket configuration subresources16
P4Object-level subresources5
P5Remaining operations6
TotalAll known unsupported29

How We Verified

  • All six operations return 501 Not Implemented.
  • The UploadPartCopy check runs before the part-upload handler, so there is no collision.
  • Existing multipart operations (uploadId, partNumber) are untouched.
  • Bucket configuration subresources such as ?versioning still return 501 from the earlier phase.

Failure Modes

RiskGuard
UploadPartCopy intercepted after the wrong handler claims itThe check is placed before the part-upload branch in PUT dispatch
Over-rejecting normal multipart uploadsThe copy check requires the copy-source header; a normal part upload does not carry it
A new unsupported operation slipping throughBoth rejection lists and the dispatch intercept are the single place to add coverage

When NOT to Use This

  • For supported operations. The lists contain only operations we do not implement. Never add a supported one.
  • As a substitute for implementation. This is honest failure, not a feature. When we implement one of these, it leaves the list.

Engineering Standards (🛡 Sentinel)

Per docs/CORE/STANDARDS.md: 🛡 Sentinel — complete, honest 501 coverage with no silent misrouting.

References / Dig deeper