HNHacker News
TopNewBestAskShowJobs

cakoose

1,103 karma · joined August 22, 2011

Work: https://anrok.com

[ my public key: https://keybase.io/cakoose; my proof: https://keybase.io/cakoose/sigs/gNz7dqjDBzs5anzP30jhCtr5bcogtlGjKLP2yghDN9I ]

submissionscomments
cakoose··on Bedrock – A modular, WAN-replicated, blockchain-based database
The "blockchain-based" part is misleading.

For one, when people say "blockchain", they're almost always including the clever protocol that enables a currency with no central authority. That's the interesting part. Bedrock doesn't do any of that.

Without that, "blockchain" is just a simple technique for incremental hashing. Bedrock uses that, but it's not substantial enough to sensibly list "blockchain-based" as one of the three top attributes.

(They could have said "Paxos-based". That's the protocol they use to ensure things don't get out of sync.)

Just trying to capitalize on the cryptocurrency hype, I guess. FaunaDB did something similar: https://fauna.com/blog/distributed-ledger-without-the-blockc...

cakoose··on John Carmack on the Joe Rogan Experience [video]
> All notable AI techniques to date specify in exhausting detail the thought processes that the AI should execute in carefully constructed algorithms.

I'm not knowledgeable about AI, but from some of of the game-playing AI research I've read about, it seems like we provide in exhaustive detail the rules and objectives and the AI figures out (though a very resource-hungry process) an "algorithm" (e.g. encoded as a neural network) to play the game well.

I'm not saying that's close to human thought, but it seems far beyond having to "specify in exhausting detail the thought processes that the AI should execute in carefully constructed algorithms."

cakoose··on Why Clojure?
> Now let’s compare that to the equivalent Java program:

  public class SquaresOfIntegers {
    public static void main(String[] args) {
      for (int i=0; i<25; i++)
        System.out.println(i*i);
    }
  }
> This is considerably more wordy, even if you don’t count the enclosing class.

First of all, Java is famously verbose. Nobody is impressed when a language is more concise than Java.

But even ignoring that, the comparison isn't representative. The enclosing class and 'main' function aren't needed for every additional fragment of code, so it probably shouldn't be counted here.

cakoose··on The not so hidden cost of sharing code between iOS and Android
I don't know enough details to say for sure, but some possibilities:

1. People may be more willing to learn Rust. I much prefer the language itself, but also it's clearly on the rise, so it may feel like a better learning investment.

2. The standard library is broader and the package ecosystem is easier to work with, so you might be able to have a more standard stack with fewer proprietary bits.

3. One complication with integrating multiple languages is making different memory management strategies coexist. Rust's type system seems to have ways of making that easier, e.g. neon-bindings.com

cakoose··on PEG Parsers
> Packrat isn't really a parsing algorithm - the PEG is the parsing algorithm.

The way I've seen it presented, PEG is primarily a style of grammar (basically, prioritized choice instead of normal alternation) and Packrat is a parsing algorithm.

http://bford.info/packrat/

cakoose··on Developers don't understand CORS
It's not just the level of detail. For example, what if your advice included one fewer detail:

> The webserver listening in on "localhost:19421" should implement a REST API. This will ensure that only Javascript running on the zoom.us domain can talk to the localhost webserver.

Do you see how that is wrong?

cakoose··on Developers don't understand CORS
No, I wasn't assuming the API will remain identical -- I saw the "should implement a REST API" part of your recommendation.

Here's what's wrong with your recommendation:

1. An AJAX REST API request doesn't necessarily mean "application/json". It could also be "application/x-www-form-urlencoded", which won't necessarily trigger a pre-flight request.

2. Your advice goes into detail on an aspect that is not the crux of this particular vulnerability ("Access-Control-Allow-Origin") but not on the aspects that are:

2a. How to handle the pre-flight request, which is the thing that would actually block wrong-site requests.

2b. If you're relying on a Content-Type of "application/json" to trigger a pre-flight request, then it should be made clear that this is now a security check -- it's common for server code to ignore the Content-Type header as long as the body is valid.

cakoose··on Developers don't understand CORS
The blog post author doesn't understand CORS either! Their advice on how to fix the problem is wrong:

> So what would a secure implementation of this feature look like? The webserver listening in on "localhost:19421" should implement a REST API and set a "Access-Control-Allow-Origin" header with the value "https://zoom.us". This will ensure that only Javascript running on the zoom.us domain can talk to the localhost webserver.

"Access-Control-Allow-Origin" doesn't block the request from going through, it just prevents wrong-origin Javascript from accessing the response.

The original vulnerability actually just a slight variant of cross-site request forgery (CSRF) -- "wrong site request forgery" :-)

For the localhost server to detect wrong-site requests, there are two simple options:

1. Use a CSRF token. This requires a shared secret between the localhost server and the Zoom website.

2. Check the "Origin" header. This requires that the request be an HTTP POST, which is what they should be.

(Note: If you're determined to use some CORS machinery, you could build something more complicated based on pre-flight requests, but there's no point.)

cakoose··on Avoid Indirection in Code
Like others said, not the point of the example.

But even then, there's not enough context to determine if there's a TOCTOU bug. For example, what if it's using an RDBMS transaction?

cakoose··on Ask HN: Old guys, what do you miss about development in the 70s, 80s, 90s, 00s?
Turbo Pascal came with reference manuals, but also with instructional books that taught you OO programming and Windows UI programming from scratch.

They must have been well-written; I didn't really have Internet access, so there was nowhere else to go if I got stuck. Though I was probably a much more determined learner back then.

cakoose··on Gmail really wants me to say yes
Another explanation: "no" responses require more information.

If you are saying yes, then that's basically all you need to say. If you're saying no, you usually also provide a reason, so you probably wouldn't use any of the short, generic "no" responses Gmail would come up with.

cakoose··on Adventures in WhatsApp DB – extracting messages from backups, with code examples
> [...] discover that WhatsApp doesn’t work on it due to a weird message > "Your phone date is inaccurate! Adjust your clock and try again." > I have no idea what do date issues have to do with not starting WhatsApp but fixing the date and time didn’t help [...]

Some network protocols use timestamps for security. For example, OAuth 1.0 HMAC used timestamps as part of its mechanism for preventing replay attacks.

I have no particular insight into what WhatsApp is doing, though.

cakoose··on TLS 1.3 is going to save us all, and other why IoT is still insecure (2017)
This article exaggerates the deficiencies of TLS 1.2.

- Because of the TCP handshake, the difference between plain HTTP and TLS 1.2 is 2 RTTs vs 4 RTTs, not 1 vs 3.

- TLS 1.2 supports session resumption, which can bring it down from 4 RTTs to 3.

- The article's "TLS 1.3 Session Resumption" diagram is actually describing "0-RTT" resumption, which is vulnerable to replay attacks and can't be used without carefully considering semantics of the HTTP POST request. (https://blog.cloudflare.com/introducing-0-rtt/#whatsthecatch)

TLS 1.3 is still better in a bunch of ways, but there's no need to be misleading.

cakoose··on Otonomo, with nearly $55M in funding, is cloning our product
The APIs in the blog post were not invented by Smartcar. Like most HTTP-based APIs, Smartcar's authorization endpoints follow the OAuth 2.0 standard, which specifies the exact parameter names and how they should work: https://tools.ietf.org/html/rfc6749#section-4.2.1

Maybe Otonomo copied more than that, but the blog post only covers the OAuth stuff, so it's incorrect to conclude that Otonomo "stole the whole public facing architecture".

Yea, Otonomo obviously lifted from Smartcar's docs, which is lazy and unclassy, but it's not _that_ big of a deal. I bet most people who implement OAuth end up using an existing company's API docs as a guide; they just usually know better than to copy entire sentences.

The Smartcar blog post is over the top. It makes it seem like their OAuth docs are their value proposition. I really hope it didn't take "months of ideation, engineering, chatting with customers, and iteration" to dream them up.

cakoose··on Size visualization of Go executables using D3
> as discussed in my previous article [1], Go uses memory instead of registers to pass arguments and return values across function calls.

[1] https://science.raphael.poss.name/go-calling-convention-x86-...

This is very surprising for a language that targets somewhat high performance.

Looks like it's a 5-10% performance hit, but makes it easier to provide good backtrace information: https://github.com/golang/go/issues/18597

cakoose··on AirPods with Wireless Charging Case
Your point that you can use one while charging the other was valid and helpful.

But saying "I'll just address this point, because it is categorically incorrect" was unnecessarily aggressive. With that opening, I think people expected a solution with no caveats.

cakoose··on FaunaDB 2.5.4
> One annoying thing that affects pretty much every database with transactions is that the effort of retrying failed transactions is pushed onto the user, by necessity. > > But if your transactions are airtight chunks of code... then the DB can retry them for you and provide a simpler interface to your app code.

Building an FaunaDB query is more difficult than just writing session-based DB code.

But if you are willing to build FaunaDB queries, it should be strictly easier to write session-based DB code as "airtight" chunks that are easy to retry.

cakoose··on Serverless collaborative editor using CRDT
Projects doing similar things:

Atom: https://blog.atom.io/2017/11/15/code-together-in-real-time-w...

Xi: https://github.com/xi-editor/xi-editor/blob/master/docs/docs...

cakoose··on An update about Redis developments in 2019
The comments in the code make it seem like absolutely no information about the secret is leaked:

> /* Again the time of the following two copies is proportional to > * len(a) + len(b) so no info is leaked. */ > memcpy(bufa,a,alen); > memcpy(bufb,b,blen);

If the attacker controls one of the inputs, the execution time reveals something about the length of the other input, right?

Or maybe you just meant that the length is leaked by the contents are not leaked? (I agree that it's generally considered ok for "timing-safe equals" functions to leak the length of the secret. But if you ARE allowed to leak the length, you can simplify the code by just checking the length in the beginning and exiting if they're not equal.)

And if you don't want to leak the length, it's easy: pre-SHA-512 the secret and then only compare hashes instead of comparing the full strings.

cakoose··on Sample cloud-native application with microservices
Exceptions seem less unstructured than "goto". With exceptions, at least everything is strictly nested.

And there's a new class of bugs: forgetting to check for an error. In Rust, the compiler won't let you forget. With exceptions, forgetting to handle an exception will result in a somewhat controlled termination process. In Go, execution will just continue in a bad state.

cakoose··on Sample cloud-native application with microservices
What do you mean by "eliminated a whole class of bugs"?
cakoose··on PyPy for low-latency systems
Relevant: "Blade: A Data Center Garbage Collector" (2015, https://arxiv.org/pdf/1504.02578.pdf)

Terrible title, but basically the same idea.

cakoose··on How to implement strings
That's similar to C++11 std::string, which has a length indicator and a null terminator.

(I believe this was often true for std::string implementations before C++11, but apparently C++11 made it a requirement.)

cakoose··on How to implement strings
> The character \0 marks the end so we call this zero-termination. [...] The only advantage of this representation is space efficency.

Sort of a tangent, but zero termination (aka null termination) can make parsing from a string slightly simpler.

Without a null terminator, in addition to processing each character, you need to check if you've hit the end of the string. With a null terminator, the end-of-input checking is elegantly part of the "processing each character" step.

You can always add a null terminator character to the end of your string in the length+data representations as well, but if your strings don't come that way you end up having to make a full copy.

cakoose··on Global variables are bad (2013)
You said that instance variables were just as bad as module globals. I was pointing out cases (w.r.t. software engineering, obviously, since that is what this thread is about) where module globals are worse.

Yes, programmers have to be aware of what they're doing, but that's true of any programming construct. It doesn't mean that we shouldn't identify the dangers.

cakoose··on Goodbye Python, Hello Go
> You're going async by using Golang, why not in python?

In Golang, you're still using a thread-based abstraction.

In Python, "going async" involves switching to a slightly different style of programming and using different I/O libraries. While that has advantages, using threads lets you stick with the standard style.

cakoose··on Global variables are bad (2013)
> If module global variables are considered truly horrible, the same can be said about instance variables inside classes. They are as good (or bad) as module globals in the sense that they represent shared state and can potentially be mutated by any method/member function in the class.

Assuming Python-like modules, module-level globals are worse for encapsulation.

1. A function can access module-level state without having been explicitly passed a reference to it.

2. You can't create additional instances of module-level state. For example, if your app server uses a module-level global for the server listening socket, you can't run two app server instances in the same process.

cakoose··on Global variables are bad (2013)
Mutable variable that have exactly one instance (globally) cause some of the same issues, which is why people might casually lump them in with "global variables". (It would be nice if everyone used more precise terminology, though.)
cakoose··on Demystifying CORS
Yeah, this aspect of CORS is almost never properly explained.

First off, it's not about the authentication cookie. It would be simple enough for browsers to just omit cookies in cross-domain requests.

Here's an example of a real issue:

1. You have a network-attached storage device on your LAN.

2. Because the device is not accessible from the public internet, you have decided not to enable authentication. Anyone on the local network can issue requests.

3. You visit a malicious website.

4. That website's JS makes network requests to your device.

Basically, when you run JS in your browser, it's using your computer's network context. That context may have privileges that not everyone has (e.g. authentication based on source IP). You don't want random JS code to have those privileges.

cakoose··on Rust in production at Figma
Yeah, waiting for Rust's async/await to mature is probably a good idea. But I'm not sure why they didn't just use threaded I/O instead.
← PreviousPage 5 of 8Next →