Privacy & Security
For whoever signs off on adding quibble to an app: where the data goes, what a submitter can cause, and what there is to review.
Where the data goes
From the browser to your application, and from your application to your issue tracker. That's the whole path. quibble is a library inside your app. There's no quibble service, and nothing is sent to us or to anyone else: no telemetry, no call home, no CDN.
Hosted feedback tools receive your users' screenshots, console logs and URLs, which makes them a data processor: a DPA, a subprocessor entry and a vendor review. quibble receives nothing, so none of that is added. Your data lives wherever your tracker does. With a self-hosted Gitea on your own hardware, it never leaves that hardware.
- Their browserA user spots a problem and clicks quibble
- Your appquibble adds the page, the error and who sent it
- Your to-do list GitHub, Jira, Linear…It arrives as an issue, ready to fix
Nothing passes through quibble. There’s no quibble server to pass through.
What a submitter can and can't cause
People who file are trusted but not privileged: signed in through your identity provider, holding no credential of their own.
They can create an issue with their text; tag it with labels that already exist; set a priority, which is held to P1–P3; attach a screenshot they chose to take; and send page context.
They can't create a label, send a note to a repository you didn't configure, close, comment on or edit anything, go past the rate limit (when one is set and a sign-in header is present), or overwrite a signed-in identity with a typed one.
The exact token permissions quibble needs, tracker by tracker, are in its operator documentation, which early-access teams receive.
Input is capped before it reaches your tracker: context values at 500 characters, 30 fields, screenshots at 2 MB and checked to be real PNGs.
The endpoint must sit behind sign-in. It creates issues. It isn't a public form. Put it behind Cloudflare Access, your app's own sign-in or any authenticating proxy. quibble reads identity from a header it's told to trust; it doesn't sign anyone in itself.
Identity
The reporter's name comes from a trusted header set by your sign-in: Cloudflare Access by default, or any header you name, so SAML, OIDC, oauth2-proxy and mTLS front ends all work. With no proxy, quibble can ask for a name or email instead.
A trusted header always wins. A typed name is used only when no header is present, and the issue marks it self-declared. That marking is the entire guarantee: a typed identity is never verified.
Behind your sign-in- Reported by: [email protected] (via quibble)
Typed in, no sign-in- Reported by: [email protected] (self-declared, via quibble)
Masking
Mark any part of a page data-quibble-mask and its text is reported as
(masked) and never sent. Screenshots honour it too: marked regions are painted
out with a solid fill before the image leaves the browser. A solid fill, not a blur,
because a blur can be reversed.
If someone shares a different tab or screen when taking the screenshot, the masked regions wouldn't line up, so quibble refuses the screenshot rather than redact the wrong thing, and says why.
Query strings are removed from the URLs in stack traces, console output and failed-request records, because they carry tokens and session IDs far more often than anything useful.
Errors and environment details are on by default. Console output and failed network requests are off until you turn them on, because they name your own internal endpoints.
data-quibble-mask: the issue says what was pointed at, and (masked) instead of the card number. Recorded on the live demo.Supply chain
Installing quibble pulls in nothing: the core is pure Python standard library, and the widget is dependency-free JavaScript with no build step. The web-framework adapters are optional extras you choose.
Trackers are supported in the package itself, not through third-party plugins, so there's no ecosystem of adapters to review. For a supply-chain review, that's the whole surface: one package, no transitive dependencies, and a check that fails the build if that ever changes. This website runs the same check against the version its demo uses.
Limits we won't overstate
- Rate limiting is per process. Several workers mean several limits. It guards against a runaway retry loop, not a determined attacker.
- Without a sign-in header, every submitter shares one limit. The limiter never keys on a typed name, because that would be trivial to change.
- Self-declared identity isn't verified. It's marked as such in the issue.
- On GitHub, screenshots need write access to repository contents, which covers the whole repository; quibble's code, not the token, keeps it to its own branch. If that's not acceptable, switch screenshots off with one setting, or keep them on your own server so the tracker gets only a link.
- quibble doesn't authenticate anyone. It trusts a header. If anything other than your proxy can set that header, attribution means nothing.
- A page can send anything it declares. Fields your app adds to the context are sent as your app provides them.
Licence
quibble is free for individuals and for companies with fewer than 100 people and under $1M in revenue, under the PolyForm Small Business licence. Larger companies, email us. Pricing.
Nothing in quibble checks the licence. There's no licence server and no call home, so a licence never adds a network path to review.
This website
No cookies. Cloudflare, which already hosts the site, counts visits with its Web Analytics: no cookies, no fingerprinting, no tracking across sites. We also keep a simple record of each visit: which home-page headline you saw, which pages you went through, and whether you emailed us, went to GitHub or tried the demo. A random id ties those steps together. It's kept in this tab only and is gone when you close it. We store your country, as Cloudflare reports it, and not your IP address. So that scanners and crawlers don't count as people, we also note whether a page was actually looked at (five seconds on screen, or a scroll, click or key press) and whether the browser says it's automated. We keep that yes-or-no, never the browser's own description of itself. The only other thing kept on your device is your light or dark choice, in local storage, and only if you use the switch. Fonts are served from this site. When you email from a page, the subject line says which version of the page you saw.
The live demo runs Python (Pyodide) in your browser, served from this site along with everything else. Nothing you type into it is sent anywhere. The demo's tracker is an in-memory stand-in. Third-party code it uses is listed, with licences, in /vendor/LICENSES.txt, along with quibble's own.
Found a security problem in quibble? Write to hello [at] quibble [dot] fyi rather than raising it in public.