I’ve just criticized people writing low-effort blog posts about minor issues, but I think I have to write another “minor issue article” myself. It’s mostly a warning to people who’s gonna try to integrate Isso into their websites… and I’ve spent a whole week working on Isso, so it’s not exactly a “low effort” article anyway.

Talking about the original Isso… Well… I can almost understand why React.js is better for most developers than the vanilla JS. The code has copyrights from 2014, but I believe even for 2014 this code was a dogshit. So I think I should leave few notes for someone who might decide to (not) integrate Isso into his website.

The previous article about self-hosted commenting was kinda open-ended because I haven’t picked any one solution for myself.
That’s because I was unable to find a perfect solutions, and I believe the reason is because self-hosted commenting service should be a framework rather than a separate service. I heard opinions like “commenting should be an integral part of the whole website” — but this one is an opposite extremety.

I ended up heavily modifying Isso, chosen for a simple reason — it is small and has some minimal amount of required features already implemented. The second best contendant was Remark42, which has flawless backend, but its official frontend is so overcomplicated that maintainers themselves have problems with new features implementation. Don’t get me wrong: it’s not like Remark42 is not possible to employ, but it’s definitely more than a week for all the todo-s I had.

To clarify: I mostly did coding with Aider + Gemini flash, it would take much more time when fully manual coding with the unfamiliar codebase.
I’m still hatching an idea of a framework for explicit fullstack development which can be imagined as a child of Alpine.js and SSR Solid.js, but this is not the topic of the current post — although such a framework seems to be particulary suitable for the self-hosted commenting due to its glue-like role between the fully static and fully dynamic content.

So, what I’ve encountered was:

  • Isso employs innerHtml for DOM generation. Double quotes are escaped by employing single quotes. I did not even know browsers can actually handle single-quoted HTML correcty, but they do. Don’t do this at home, kids.
    Hell, nowadays even uhtml does not employ innerHtml beyond the initial template parsing;

  • Name-email-website localStorage save/load can inject arbitrary HTML from the fields, as a result of innerHtml assignment;

  • Html5lib dependency is used in only once place to extract the title of the original page. In the world of pink ponies this allows us to get the title from a reputable source i.e. our own website. In the world of filthy humans this means we introduce SSRF into our system, because we never check the Host/Origin/Referer, while CORS only implements blocking on a well-behaved client side. Remark42 had a similar problem. So I ended up dropping the whole title thing and employing raw URL-s — thanksfully, my blog has readable URL-s;

  • Authors really wanted to share the cookies with the whole internet. Made at least some of them HttpOnly and configured stricter SameSite;

  • The hashing of email/IP with 1000 iteration pbkdf2 makes the whole IPv4 range hackable in half a day. Yes, you can increase pbkdf2 iteration count, but that will put a heavy load onto backend because the hashes are not stored in DB despite being published to the user. But remote IP and email are stored in DB as a plain text. I’ve added a corresponding disclaimer for anyone willing to leave their personal data in the provided commenting form. I put Isso into an isolated rootless container, so it’s totally isolated from the rest of the system, but the personal data resides inside the container;

  • As I already mentioned in the previous article, proof of work things like Altcha and Cap are not really protecting anything. at least not more than adding an opaque round-trip into the comment posting logic. So that’s pretty much what I did in the end — implemented a simple opaque back-and-forth negotiation that frontend has to pass before its submission is accepted by backend. Noteworthy, I employed sidecar Redis as a volatile storage of tokens, despite the fact https://github.com/byko3y/python-shared-objects was specifically designed to handle this exact case without any external servers. I do realize Python Shared Objects was not tested well, Isso is already unreliable enough, and I don’t see much future in supporting neither Isso nor Python Shared Objects.

  • Isso is employing synchronous workers, which is a great way to immediately die from any DDoS in 2026. Of course, the only thing that would die is commenting, which is not a big deal.

Non-framework JS projects don’t have to be this horrible. It almost seems like JS devs are perfectly fine with unsafe practices and spagheti code — just like old school PHP devs are. And I can perfectly understand the motivation behind architects of React.js who tried to minimize the damage from developers randomly modifying some remote variable they don’t like or employing innerHtml “because it’s quicker this way”.

However, to handle 10 comments a year this “guestbook” solution is more than enough. So far in few days I’ve got zero spam (and I do get bot scans). To be fair I don’t even see any submission failures by bots because Isso completely lacks classic HTML forms, so figuring out how to corectly fill HTTP API fields is not so straightforward even for LLM, while browser-based bots need to be patient enough to wait through all the loads and round-trips.

Sad to say, I will not publish the updated source code because most of the changes are related to security and anti-bot matters, it’s pretty much “security by obscurity”.

There are not much other decent options for self-hosted commenting. Remark42 is a solid choice if you don’t need to tweek anything. Twikoo might be another option, especially since 2023 when it first got LokiJS (MongoDB-compatible) mode for file-based storage — but do note that I haven’t tried examining Twikoo source code, so I cannot comment on its quality yet.