fix(extension): alert on real org detections instead of missing usage fields - #248
Merged
Merged
Conversation
… fields The worker read usage.threats/usage.warnings from /api/usage, which returns neither, so the count was always 0 and no notification ever fired. It now polls GET /api/orgs/:id/detections?status=new for the user's current org, shows the new-detection count and the newest detections in the popup and toolbar tooltip, and notifies for high/critical detections not seen in the previous poll (diffed by id, since detected_at can predate the upload). Clicking the notification opens /org/<slug>/detections. The toolbar badge stays with the per-tab page checks. The bundled icons were corrupt 1x1 PNGs; Chrome refuses a basic notification whose icon can't be decoded, so they are regenerated from the web app's 512px icon.
ThreatCrush Security Scan13 finding(s) HIGH/CRITICAL: 1 | MEDIUM: 6 | LOW: 6
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
usage.threats/usage.warningsfrom/api/usage, which returns neither, so the count was always 0 and no notification ever fired. It now pollsGET /api/orgs/:id/detections?status=new&limit=100for the signed-in user's current org (current_org_idfrom/api/auth/mewhen the user has several orgs, else the only / most recently joined org from/api/orgs), on the existingthreatcrush-event-checkalarm and whenever the popup's Account tab opens. NewlistOrganizations()/listDetections()insrc/lib/api.js(separate hunk; the top-up call site is untouched). Logic lives in the newsrc/background/detections.js.notificationsEnabled). One notification per org (idthreatcrush-detections:<slug>), replaced by the next one; clicking opens<app>/org/<slug>/detections. The first poll after sign-in or an org switch only records a baseline, so installing the extension doesn't replay old alerts. Alarm and popup polls are single-flighted so one detection can't notify twice./usagewith no org). Signed in with no org shows "No organization". An API failure keeps the last known numbers and shows "Could not reach ThreatCrush."ThreatCrush: N new detections in <org>). Why: feat(extension): local security checks for the active page #240 sets per-tab badges and falls back to the global badge while a page loads; putting the account count in the global badge would make the same slot mean "page problems" on one tab and "server detections" on another. The old globalupdateBadge()and the unusedCHECK_NOWmessage are removed.apps/extension/public/icons/*.pngwere 1×1 PNGs with a bad IDAT CRC. Chrome rejects a basic notification whose icon can't be decoded (Unable to download all specified images.), so notifications could not have been shown even with a non-zero count, and the toolbar icon was blank. Regenerated at 16/32/48/128 fromapps/web/public/icons/icon-512x512.png. The notificationiconUrlnow useschrome.runtime.getURL(a relative path resolved againstbackground/in the worker).onInstalledre-creates the alarm with the interval saved in Options instead of resetting it to 5 minutes on every update.How verified
NODE_ENV=test pnpm --filter @profullstack/threatcrush-extension test: 5 files, 63 tests pass, including the new__tests__/detection-alerts.test.js(baseline without notifying, id diffing across polls, severity filter, notifications toggle, org switch re-baseline, signed-out no-op with no console output, no-org no-op, API error keeps state and doesn't notify, concurrent polls notify once, notification click URL). (My shell exportsNODE_ENV=production, under which the pre-existingoptions-app.test.jsxfails withReact.act is not a function; unrelated to this change.)pnpm --filter @profullstack/threatcrush-extension build: Chrome, Firefox and Safari builds complete.next dev -p 3447(NEXT_PUBLIC_APP_URL=http://localhost:3447; for this run only I addedhttp://localhost:3447/*andhttp://127.0.0.1:54321/*tohost_permissionsin the dist copy, since the committed manifest only listslocalhost:3000). Loaded it in headless Chromium 1243 with--load-extension, throwaway user + org + server, detections inserted via SQL. Observed:ThreatCrush, badge empty, no notification, no console errors/warnings.detected_at3 h in the past plus a medium one, fired the alarm: exactly onechrome.notifications.create("threatcrush-detections:ea-ext-org", {title: "Critical detection in EA Ext Org", message: "New critical: SSH brute force from 203.0.113.9"})(wrapped in the service worker to record calls);chrome.notifications.getAll()listed it as shown; tooltipThreatCrush: 4 new detections in EA Ext Org; global badge still empty. A second alarm with unchanged data notified nothing. Reopened popup: 4 / 2, four detections listed; View all openedhttp://localhost:3447/org/ea-ext-org/detections.ThreatCrush, stored state cleared.ThreatCrush, badge empty, no console errors/warnings.PAGE_CHECKSon alocalhost:3447tab set that tab's badge to1(one warning) while the global badge stayed empty.Notification failed: Unable to download all specified images.andgetAll()was empty.Blocked on the owner
Decisions
since=<last check>.sincefilters ondetected_at, which the daemon sets and which can predate the upload (spooled events are replayed later, per the cloud contract). A time window would drop those; the smoke run above shows a 3-hour-olddetected_atstill notifying. The worker keeps the ids from the last page (≤100) inchrome.storage.local.N+when there are more new detections than that./api/usagetoday_requests(billed API requests), not security events. Easy to restore from git if wanted.