upvote
FYI, that’s currently available in a Humble Bundle with 16 other PragProg functional programming books: https://www.humblebundle.com/books/ultimate-functional-progr...
reply
Great find, grabbed that. Thanks!
reply
Yea I've worked through Elixir in Action and appreciate all book recommendations. My issue is, tutorial style books rarely cover security related concerns.
reply
what do you mean by 'security related concerns'?
reply
How to properly build a liveview thats safe against hijacking the websocket phoenix uses for liveviews. You can just do it from the devtools on client side. With regular HTTP requests at least I know what to look out for, with liveview there are almost no resources on how to build a view securely. Like I was able to just call the functions in my module by just addressing them from my browsers console. Just to name an example.
reply
[1] https://phoenix-live-view.hexdocs.pm/security-model.html

There's a guide in the LiveView docs that walks you through the security model. To be clear, you need to always assume that the user can send you anything. That's a fact of any networked system: Clients need to be assumed to be completely under the control of an evil user, because at the end of the day it is impossible to know whether you're talking to the client you wrote, or some evil program written by an adversary. Any function that acts as a handler for an event/message can be called by the user, at any time. You have to use session/socket state to handle authorization.

reply
I am well aware of that, its much much easier to account for this with regular HTTP handlers in other stacks though. The issue here is that you can call random functions if you guess the signature correctly. Even authorized/authenticated users can and will missbehave if given the chance.
reply
To clarify, when you say "random functions", do you mean arbitrary event handlers like "handle_event("my_event")", despite the intended UI not presenting a way to call that event at the moment? Or do you mean any function in the LiveView module?

The latter doesn't seem to be the case, and if it is would be alarming. The former is absolutely the intended behavior. The client can send events to the server, that's how the whole thing works. If certain events shouldn't be available at certain times, you need to check that server side, and that's going to be true in any http handler.

reply
>"handle_event("my_event")", despite the intended UI not presenting a way to call that event at the moment?

Exactly this, didnt know how to phrase it as it was a while ago where i had this issue.

And thats absolutely not true for any HTTP handler as there's no way for people to easily break out of the intended behavior.

reply
In most other HTTP handlers I've ever used, event handling would be handled by API endpoints, which are trivial for the user to target directly just by going to the Network tab in their browser's developer console.
reply
Honestly just build it using the tutorials and sound mind and you're like 80% there.

This may sound crazy but when any interpreter boots up, but I feel it especially with BEAM, that needs to be your "let there be Light" moment. That's your world, that state is yours and only your will decides what changes.

So yes you can call all functions in your module, that's indeed how it works. But that's your module and that function mutates your world.

Just like you filter what people tell you based on your knowledge, you do the same here.

Most of my methods start with guard clauses.

`return if condition_not_met`

Don't touch my state if I don't agree with what you want me to do.

In Ruby it's essential cause that's how we get RuntimeErrors all over the place. In Elixir it's way easier to do, with pattern matching. And easier since state is what enters the function and will be what leaves.

If you keep this in mind you should inherently write safe code, because in protecting your domain through guards you basically close the door for exploitation by unknown means.

I'll give you one example I just thought of. Where I work we run Rails since the time before time, and as such had a lot of technical debt.

Around Rails 5 or 6 what we call `ActionController::Parameters` had a breaking change. Basically this module processes parameters received from HTTP requests.

Beforehand it just wrapped all it got and handed it over to us. But now it expected us to tell it what to expect. And if didn't find what it expected it blew up with a bang!

Horrible for our hundreds of controllers with `controllers * 4` html templates where all the form keys were hidden.

We either had to add the conventiely available `permit!` call, or find the form keys for all the forms, and add `permit(:name, :address,...)`. A shitload of work before AI.

I ended up monkey patching Rails to generate the lists for us instead of crashing. And for the point of this entire story...

The defaults of most frameworks are very safe, but they require the most verbosity so the framework knows what to expect and to guard it. But there always exists easier and faster ways to the same goal, but it's generally a trade. You get ease, you sacrifice some security.

Don't get in that habit and you'll be fine. And spend a lot of time thinking what could go wrong and guard against them.

reply
I've heard that Phoenix has changed a lot since that book was written. How relevant are those framework specific parts still?
reply
As someone who learned Elixir during the Phoenix 1.7 release, let me tell you: If you downgrade to Phoenix 1.6 and learn from there, you should be fine.

The upgraded versions are mostly the same, but the differences in Phoenix 1.7 are enough to break the tutorials enough to confuse a newbie. Now, in the post-LLM age, that's not nearly as bad. But it was a real pain when I was learning.

reply