Joey (NostrComments)'s avatar
Joey (NostrComments)
slurpnc@coinos.io
npub1ewxm...ds9e
I build NostrComments — a browser extension that adds a censorship-resistant comment section to every website, powered by Nostr — and Attest, a Nostr signer for Firefox that holds your key so a website never has to, and asks before it signs anything. Free and open source, always. NostrComments for Firefox: https://addons.mozilla.org/en-US/firefox/addon/nostrcomments/ NostrComments for Chrome: https://chromewebstore.google.com/detail/nostrcomments/ebmgdpicceaencegknannfaljhbfgido Attest for Firefox: https://addons.mozilla.org/firefox/addon/attest/ Monero: 87aDTPD9HQx2QenKsS7MvHDdqsziFPD7UB37X6G5XVXc2ZPhAs8DdEKUPYJijVcRjj1gU5KvxLCTfWUKWqrd1D5o8uw5EpM
One thing the article leaves out: what to do if you already put money in. Call the number printed on the machine straight away. Some operators hold a new customer's first purchase for a while before it goes out (CoinFlip says 48 hours), and inside that window the money can still be stopped. After that, a bitcoin payment cannot be reversed. And for anyone reading this for a parent: Microsoft, banks, police and tax offices never ask you to pay in bitcoin or gift cards. Anyone who does, and won't let you hang up, is the scam. Read the thread:
Good advice. Two things to add: a "recovery service" that asks for a copy of your ID before doing anything is collecting material for the next scam, so never send it. And report it to your financial regulator too, not only the police (BaFin in Germany, the FBI's IC3 at ic3.gov in the US), because regulators publish warnings that protect the next victim. Read the thread:
Worth knowing how this one worked: tapping the notification just opened the real wallet app, so nothing looked wrong. The phishing link only showed up afterwards, in Android's notification history. A clean-looking tap proves nothing about where a notification came from. The rule that covers every variant: a hardware wallet's recovery words go on paper or metal and nowhere else. No app, website, support agent or "critical vulnerability" alert ever needs them typed in. If a message says your wallet is at risk, close it and check the maker's official site or account yourself. Note that it is still unconfirmed whether SecuX's own systems were involved, so no need to panic about the device itself. Read the thread:
Security update for NostrComments: please make sure you are on 23.10.3 or later (Firefox and Chrome both have it). Two problems were found and fixed this week. On some websites, a malicious page could read a private key stored in NostrComments, or press the panel's own buttons, such as "Show my key" or setting a password on your key. Keys kept in a signer extension (Alby, nos2x, Attest) were never at risk. We have no indication that these flaws were ever abused, but if you keep a key in NostrComments and want to be certain, make a new one under Settings → Rotate key. For developers: the panel lives in an open shadow root, so the page can restyle it and click its buttons. The fixes make every key-related control require a real click, and stop reading anything security-relevant from state the page can change. The details are in the security advisories on GitHub.
A practical note for client developers, from a bug I just fixed in my own extension: signer extensions inject window.nostr asynchronously, so it may not exist yet when your code first looks. My client checked once five seconds after load and then every five seconds, which meant that for the first seconds of every page a user who had already chosen their signer saw "Not connected" and a Connect button. Now it looks at 0.3, 1, 2 and 4 seconds, then backs off. Two details that matter: only check whether window.nostr is present during those early looks, and call getPublicKey once, when you actually connect, so the signer doesn't get a burst of requests. Read the thread:
GM Nostr ☀️ Every time I pick a new alarm tune I think: this one's lovely, I'll finally wake up happy. Three days later I hate it with a passion. Has anyone found an alarm sound that survives?
A real-world data point on the Users figure, since this page only says it counts installations rather than activity: in August my extension's listing reported about 5,000 users. The breakdown was 97% United States and 79% ChromeOS, and nothing else I could measure moved with it, so I never believed it. By October the figure had dropped to 22, which matches what I can actually observe. Lesson: before you quote this number, look at the country and OS breakdown. A distribution that looks nothing like your audience is probably not your audience. My extension has no telemetry by design, so I count real use from the outside instead: how many distinct keys have published something with it. Read the thread:
A practical caveat for extension developers who use shadow DOM to keep their UI safe from the page: an open shadow root does not keep other code out. I put my extension's panel in one, and yesterday a user's Share button simply vanished on one site. The button was in the DOM, with no inline style, but its computed display was "none" and its colors had been rewritten, so another stylesheet had been injected into the shadow root. The likely culprit is a content blocker's social-widget filter, because the button's class was "share-btn", a name those lists hide on purpose. The fix was a class name no filter targets. Lesson: inside an open shadow root, treat your class names as public, and don't give a control a name that sounds like an ad or a widget. Read the thread:
This is the project's own thread. Questions, ideas, or things that annoy you about NostrComments: leave them here, and I'll answer. Bugs are easier to track in Issues. Recent fixes: the Share button could be hidden by content blockers (fixed in 23.9.5), and it could post twice with a slow signer (fixed in 23.9.4). Read the thread:
Some practical experience, since the article stays general: I push my project to GitHub and to two Nostr git servers (gitnostr.com and relay.ngit.dev) with a single script, so the article's "we don't need to stop using GitHub" is exactly how it works in practice. Yesterday I sent my first patch to a repo that lives only on Nostr, with "ngit send". One member-only relay refused it with a 403, but the others took it, so it didn't matter. That's the resilience the article describes, in one terminal line. One correction: GRASP isn't so much a bridge as a server type that bundles a relay and a git server, and it creates the repository automatically when your announcement lists it. That's why you don't have to set anything up on the server side. Read the thread:
Worth knowing if you're thinking of applying: the money is for the people doing the hunting (AI tokens, servers, fuzzing), not for projects that want an audit of their own code. All five grantees in this first round work on Bitcoin infrastructure: Core, libsecp256k1, btcd, BTCPay and mempool. Applications are fast-tracked via opensats.org/apply/red. Read the thread:
Worth knowing if you're thinking of applying: the money is for the people doing the hunting (AI tokens, servers, fuzzing), not for projects that want an audit of their own code. All five grantees in this first round work on Bitcoin infrastructure: Core, libsecp256k1, btcd, BTCPay and mempool. Applications are fast-tracked via opensats.org/apply/red. Read the thread:
I put a comment section on every web page on the internet. You can now: - discuss news articles without censorship or being banned - warn each other for possible scam websites and many other things with NostrComments Install the browser extension now on: Chrome: https://chromewebstore.google.com/detail/nostrcomments/ebmgdpicceaencegknannfaljhbfgido Firefox: Puts the Freedom back in your hands Open source: Github: #nostr #foss #freedom #censorship
NostrComments puts a comment thread on every web page on the internet. This means you can post and read comments about the web page from other users. The thread lives on Nostr relays, not on the site. There is no middleman: no server of mine, no account, no telemetry, and the site you're commenting on can't close it. For users: install the extension, make a key in one click or use your existing Nostr signer, and comment anywhere. That includes the news site that turned comments off, the paywalled article, the government page and the press release. Nostr notes that tag a page's address show up in its thread too, so a page isn't always empty. Zap a good comment, mute the bad ones. Nothing is sent until you switch it on; after that, the relays you choose can see which pages you read. For developers: comments are plain NIP-22 events (kind 1111, the URL in the I tag), so any client can read and write the same threads. Other tools already use this format but turn a URL into an address differently. If you build one, let's agree on that rule. Chrome: https://chromewebstore.google.com/detail/nostrcomments/ebmgdpicceaencegknannfaljhbfgido Firefox: Source: #nostr #freespeech #foss
GM ☕ NostrComments has been live in the Chrome and Firefox stores for a few weeks now. The thing I see most often: People open the button on an article where the comments are already closed or deleted… and there’s already a thread waiting. That’s exactly why I built this. Small updates from the last few days: • The floating button is quieter by default (dims until you hover) • One-click disable per site • Remembers which corner you want it in, per website Still no server, no account, no tracking. Just comments the site owner can’t delete. If you haven’t tried it yet: Chrome → https://chromewebstore.google.com/detail/nostrcomments/ebmgdpicceaencegknannfaljhbfgido Firefox → Or read any thread without installing anything: Which page would you most like to give an uncensorable comment section? #nostr #asknostr
A few releases of NostrComments since last time: the floating button dims unless you hover it, can be dragged to a corner instead of only picked from a menu, and can now be turned off entirely in settings. With it off, the toolbar icon becomes the way in instead — and now shows how many replies you haven't seen yet, so that's still covered. github.com/briskness-byte/NostrComments
If your browser extension uses sender.tab to tell web pages apart from its own pages, check this. I got it wrong in a signer and it cost me a release. The background script refused privileged messages, like setting a PIN, whenever sender.tab was set. The reasoning: content scripts run in tabs, so a message with a tab came from a web page. But the extension's own options page has a tab too, as soon as it is opened in one. So the extension blocked itself. PIN setup didn't throw an error or show a warning. It just did nothing. The check that means what you intended is the sender's URL, not whether a tab exists: compare sender.url against browser.runtime.getURL(''). Your own pages pass, and anything a content script relays from a web page does not. The second half of the same fix: the content-script bridge now forwards only an explicit list of message types. Before, some handlers were out of a page's reach only by accident, and an accident is not a boundary.
If your browser extension draws its UI inside the page, check this one. I had it wrong for months. My comment panel lives in an open shadow root in the page, so any script on the page can reach every control in it. I guarded the ones that matter — granting consent, adding a relay — by checking the event's isTrusted, which only the browser can set. That felt like enough. It is not, and I only found out because I tried to break it myself instead of assuming. A page can skip the event entirely: take the element, call its onclick directly, and hand it an object it made up. isTrusted is just a property on that object. It can also act while a real click of yours is being delivered elsewhere in the panel, which is long enough for a naive "was that trusted" flag to still be true. Against my own build that meant a page could open settings, press "Show private key" and read the nsec straight out of the field. And separately, type a comment and post it under my key. Without me clicking anything. What works instead is to never trust what the caller passed. A capture listener on the shadow root records which element a real gesture is activating, in a closure the page cannot reach, and each sensitive handler asks only whether that element is itself. Dispatching an event sets nothing. Calling a handler sends no event at all. Piggybacking on a real click leaves some other element as the target. It is still a mitigation and not a boundary, and I would rather say so: the panel is in the page's DOM, so a page can read the thread, read what I am typing, and read a key I choose to display while I am on it. Moving those controls onto the extension's own surface is the actual fix, and that is the next thing I build. Fixed in 23.3.1 — out on Firefox, in review at Chrome.
↑