Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Ots – share a secret via one-time URL (github.com/sniptt-official)
77 points by slavomirvojacek on Aug 9, 2021 | hide | past | favorite | 44 comments


Edit: This information is apparently outdated, see discussion below.

> # Why should I trust you with my secrets?

> All secrets are encrypted end-to-end, which means the plaintext values never leave your device. We do not log, track, share, or store the encryption key that protects your secret. You can check the client code to learn more about how we create the encryption key as well as what data is being sent to our servers.

Those are all good, but ultimately don't really answer the question when the decryption key is part of the URL. If you wanted to avoid the necessity to trust secure.sniptt.com the decryption key should at least have been placed inside the fragment. Then you could at least verify if it's being sent to the server or not. As it is it's definitely sent to the server, you'll just have to trust them that they wont use it for anything nefarious


Yep, that's what we do with https://0bin.net.

Also you must avoid client side 3rd party scrips, so no analytics. Also no cdn. I hope ots will self host their google fonts at some point, since you basically slink all secret URL to you google account (albeit without pwd) if you are logged in.

We also had several demands for an url shortener but couldn't find a sustainable way to do it. 3rs party have rate limits and hosting our own would get us back to step one.

DMCA also gets really interesting when you get a request but they don't include the hash because some of their tooling strip it along the way.

Anyway, even with all that, you still trust us since we could inject a rogue script at any time in the page.

So the process really protects only us as host (see our faq), but if you want real security, use pgp or signal. Or if you like the cmd thingy, magic wormhole is kinda awesome.

Still better than sending a password using plan text of course :)


Yeah guess you'd have to write your own client if you really wanted to be sure nobody could read the message in transit. But not sending the password to the server should at least remove the obvious

And credit to the Sniptt team, apparently they do actually put the password in the fragment in newer versions (and presumably you could build your own client for it using this repository if you're extra paranoid).


Yes, I think if they remove the cdn call it will start to be quite nice


The alternative is to do file transfers through WebRTC which is supposed to be end-to-end from my understanding.


If you use a webclient, it doesn't matter, you trust the server no matter what you use. Ots cli has the advantage of being auditable once, and remain on your computer.


True, I was thinking about the problem from a web only perspective, since WebRTC tries to do a direct connection between peers and only uses a third party server when one or both connections are behind a NAT.


If you initiate the session from your browser it doesn't matter. At best you get better cryto since it's native, but nothing more, and you can't store the result, so the receiver has to be connected.

If you don't, then the point is moot, and the problem has been solved with the excellent magic whormhole cli.


Hi, I am one of the core members at Sniptt - we recently made the decryption key part of the fragment precisely for the above reason. I believe the GIF in the README is outdated :) - the newer versions of the CLI ought to place the decryption key in the fragment, but please let me know if that's not the case! Thanks.


Is there a rate limit ? Because the convenience the cli gives would make it really easy to create a FUSE driver for it and store abitrary files.


Hi, yes we've got basic rate limits in place, as well as other protective measures as this is pretty much an open endpoint. Please let me know if you'd like to learn more about how we're protecting the API as this is indeed quite an interesting topic in itself. Thanks!


Great. Are you considering removing your call to google fonts ? It gives way too much data to google for something that is privacy oriented.

Also, do you have a grace period for your burn after reading URL so that it can safely be sent by chats and emails system that visit any link you post ?


Great question - we will likely be looking at G Fonts alternatives as we are planning to revamp the entire website over the coming weeks/months.

As for "grace period", are you asking about URL/link previews and whether those have any effect on reading the secret? If so, the answer is no - the secret will only be read once the client-side JavaScript code is loaded and executed, only certain layout components are rendered server-side.

But I may have misunderstood your question, in which case please do not hesitate to ask again :)


Well, if you receive the url using gmail, google will visit the link, and execute the JS code. If you don't have a grace period, your secret will be unreadable before the human as a chance to get to it.

Just saying that because, while at 0bin we have a 1 day default expiration delay, users can chose burn after reading. But we had to add a small grace period to allow for user to check the URL, reload by listake, send vua gmail, etc.

I thin ots burn after reading by default so it could affect you.


I have run into this problem as well, my webapp sends one-time login/unsubscribe/etc links via email and bots like Office365 click on them, and, yes, they execute JS as well.

A standard workaround is to serve a page with a submit button on HTTP GET, and actually perform the login/unsubscribe/whatever on HTTP POST.

In case of emails, one can also observe the email scanner bots run almost immediately after the email goes out. We can use this as a bot detection heuristic, and make life a little easier for human users:

* if the login link is clicked within 5 minutes of email being sent, treat it as a possible bot activity and require the extra button press

* otherwise, assume the visitor is human, and auto-click the button via JS on page load

More context in this StackOverflow question: https://stackoverflow.com/questions/59281750/strategies-to-p...


Ouch. Google will visit the url and exec the js code. I did not know it sounds insane.


Oh, nice to see you're on top of things. Looks like the online version does indeed include the decryption key separately in a fragment.


This is what firefox send did. The code is still maintained here: https://github.com/timvisee/send


Man, I would love a self-hosted version of this. I've worked at a lot of tiny startups and it often goes like this:

1. Sam needs to send some sensitive credentials to Alex

2. Well, we know we shouldn't use slack or email

3. We should probably use a shared password manager, but that'd be a much larger conversation with the whole dev team

4. There are a ton of options if I search "share secrets securely," but I'd have to dig into a few to figure out if I trust A. that company and B. their security model

5. Fuck it, just share it on slack, delete the message later, and hope for the best. We'll figure out a better solution "next time."

I'd love something simple and self-hosted that I could throw onto heroku, or deploy as a ready-made container, that'd provide one-time-use urls like this. It'd be a great way to have slightly better secret delivery over insecure channels (like slack) in the early days of an eng team before we get around to setting up a unified system for secret sharing. And easy self-hosting means we don't have to solve the trust problem every time.


Hi, I am one of the co-creators of Sniptt.

We faced this ourselves countless times, and it is exactly why we created both OTS and Snip (https://github.com/sniptt-official/snip - like OTS but with the ability to persist secrets and also create shared vaults etc.).

Pleased to say that self-hosted options for both OTS and Snip are currently top of our roadmap.

Keep an eye on the repos for updates! :)


Myself and I'm sure many other's can't wait to try it once you have the self hosted version!


I built this for my company. It’s create-react-app with Redis. Redis works great in this instance because it has built-in functionality for timed expiration (no cron needed). I use Node’s crypto to cipher it in the browser with a randomly generated short passphrase, generate a random ID, insert the ciphered message into the DB with the aforementioned ID, and then use the ID and passphrase to build a URL (passphrase as fragment) that is given to the user to share.


Onceler is one option based on Ruby, in-memory storage only:

https://github.com/ab/onceler


Both S/MIME (encrypted email) and OMEMO (signal style encrypted IM for XMPP with keys generated and verified client side) have been around for quite a while. That your organization doesn't have one of these is a complete failure of whoever is running IT.


For the last couple of years my org has been self-hosting Yopass https://github.com/jhaals/yopass. We use it to share secrets (with one time URLs) with each other.


What about option 6?

Create a GPG key and encrypt / decrypt your messages.

It takes about 10 minutes once to set up your key and then it's easy to send and receive encrypted messages with no central server since you could send the encrypted text over whatever transport mechanism you prefer (gist, email, etc.).


We kinda did this with the snip cli (which is one of our other repos besides the ots cli). It's basically a wrapper around PGP with some additional features like vaults to facilitate sharing PGP encrypted secrets with a team. And... It takes less than 10 minutes to set up :P


If anyone is curious like I was, here's a quick review of what the linked code does:

- Reads plaintext input from stdin

- Symmetrically encrypts the plaintext using a 32-byte [cryptographically] random generated key (AES-256 GCM)

- POSTs the ciphertext and expiry (default 24h) to https://api.ots.sniptt.com/secrets

- The server responds with a URL to view the secret via a response header

- Query string "?ref=cli&v=<version>" are appended to the secret URL

- The decryption key is base64 encoded and appended to the secret URL as a Fragment, "#<key>"

- The secret URL is printed to stdout


Hi, just for completeness - the decryption key is added to the secret URL as a fragment in the penultimate step.


Thanks for the correction, updated.


The problem with these one-time URL's is that most people share them in places where the "one-time" is usually a cloud provider. If you share over IM, the IM service will check the URL to provide preview, or virus scan it. Same for many email providers. By the time you try to open it, it's already been burned.

You can whitelist those parties, but it somewhat defeats the purpose of a secure one-time link.


The encrypted content should be served (and burned server-side) only to a POST request. No sane service can expect a POST request to be idempotent and therefore shouldn’t fire it (twice).


That’s why I password protect any one-time URLs that I ever use, regardless of the provider.

They can’t cause the URL to auto-expire if they don’t have the password.

This password on the one-time URL is something that I share via less secure methods and is easily guessable. It’s only purpose is to prevent the one-time URL from being auto-expired by malware checkers or preview creators.


We're considering adding additional password protection as a new feature (see https://github.com/sniptt-official/ots/issues/2) - this password can then be shared via other channels with the recipient.


Hi, we will be using https://aws.amazon.com/waf/features/bot-control/ which should help somewhat, but I think we will have to spend a bit more time trying to establish a more robust solution.


Hi all, since we've had a bit of traction today I thought I'd ask whether there are any additional features you'd like to see added?

For example, some sort of "self-serve" UI where you could get an API key which would allow users/teams have dedicated rate-limits and not use the default/public limits? Or a self-hosted option where the API could be deployed to the company's cloud of choice?

Or.. leave as is?

Please let us know! :)


> Or a self-hosted option where the API could be deployed to the company's cloud of choice?

Can put it on Tor and give an ephemeral onion link (I wrote https://github.com/cretz/bine to help w/ just these use cases). So people could access via Tor browser or via the same CLI with a "client"/"get" command. Can even have the ephemeral server determine its been HTTP "GET"d and kill itself. Then you don't even need a public website.


Is the server component running at api.ots.sniptt.com open source? I looked through the org's repositories and wasn't able to find it.


It is not at the moment but we are considering making the server + maybe infra repos public in the future, most likely when we've agreed on and implemented some sort of self-hosted option(s).

We will probably write a blog post or two about how we've designed the API + infra around it as there are some interesting topics to be covered.

One of the goals was to also have fun and experiment with a few approaches we've been wanting to use but could not on our daily jobs.

For reference, everything is on AWS and we are using AWS CDK (TypeScript), having moved away from serverless.com recently.

We are ONLY using managed services/resources which are "fully serverless" (API GW, WAF, Dynamo + Dynamo Streams, Lambda, EventBridge, ...) - to save cost, to minimise waste, to reduce ops, etc.

Hope this helps, happy to provide more details.


I'm surprised nobody has created a sort of s3 service that only serves files once. It would be useful to enable services like this or other things like leaving a trail of files that reference future urls.


I have been wondering recently - how secure are URLs? For example Telegram's bot API is authenticated with a token which has to be included in the URL for any request.

What kind of failure modes are there regarding this?


If they click on the URL while their internet is out, then the URL may remain in their browser's search history. The search history may sync between the devices, so if someone has access to your phone, they may get the secret URL when your internet resumes (and you haven't clicked yet).

This probably isn't terrible though.


In this case, the links are one-use, so if it's in your history it's already gone (and therefore secure).


If you use HTTPS, they're pretty much as secure as HTTPS itself is. Anything that would let you obtain or modify the token at that point would be a break of HTTPS.

(Unless you're using some weird system where the secret is in the domain name, in which case it can be a bit more complicated, but who does that?)

If you use HTTP they're not secure at all.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: