Amazon S3

How I Share a Private S3 File Without Touching Bucket Permissions

One AWS CLI command, one temporary link, zero cleanup

Every time someone needs a file that lives in a private S3 bucket, I used to face an annoying choice: open up permissions permanently, or fumble through the console. The presign command solved that for good — here's how I use it, and what I'm still careful about.

The problem with sharing anything from a private bucket

I keep most of my working files in S3, and almost none of that bucket is public — which is exactly how it should be. The trouble shows up the moment someone else needs to see one specific file. They click the object URL in their browser and get an access denied error, because they don't have permissions on the bucket. Nothing is actually wrong; the bucket is doing its job.

The tempting shortcut is to just grant that person access, or worse, flip the object or the bucket to public. But that's solving a one-off, temporary need with a permanent, structural change. Now you've got a permission grant sitting around that you'll probably forget to revoke, or a public object that stays public long after anyone needed it. For a single file that one person needs to see once, that's a lot of surface area for very little benefit.

What I actually want in that moment is narrower: temporary access to one object, for one person, for a limited window of time, without changing anything about how the bucket is configured. That's precisely what a presigned URL gives you, and it's the tool I reach for now by default whenever this comes up.

Generating the link with presign

The AWS CLI has a presign command built for this. Point it at the object you want to share — in my case a file called example.png — and it hands back a single URL. That URL encodes temporary credentials and a signature, so anyone holding the link can fetch that one object directly, without needing an IAM user, a role, or any standing permission on the bucket at all.

I'll be upfront that the exact flags and full invocation are easy to get wrong from memory alone, so if you're following along, it's worth checking the current AWS CLI documentation for the precise syntax rather than reconstructing it from a description. The shape of it, though, is simple: you're telling the CLI which bucket and key to sign, and it does the cryptographic work of producing a URL that S3 will honor without further authentication.

One detail that trips people up: the URL it returns is long, and every part of it matters. It's not just a path to the object — it's got query string parameters tacked on that carry the signature, the expiration, and the credentials scope. If you copy only part of it, or a chat client or email truncates it, the link simply won't work. I've gotten in the habit of copying the entire line as one block and pasting it somewhere I can immediately verify it wasn't cut off, rather than trusting that a partial copy will still resolve.

Why the link expires on its own

The part I like most about this approach is that I don't have to remember to clean anything up afterward. When you don't explicitly set an expiration, the presigned URL is commonly described as defaulting to one hour — after that window, the link simply stops working, and there's no permission left over to revoke because none was ever granted in the first place. That said, I'd treat the exact default as something to confirm against the current AWS CLI docs for the version you're running rather than a fixed rule, since defaults like this can shift between versions or depend on how your CLI is configured. If the timing matters for what you're doing, it's worth setting the expiration explicitly instead of relying on whatever the default happens to be.

Either way, the underlying idea holds: this is self-expiring access. I generate the link, send it to whoever needs it, and by the time I've moved on to something else, the door has already closed behind me. Compare that to adding someone to a bucket policy or an IAM group — that access sits there until a person remembers to remove it, which in practice can be months or never. A presigned URL fails safe by default.

That's also why I don't stress about the link being technically public for that window. Anyone with the URL — not just the person I sent it to — can open it while it's valid, since there's no additional login check on the other end. For a screenshot or a demo file, I genuinely don't mind that it's reachable by whoever has the link for an hour; the cost of that exposure is basically zero. But that tradeoff only holds because the file isn't sensitive. If I were sharing something that actually mattered — customer data, credentials, anything with real consequences if the wrong person opened it — I wouldn't lean on the casual version of this. I'd shorten the expiration deliberately, send the link through a channel I trust, and think about who might realistically intercept it. The mechanism doesn't care what's in the file; the judgment about how carefully to handle it still has to come from me.

Opening the link myself

Here's a small thing that made the whole exercise feel more real to me: after generating the link, I didn't actually remember what the file was. I opened my own presigned URL the same way the recipient would, and it turned out to be a screenshot of my app controller repository — not something dramatic, just a leftover from earlier work I'd used as a convenient test file.

It's a minor moment, but it underscored something useful about how presigned URLs work: the CLI doesn't need to know or care what the object contains. It's signing a path, not inspecting content. That's obvious in principle, but there's something clarifying about watching it play out — the tool does exactly what it's told, and the content on the other end is entirely up to whatever you happened to point it at.

Conclusion

If you've got a private S3 bucket and a recurring need to hand someone a single file without reworking permissions, try running presign against a real object in your own bucket the next time it comes up — it takes less time than writing out an access policy, and you can watch the link stop working on its own once the window closes.

Official AWS references

KEEP PRACTICING THE DECISION

Learn the concept, then test the edge case.

The Solutions Architect Associate course in TutorialRepo combines guided lessons, scenario questions, review, and course-aware explanations.

  All articles