S3 bucket security is the combination of identity, permission, exposure, and recovery controls used to protect objects from unauthorized access, accidental publication, destructive changes, and credential misuse. A bucket should be private by default unless public access is a documented product requirement.
That boundary matters because object storage often contains user uploads, database exports, backup archives, reports, and application assets. A single overpowered access key or public-read rule can expose several data classes at once. Raff Technologies has supported more than 15,000 VM deployments, and the same operating lesson applies to object storage: the safest design reduces how much one mistake can affect.
Raff's four-control bucket model is identity, permission, exposure, and recovery. This guide explains how to apply that model to S3-compatible object storage without assuming that every provider supports every Amazon S3 feature. For the wider architecture, start with Storage and Recovery Architecture for Production Apps. For workload selection, read S3-Compatible Object Storage Use Cases for Developers.
S3 bucket security starts with a private-by-default boundary
A production bucket should begin as private. Public access should be treated as a publishing decision, not as the easiest way to make an application work.
Private-by-default means:
- anonymous requests cannot list bucket contents;
- anonymous requests cannot download objects;
- anonymous requests cannot upload or overwrite objects;
- applications authenticate with a dedicated credential;
- users receive access through the application or a time-limited link;
- public objects, when required, live in a deliberately separated boundary.
A practical bucket layout separates trust levels:
production-private-uploads production-public-assets production-backup-archives staging-uploads
This is safer than putting private uploads, public website files, backups, and test data into one bucket with a complicated collection of exceptions.
Amazon S3 recommends blocking public access unless it is explicitly required. Its documentation also emphasizes least privilege and regular review of public or cross-account access. Those principles apply to S3-compatible storage even when the provider uses different control names.
A public bucket is not automatically insecure when public distribution is the intended use case. The problem is undocumented public access or a public policy applied to data that was meant to remain private.
The access-control framework separates identity, data, and actions
The central design decision is who needs access, to which objects, and for which operations.
| Workload identity | Required data boundary | Typical allowed actions | Actions usually withheld |
|---|---|---|---|
| Application upload service | One upload bucket or prefix | Put, read metadata, limited get | Bucket administration, unrelated buckets |
| Background processor | Input and output prefixes | Get input, put output | Policy changes, credential administration |
| Backup job | Dedicated backup bucket | Put, list required prefix, verify object | Public access, unrelated application data |
| Restore operator | Approved recovery scope | Get, list, integrity verification | Permanent broad write unless required |
| Deployment pipeline | Static asset bucket | Put new release objects, invalidate or replace controlled keys | Backup and user-upload access |
| Human administrator | Management boundary | Review configuration and emergency changes | Routine application use with admin credentials |
Use this decision sequence:
- Identify the workload, not merely the person or server.
- Name the exact bucket or prefix it requires.
- List the minimum read, write, list, and delete actions.
- Separate routine operations from administration.
- Decide how access will be revoked and audited.
- Define how deleted or overwritten data will be recovered.
Choose separate credentials when workloads have different owners, environments, data sensitivity, or deletion rights. Choose separate buckets when public exposure, retention, recovery, or lifecycle rules differ materially.
One application credential should control one workload boundary, not every bucket in an account.
Credentials should be scoped, isolated, and replaceable
Long-lived access keys are bearer credentials: anyone who obtains the key material may be able to act with its permissions. Their security therefore depends on both the policy and how the secret is stored.
At Raff, I use a simple review rule: a production application credential must not read or delete objects belonging to an unrelated workload. This decision reduces blast radius even when secret handling fails elsewhere.
Credential controls should include:
- separate production and non-production credentials;
- separate credentials for unrelated applications;
- no credentials committed to source control;
- no secrets embedded in container images or public build artifacts;
- injection through a controlled secret or environment mechanism;
- documented owner and purpose;
- a replacement and revocation procedure;
- removal of unused credentials;
- rotation after suspected exposure, team changes, or integration retirement.
Where a provider supports temporary workload credentials, prefer them over permanent keys. AWS IAM recommends temporary credentials for workloads and least-privilege permissions. Some S3-compatible providers rely primarily on long-lived access keys, so the exact implementation must be verified before the architecture depends on roles, token services, or provider-specific policy conditions.
Avoid one shared key for developers, CI/CD, production applications, backup jobs, and desktop clients. Shared credentials prevent clean attribution and make revocation disruptive because every integration must change at once.
Bucket policies should express least privilege and safe denial
A bucket policy should make the allowed path easy to explain. Complexity is often a sign that too many trust boundaries share one bucket.
A sound policy design answers:
- Which principal is allowed?
- Which bucket or object path is covered?
- Which actions are allowed?
- Which network, transport, or contextual conditions apply?
- Which unsafe actions are explicitly denied?
The narrow pattern is:
Allow: application-upload identity to write objects under production/uploads/* Do not allow: bucket policy changes unrelated prefixes global bucket listing object deletion unless the workflow requires it
Deletion deserves separate consideration. Many applications need to upload and download objects but do not need permanent delete access during every request. Deletion can be handled by a narrower lifecycle, administrative, or cleanup process when the product permits it.
Policy reviews should look for:
- wildcard principals;
- wildcard resources;
- broad
*actions; - public-read or public-write rules;
- permissions spanning production and staging;
- administrative actions granted to applications;
- delete permission without a recovery path;
- conditions copied from another provider without validation.
Amazon S3 documents that narrow Allow rules and broad protective Deny rules can support least privilege. The exact policy language and supported condition keys vary across S3-compatible services, so a policy that works on AWS should not be assumed portable without testing.
Private delivery should use short-lived access paths
Private objects still need to reach authorized users. The application should make that decision without making the whole bucket public.
A common pattern is a presigned URL:
Authenticated user ↓ Application checks authorization ↓ Application creates short-lived object URL ↓ User uploads or downloads one approved object
A presigned URL grants time-limited access using the permissions of the credential that created it. It should therefore be treated as a bearer token until it expires.
Use short-lived URLs with:
- the minimum practical expiration time;
- one known object key;
- server-side authorization before generation;
- unpredictable object keys where enumeration matters;
- file type and size controls for uploads;
- logging around URL issuance where the risk justifies it;
- no exposure in analytics, referrer data, support tickets, or public logs.
AWS documentation notes that presigned URLs can provide uploads or downloads without giving the recipient the underlying security credentials. It also warns that an upload to an existing key may replace the object, which makes key generation and overwrite policy part of the security design.
Presigned URLs move access into time and scope; they do not make a private object public.
Logging, retention, and recovery cover different failure modes
Access control reduces unauthorized actions, but it cannot recover every valid yet harmful action. A credential with legitimate delete permission can still remove the wrong objects. An application bug can overwrite correct data. A user can request deletion and later need recovery within a defined retention window.
Treat these as separate layers:
| Control | Primary purpose |
|---|---|
| Authentication | Prove which identity is making the request |
| Authorization | Limit which actions and objects the identity can access |
| Access logging | Record requests for investigation and operations |
| Versioning, when supported | Preserve prior object versions after overwrite or deletion |
| Retention or object lock, when supported | Prevent deletion or modification for a defined period |
| Backup or replication | Maintain an independent recovery copy |
| Restore testing | Prove that the recovery path works |
Do not claim a control exists simply because the API is S3-compatible. Compatibility often covers common object operations, while versioning, object lock, policy conditions, audit events, replication, and identity features may differ.
The security review should document:
- which events are logged;
- how long logs are retained;
- who can alter logging;
- whether object versions exist;
- who can delete versions;
- whether retained copies share the same credentials;
- how recovery is tested;
- the maximum acceptable data-loss window.
A bucket that is private but unrecoverable is not ready for critical production data.
Raff Object Storage fits a provider-neutral security model
Raff Object Storage is S3-compatible and can be accessed with common S3-aware tools, SDKs, and applications. The security design should begin with workload boundaries rather than assuming AWS-specific account, role, policy, or organization features exist unchanged.
For a typical Raff workload, use this model:
Raff VM application ├── dedicated object-storage credential ├── private application bucket └── short-lived user access generated by the app Separate backup workflow ├── separate credential └── separate backup bucket
This keeps application access distinct from recovery access. A compromised web application credential should not automatically provide administrative control over backups or unrelated buckets.
Raff's practical design rule is to separate at least 2 environments—production and non-production—and then separate credentials again when workloads have different owners or delete rights. Use Raff Object Storage for durable API-addressed files, Raff VM for application compute, and the recovery guidance in Restore Testing Checklist for Production VMs when the stored objects participate in a broader recovery plan.
Before deployment, verify the current Raff controls available for credential creation, bucket access, public exposure, object recovery, logging, and retention. Document any feature difference from Amazon S3 instead of copying an AWS policy and assuming equivalent enforcement.
Conclusion
S3 bucket security begins with a private boundary, a dedicated workload identity, and permissions narrow enough to explain in one paragraph. Separate production from non-production, keep application credentials away from administration, and make public access a deliberate publishing decision.
Then add the controls access policies cannot provide alone: logging, overwrite and deletion recovery, independent backups, and tested restores. Presigned URLs are useful for controlled private delivery, but their lifetime and scope must match the user action.
Continue with Storage and Recovery Architecture for Production Apps to place object security inside a complete storage and recovery design. Review S3-Compatible Object Storage Use Cases for Developers before assigning buckets to uploads, archives, backups, or generated files.