Repository navigation
Conversation
…et is forbidden HeadBucket is authorized as s3:ListBucket with no s3:prefix. A deploy role that may list only its own prefix of a shared deploymentBucket (a common least-privilege setup) gets a 403 for a bucket it can deploy to, and the deploy fails with "Could not locate deployment bucket ... Error: UnknownError" (the 403 has no body). Serverless v3 and osls before oss-serverless#113 called GetBucketLocation, which needs only s3:GetBucketLocation. On a 403 only, ask GetBucketLocation and run the result through the existing region check; an empty constraint is us-east-1. Every other outcome is unchanged.
GrahamCampbell
self-requested a review
October 6, 2026 20:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Since #113,
ensureValidBucketExistschecks a customprovider.deploymentBucketwithHeadBucket. S3 authorizesHeadBucketass3:ListBucketwithout ans3:prefix, so a deploy role whoses3:ListBucketis limited to its own prefix of a shared deployment bucket gets a 403 for a bucket it can deploy to. That's a common least-privilege setup: one shared bucket, each service/stage role scoped toserverless/<service>/<stage>/.The deploy then fails before uploading anything:
(
UnknownErrorbecause a HEAD 403 has no body.) The same roles worked with Serverless v3 and osls before #113, which calledGetBucketLocation; that needs onlys3:GetBucketLocation.A policy that hits this:
{ "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::my-shared-bucket" }, { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::my-shared-bucket", "Condition": { "StringLike": { "s3:prefix": ["serverless/my-service/prod", "serverless/my-service/prod/*"] } } }, { "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"], "Resource": "arn:aws:s3:::my-shared-bucket/serverless/my-service/prod/*" }Change
Only when
HeadBucketfails with a 403 (isS3HeadBucketForbiddenError), askGetBucketLocationand feed the result through the existing region check. An emptyLocationConstraintmeansus-east-1, which was the reason for #113, andEUis normalized as before viagetS3BucketRegion. If the fallback fails too, the original error is reported exactly as before. A successfulHeadBucketand any non-403 failure follow the same code paths and messages as today.Tests
Four unit tests in
ensure-valid-bucket-exists.test.js:HeadBucketfalls back toGetBucketLocationand accepts aus-east-1bucket;DEPLOYMENT_BUCKET_INVALID_REGION);HeadBucketerror (DEPLOYMENT_BUCKET_NOT_FOUND);We're carrying this exact change as a
pnpm patchofosls@4.4.0while we move our services from Serverless v3 to osls, and would like to drop it. I haven't checked whether 3.x needs the same change (#113 landed there too); happy to backport if you want it.