residoo 0.8.7 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -97,7 +97,7 @@ while losing rows, then fixed in public against the classes it was losing
97
97
 
98
98
  ## What it does
99
99
 
100
- - Scans your local AI-agent session transcripts for 67 high-confidence
100
+ - Scans your local AI-agent session transcripts for 79 high-confidence
101
101
  secret patterns: cloud provider keys, private key blocks, OAuth/API
102
102
  tokens, database connection strings, and more. See
103
103
  [`src/patterns.js`](src/patterns.js).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "residoo",
3
- "version": "0.8.7",
3
+ "version": "0.8.8",
4
4
  "description": "Find secrets leaking through your AI coding agent's session history. Zero network calls in the scan path, zero dependencies.",
5
5
  "license": "MIT",
6
6
  "author": "CloudRoam (https://cloudroam.io)",
package/src/patterns.js CHANGED
@@ -228,6 +228,50 @@ const PATTERNS = [
228
228
  // collide with any of them.
229
229
  { id: "elevenlabs_key", label: "ElevenLabs API key", confidence: "high",
230
230
  re: /\bsk_[a-f0-9]{48}\b/g },
231
+ // Third batch from the 2026-09-04 competitor research pass. NVIDIA's own
232
+ // docs (docs.nvidia.com) confirm the nvapi- prefix ("Keys typically start
233
+ // with nvapi-") without stating an exact length.
234
+ { id: "nvidia_api_key", label: "NVIDIA API key", confidence: "high",
235
+ re: /\bnvapi-[A-Za-z0-9_-]{40,200}\b/g },
236
+ // Jina AI: prefix confirmed via Jina's own GitHub org/SDKs and broad
237
+ // ecosystem documentation; exact 60-char length taken from noseyparker's
238
+ // own shipped rule, not independently pinned by a Jina spec page.
239
+ { id: "jina_key", label: "Jina AI API key", confidence: "high",
240
+ re: /\bjina_[A-Za-z0-9]{60}\b/g },
241
+ // Tavily: tvly- prefix confirmed via Tavily's own official SDK repos
242
+ // (tavily-python, tavily-js); exact 32-char length not independently
243
+ // pinned by a dedicated format spec page.
244
+ { id: "tavily_key", label: "Tavily API key", confidence: "high",
245
+ re: /\btvly-[A-Za-z0-9]{32}\b/g },
246
+ // Firecrawl: fc- prefix appears in Firecrawl's own docs and SDKs, but
247
+ // only as illustrative placeholders -- no page independently confirms
248
+ // the exact 32-lowercase-hex body. Shipped anyway on the combination of
249
+ // the prefix plus a strict hex-only body requirement right after it.
250
+ { id: "firecrawl_key", label: "Firecrawl API key", confidence: "high",
251
+ re: /\bfc-[a-f0-9]{32}\b/g },
252
+ // Databricks PAT: Databricks' own docs deliberately show only placeholder
253
+ // tokens, no real format. Corroborated by two independent secondary
254
+ // sources instead -- Microsoft Purview's own Sensitive-Information-Type
255
+ // definition for Azure Databricks PATs, and TruffleHog's shipped OSS
256
+ // detector -- both agreeing on dapi + 32 lowercase hex, optionally a
257
+ // trailing -<digits>. Not Databricks-primary-sourced, so flagged medium
258
+ // rather than high like the rest of this file. The strict lowercase-hex
259
+ // body avoids the one real collision risk found during research: Binance
260
+ // also uses a "dapi" naming convention for its COIN-margined futures API
261
+ // (e.g. dapiDataGetTopLongShortPositionRatio), but that never matches
262
+ // since it isn't hex.
263
+ { id: "databricks_pat", label: "Databricks personal access token", confidence: "medium",
264
+ re: /\bdapi[a-f0-9]{32}(?:-[0-9]+)?\b/g },
265
+ // Sourcegraph: sgp_ prefix confirmed via Sourcegraph's own docs ("Access
266
+ // tokens now begin with the prefix sgp_"); exact body shape (an optional
267
+ // 16-hex instance-id infix, or a local_ marker, before the 40-hex body)
268
+ // taken from noseyparker's worked examples, not independently pinned.
269
+ // NOTE for future additions: Segment's own "Public API Token" also uses
270
+ // an sgp_ prefix (sgp_[a-zA-Z0-9]{64}) -- not added here, but if it ever
271
+ // is, the two rules are already mutually exclusive (hex-only 40 vs.
272
+ // mixed-case 64), just worth testing explicitly at that point.
273
+ { id: "sourcegraph_token", label: "Sourcegraph access token", confidence: "high",
274
+ re: /\bsgp_(?:[a-fA-F0-9]{16}_|local_)?[a-fA-F0-9]{40}\b/g },
231
275
 
232
276
  // ── Cloud / infra ──────────────────────────────────────────────────────
233
277
  { id: "digitalocean_token", label: "DigitalOcean access token", confidence: "high",
@@ -452,6 +496,49 @@ const PATTERNS = [
452
496
  // random-looking segment.
453
497
  { id: "resend_key", label: "Resend API key", confidence: "high",
454
498
  re: /\bre_[A-Za-z0-9]{6,12}_[A-Za-z0-9]{18,32}\b/g },
499
+ // Shopify Admin API access token: shpat_/shppa_ prefixes confirmed via
500
+ // Shopify's own current developer docs. Exact body length not stated on
501
+ // that page (a since-404'd Shopify changelog described it, quoted only
502
+ // by secondary sources), hence a generous floor/ceiling bound. Legacy
503
+ // shpca_/shpss_/shpua_ prefixes are real (Shopify community forum) but
504
+ // not on the current primary page, so left out here.
505
+ { id: "shopify_admin_token", label: "Shopify Admin API access token", confidence: "high",
506
+ re: /\bshp(?:at|pa)_[A-Za-z0-9]{32,40}\b/g },
507
+ // HubSpot private app token: HubSpot's own docs show only a masked
508
+ // example (pat-**-***...), corroborated by real (redacted) examples on
509
+ // HubSpot's own community forum showing the pat-<region>-<UUID-shaped
510
+ // body> structure. Medium confidence: the shape is real but the exact
511
+ // per-segment lengths are inferred, not vendor-pinned.
512
+ { id: "hubspot_token", label: "HubSpot private app access token", confidence: "medium",
513
+ re: /\bpat-[a-z]{2}\d-[a-f0-9-]{30,60}\b/gi },
514
+ // Grafana service account token: exact shape read directly off Grafana's
515
+ // own docs example token (grafana.com/docs/grafana/latest/administration/service-accounts/),
516
+ // not inferred -- two independently-random underscore-delimited segments
517
+ // behind a distinctive 5-char prefix.
518
+ { id: "grafana_service_account_token", label: "Grafana service account token", confidence: "high",
519
+ re: /\bglsa_[A-Za-z0-9]{32}_[A-Fa-f0-9]{8}\b/g },
520
+ // New Relic: NRAK- prefix confirmed via New Relic's own migration-notice
521
+ // doc ("If your API key starts with NRAK, no update is required").
522
+ // Exact body length/charset not published; generously bounded.
523
+ { id: "new_relic_api_key", label: "New Relic API key", confidence: "high",
524
+ re: /\bNRAK-[A-Z0-9]{27,64}\b/g },
525
+ // Mailchimp: 32 lowercase hex + a literal -us<datacenter digits> suffix,
526
+ // read directly off a live example in Mailchimp's own docs. The suffix
527
+ // is what makes this safe as a default rule -- a bare 32-hex string
528
+ // alone would be indistinguishable from countless unrelated hashes, but
529
+ // the specific "-usN" tail is Mailchimp-specific.
530
+ { id: "mailchimp_key", label: "Mailchimp API key", confidence: "high",
531
+ re: /\b[0-9a-f]{32}-us[0-9]{1,2}\b/g },
532
+ // Akamai EdgeGrid access_token / client_token: akab- prefix and the
533
+ // hyphen-separated two-segment shape confirmed via Akamai's own current
534
+ // docs (literal examples shown), independently corroborated by a
535
+ // detect-secrets maintainer's own reproduction. Neither source states
536
+ // hard segment-length bounds, so the ranges here are a reasonable
537
+ // envelope, not vendor-pinned. Akamai's client_secret was investigated
538
+ // and NOT added: no distinctive prefix in Akamai's own examples, the
539
+ // same bare/opaque shape already excluded elsewhere in this file.
540
+ { id: "akamai_edgegrid_token", label: "Akamai EdgeGrid token", confidence: "high",
541
+ re: /\bakab-[a-z0-9]{16,32}-[a-z0-9]{6,32}\b/g },
455
542
  ];
456
543
 
457
544
  /**
package/src/rotation.js CHANGED
@@ -572,6 +572,71 @@ const ROTATION_GUIDANCE = {
572
572
  ],
573
573
  revokeNote: "A key grants full account access (voices, generations, billing); deletion is immediate.",
574
574
  },
575
+ // docs.nvidia.com's own key-management pages point at build.nvidia.com
576
+ // for personal keys; login-walled, hence the path in words.
577
+ nvidia_api_key: {
578
+ label: "NVIDIA API key",
579
+ consolePath: "build.nvidia.com > your profile > API Keys",
580
+ steps: [
581
+ "Open API Keys under your NVIDIA Build profile",
582
+ "Delete the leaked key",
583
+ "Generate a replacement and update whatever used the old one",
584
+ ],
585
+ revokeNote: "Deletion is immediate; anything still using the old key starts failing authentication at once.",
586
+ },
587
+ jina_key: {
588
+ label: "Jina AI API key",
589
+ consolePath: "jina.ai > API keys (jina.ai/api-dashboard/key-manager)",
590
+ steps: [
591
+ "Open the API key manager",
592
+ "Delete the leaked key",
593
+ "Create a replacement and update whatever used the old one",
594
+ ],
595
+ revokeNote: "Deletion is immediate; anything still using the old key starts failing authentication at once.",
596
+ },
597
+ tavily_key: {
598
+ label: "Tavily API key",
599
+ consolePath: "app.tavily.com > API Keys",
600
+ steps: [
601
+ "Open API Keys in the Tavily dashboard",
602
+ "Delete the leaked key",
603
+ "Create a replacement and update whatever used the old one",
604
+ ],
605
+ revokeNote: "Deletion is immediate; anything still using the old key starts failing authentication at once.",
606
+ },
607
+ firecrawl_key: {
608
+ label: "Firecrawl API key",
609
+ consolePath: "firecrawl.dev dashboard > API Keys",
610
+ steps: [
611
+ "Open API Keys in the Firecrawl dashboard",
612
+ "Delete the leaked key",
613
+ "Create a replacement and update whatever used the old one",
614
+ ],
615
+ revokeNote: "Deletion is immediate; anything still using the old key starts failing authentication at once.",
616
+ },
617
+ // Format is not Databricks-primary-sourced (see the comment in
618
+ // src/patterns.js), but the rotation location itself is confirmed
619
+ // directly from Databricks' own docs (docs.databricks.com/aws/en/dev-tools/auth/pat).
620
+ databricks_pat: {
621
+ label: "Databricks personal access token",
622
+ consolePath: "Databricks workspace > User Settings > Developer > Access tokens",
623
+ steps: [
624
+ "Open Access tokens under Developer settings in the workspace",
625
+ "Revoke the leaked token",
626
+ "Create a replacement with the shortest lifetime that works for your use case",
627
+ ],
628
+ revokeNote: "Revocation is immediate; anything still using the old token starts failing authentication at once.",
629
+ },
630
+ sourcegraph_token: {
631
+ label: "Sourcegraph access token",
632
+ rotateUrl: "https://sourcegraph.com/docs/cli/how-tos/creating_an_access_token",
633
+ steps: [
634
+ "Sourcegraph instance > user menu > Settings > Access tokens",
635
+ "Delete the leaked token",
636
+ "Create a replacement with the narrowest scopes it needs",
637
+ ],
638
+ revokeNote: "Deletion is immediate; anything still using the old token starts failing authentication at once.",
639
+ },
575
640
 
576
641
  // ── Cloud / infra ─────────────────────────────────────────────────────
577
642
  // docs.digitalocean.com/reference/api/create-personal-access-token/
@@ -963,6 +1028,71 @@ const ROTATION_GUIDANCE = {
963
1028
  ],
964
1029
  revokeNote: "Deletion is immediate; the key stops authenticating on the next request.",
965
1030
  },
1031
+ // shopify.dev/docs/apps/build/authentication-authorization/access-tokens
1032
+ shopify_admin_token: {
1033
+ label: "Shopify Admin API access token",
1034
+ rotateUrl: "https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens",
1035
+ steps: [
1036
+ "For a custom app: Shopify admin > Settings > Apps and sales channels > the app > uninstall/reinstall to reissue",
1037
+ "For a public/private app: revoke access from the Partner Dashboard and reinstall",
1038
+ "Update whatever used the old token",
1039
+ ],
1040
+ revokeNote: "This token can read/write store data (orders, customers, products) depending on its scopes -- review recent admin activity, not just API logs.",
1041
+ },
1042
+ hubspot_token: {
1043
+ label: "HubSpot private app access token",
1044
+ consolePath: "HubSpot account > Settings > Integrations > Private Apps",
1045
+ steps: [
1046
+ "Open Private Apps under Integrations",
1047
+ "Open the relevant app and rotate or delete its access token",
1048
+ "Update whatever used the old token",
1049
+ ],
1050
+ revokeNote: "Deletion/rotation is immediate; anything still using the old token starts failing authentication at once.",
1051
+ },
1052
+ // grafana.com/docs/grafana/latest/administration/service-accounts/
1053
+ grafana_service_account_token: {
1054
+ label: "Grafana service account token",
1055
+ rotateUrl: "https://grafana.com/docs/grafana/latest/administration/service-accounts/",
1056
+ steps: [
1057
+ "Administration > Users and access > Service accounts",
1058
+ "Open the relevant service account and delete the leaked token",
1059
+ "Add a replacement token and update whatever used the old one",
1060
+ ],
1061
+ revokeNote: "Deletion is immediate; anything still using the old token starts failing authentication at once.",
1062
+ },
1063
+ // docs.newrelic.com's own migration notice confirms the NRAK prefix;
1064
+ // key management itself is login-walled.
1065
+ new_relic_api_key: {
1066
+ label: "New Relic API key",
1067
+ consolePath: "one.newrelic.com > API keys (under your user menu)",
1068
+ steps: [
1069
+ "Open API keys",
1070
+ "Delete the leaked key",
1071
+ "Create a replacement and update whatever used the old one",
1072
+ ],
1073
+ revokeNote: "Deletion is immediate; anything still using the old key starts failing authentication at once.",
1074
+ },
1075
+ mailchimp_key: {
1076
+ label: "Mailchimp API key",
1077
+ consolePath: "Mailchimp account > Profile > Extras > API keys",
1078
+ steps: [
1079
+ "Open API keys under Extras in your account profile",
1080
+ "Delete the leaked key",
1081
+ "Create a replacement and update whatever used the old one",
1082
+ ],
1083
+ revokeNote: "Deletion is immediate; anything still using the old key starts failing authentication at once.",
1084
+ },
1085
+ // techdocs.akamai.com/developer/docs/authenticate-with-edgegrid
1086
+ akamai_edgegrid_token: {
1087
+ label: "Akamai EdgeGrid token",
1088
+ rotateUrl: "https://techdocs.akamai.com/developer/docs/authenticate-with-edgegrid",
1089
+ steps: [
1090
+ "Akamai Control Center > Identity & access management > API clients",
1091
+ "Open the relevant API client and deactivate/delete the leaked credential",
1092
+ "Create a replacement client credential and update whatever used the old one",
1093
+ ],
1094
+ revokeNote: "Deactivation is immediate; anything still using the old credential starts failing authentication at once.",
1095
+ },
966
1096
 
967
1097
  // ── NOISY_PATTERNS (only reachable via --include-noisy) ───────────────
968
1098
  generic_password_assignment: {