residoo 0.8.4 → 0.8.6
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 +1 -1
- package/package.json +1 -1
- package/src/patterns.js +74 -2
- package/src/rotation.js +55 -0
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
|
|
100
|
+
- Scans your local AI-agent session transcripts for 59 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.
|
|
3
|
+
"version": "0.8.6",
|
|
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
|
@@ -20,8 +20,17 @@ const PATTERNS = [
|
|
|
20
20
|
re: /\bASIA[0-9A-Z]{16}\b/g },
|
|
21
21
|
{ id: "private_key_block", label: "Private key block", confidence: "high",
|
|
22
22
|
re: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/g },
|
|
23
|
+
// Widened twice from the original gh[pousr]_[A-Za-z0-9]{36,255}, both
|
|
24
|
+
// confirmed via GitHub's own docs (docs.github.com, authentication
|
|
25
|
+
// overview): (1) fine-grained PATs use an entirely disjoint literal
|
|
26
|
+
// prefix, github_pat_, not gh[pousr]_ at all -- the original regex
|
|
27
|
+
// could never match one; (2) GitHub's own 2026-04-24 changelog post
|
|
28
|
+
// shows App installation tokens (ghs_) rolling out to a new
|
|
29
|
+
// ghs_<appid>_<3-segment-JWT> shape, whose dots fell outside the old
|
|
30
|
+
// [A-Za-z0-9] body class. The distinctive prefix carries the FP
|
|
31
|
+
// protection, so widening the body to include . _ - is safe.
|
|
23
32
|
{ id: "github_pat", label: "GitHub personal access token", confidence: "high",
|
|
24
|
-
re: /\
|
|
33
|
+
re: /\b(?:gh[pousr]_|github_pat_)[A-Za-z0-9_.-]{20,600}\b/g },
|
|
25
34
|
{ id: "gitlab_pat", label: "GitLab personal access token", confidence: "high",
|
|
26
35
|
re: /\bglpat-[A-Za-z0-9_-]{20,100}\b/g },
|
|
27
36
|
{ id: "slack_token", label: "Slack token", confidence: "high",
|
|
@@ -58,6 +67,34 @@ const PATTERNS = [
|
|
|
58
67
|
// unlike a short/generic prefix where that same generosity would matter.
|
|
59
68
|
{ id: "stripe_webhook_secret", label: "Stripe webhook signing secret", confidence: "high",
|
|
60
69
|
re: /\bwhsec_[A-Za-z0-9]{24,64}\b/g },
|
|
70
|
+
// Azure AD (Entra ID) client secret. Found missing by cross-checking
|
|
71
|
+
// gitleaks' own open-issue tracker (gitleaks/gitleaks#1687), which
|
|
72
|
+
// asked for Azure coverage generally -- gitleaks itself already has a
|
|
73
|
+
// rule (id "azure-ad-client-secret" in its own gitleaks.toml), so this
|
|
74
|
+
// is adapted directly from that battle-tested pattern rather than
|
|
75
|
+
// designed from scratch: 2-4 chars, one digit, the literal "Q~"
|
|
76
|
+
// marker, then 28-36 more chars. No capture group (unlike gitleaks'
|
|
77
|
+
// Go regex), to match every other rule in this file using the whole
|
|
78
|
+
// match as the value; zero-width lookaround used instead of gitleaks'
|
|
79
|
+
// literal delimiter character classes for the same reason -- the
|
|
80
|
+
// charset includes non-word characters (~ .) that a plain \b boundary
|
|
81
|
+
// can't reliably bound. Azure Storage Account keys were investigated
|
|
82
|
+
// and NOT added: they're a bare, unprefixed base64 blob (~88 chars,
|
|
83
|
+
// confirmed via learn.microsoft.com), the same unsafe generic shape
|
|
84
|
+
// already excluded for Weights & Biases' classic key format.
|
|
85
|
+
{ id: "azure_ad_client_secret", label: "Azure AD (Entra ID) client secret", confidence: "high",
|
|
86
|
+
re: /(?<![A-Za-z0-9_.~-])[A-Za-z0-9_.~]{2,4}\dQ~[A-Za-z0-9_.~-]{28,36}(?![A-Za-z0-9_.~-])/g },
|
|
87
|
+
// Tailscale auth key. Found missing via gitleaks/gitleaks#1778 (still
|
|
88
|
+
// open there too). No fully authoritative current spec found: Tailscale's
|
|
89
|
+
// own kb/1085/auth-keys page shows an older bare "tskey-<hex>" example,
|
|
90
|
+
// while more recent third-party usage consistently shows a newer
|
|
91
|
+
// "tskey-auth-<id>-<secret>" two-segment form -- genuine format
|
|
92
|
+
// evolution, not a single confirmed shape. Covers both on the strength
|
|
93
|
+
// of the "tskey-" prefix alone, which carries negligible false-positive
|
|
94
|
+
// risk regardless of which era's exact body shape is present, same
|
|
95
|
+
// reasoning as whsec_ above.
|
|
96
|
+
{ id: "tailscale_auth_key", label: "Tailscale auth key", confidence: "high",
|
|
97
|
+
re: /\btskey-(?:auth-)?[A-Za-z0-9-]{15,80}\b/g },
|
|
61
98
|
// The negative lookahead keeps this rule mutually exclusive with anthropic_key
|
|
62
99
|
// and openrouter_key below — without it, "sk-ant-..." or "sk-or-v1-..." match
|
|
63
100
|
// BOTH this pattern and the more specific one, and get reported twice under
|
|
@@ -135,8 +172,24 @@ const PATTERNS = [
|
|
|
135
172
|
// ── Cloud / infra ──────────────────────────────────────────────────────
|
|
136
173
|
{ id: "digitalocean_token", label: "DigitalOcean access token", confidence: "high",
|
|
137
174
|
re: /\b(?:dop|doo|dor)_v1_[a-f0-9]{64}\b/g },
|
|
175
|
+
// The optional v0_ infix is NOT confirmed by Supabase's own docs -- found
|
|
176
|
+
// via a gitleaks feature request (gitleaks/gitleaks#2225) whose author
|
|
177
|
+
// cites real tokens seen in the wild, and cross-checked that trufflehog's
|
|
178
|
+
// own supabase detector has the identical blind spot for the same
|
|
179
|
+
// reason. Same honesty tier as tailscale_auth_key: shipped despite
|
|
180
|
+
// imperfect vendor documentation because the addition is a narrow,
|
|
181
|
+
// low-risk optional segment, not a guessed body shape.
|
|
138
182
|
{ id: "supabase_token", label: "Supabase personal access token", confidence: "high",
|
|
139
|
-
re: /\bsbp_[a-z0-9]{40}\b/g },
|
|
183
|
+
re: /\bsbp_(?:v0_)?[a-z0-9]{40}\b/g },
|
|
184
|
+
// Supabase's newer "secret key" replaces the JWT-based service_role key
|
|
185
|
+
// and, unlike it, bypasses Row Level Security -- full database/storage/
|
|
186
|
+
// auth access. Confirmed via supabase.com/docs/guides/api/api-keys,
|
|
187
|
+
// which names sb_secret_ explicitly ("not JWTs") but does not publish an
|
|
188
|
+
// exact suffix length, hence the generous floor/ceiling bound already
|
|
189
|
+
// used elsewhere in this file (cerebras_key, render_key) for the same
|
|
190
|
+
// situation.
|
|
191
|
+
{ id: "supabase_secret_key", label: "Supabase secret API key", confidence: "high",
|
|
192
|
+
re: /\bsb_secret_[A-Za-z0-9_-]{20,200}\b/g },
|
|
140
193
|
// Confirmed via planetscale.com/docs/api/reference/service-tokens: the
|
|
141
194
|
// secret half of a service token pair. The id half (12 lowercase
|
|
142
195
|
// alphanumeric characters, no prefix) is not a rule on its own for the
|
|
@@ -284,6 +337,25 @@ const PATTERNS = [
|
|
|
284
337
|
// than a doc-confirmed exact count.
|
|
285
338
|
{ id: "posthog_key", label: "PostHog personal API key", confidence: "high",
|
|
286
339
|
re: /\bphx_[A-Za-z0-9]{40,}\b/g },
|
|
340
|
+
// Claude Code Remote Control session URL -- not a vendor API key, a URL
|
|
341
|
+
// that IS a bearer credential: opening it in a browser grants full
|
|
342
|
+
// read/write/execute access to a live local Claude Code session, no
|
|
343
|
+
// further auth. Anthropic's own docs (code.claude.com/docs/en/remote-control,
|
|
344
|
+
// fetched 2026-09-04) confirm this URL is printed directly into the
|
|
345
|
+
// conversation ("Claude Code also posts the session URL in the
|
|
346
|
+
// conversation") -- i.e. this genuinely lands in the exact transcripts
|
|
347
|
+
// this project scans, not a hypothetical risk. Found via a gitleaks
|
|
348
|
+
// open-issue request (gitleaks/gitleaks#2094) that proposed a
|
|
349
|
+
// `session_<id>` prefix as "illustrative," unconfirmed. That guess was
|
|
350
|
+
// checked against this project's own installed `claude` binary (macOS,
|
|
351
|
+
// `strings /usr/local/bin/claude`) rather than assumed correct: the
|
|
352
|
+
// literal web-URL template is `` `/code/${sessionId}` `` with NO prefix
|
|
353
|
+
// at all, and `sessionId:mqH.randomUUID()` confirms the ID is a
|
|
354
|
+
// standard UUID v4 -- both directly present in the shipped binary's own
|
|
355
|
+
// strings, not inferred. The gitleaks issue's proposed pattern would
|
|
356
|
+
// have MISSED every real instance of this URL.
|
|
357
|
+
{ id: "claude_code_remote_control_url", label: "Claude Code Remote Control session URL", confidence: "high",
|
|
358
|
+
re: /\bclaude\.ai\/code\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/g },
|
|
287
359
|
// LangSmith personal access token (lsv2_pt_) / service key (lsv2_sk_).
|
|
288
360
|
// Found missing by cross-checking agentsweep's own open-issue tracker.
|
|
289
361
|
// The first segment (32 hex, UUID-shaped) is consistent across every
|
package/src/rotation.js
CHANGED
|
@@ -216,6 +216,32 @@ const ROTATION_GUIDANCE = {
|
|
|
216
216
|
],
|
|
217
217
|
revokeNote: "A leaked webhook secret alone can't drain funds or read data -- it only lets an attacker forge fake Stripe-Signature headers to a webhook endpoint that trusts them, so this is a spoofing/logic-bypass risk, not an account-access one. Still worth rolling promptly: it's what stands between a webhook handler and forged events.",
|
|
218
218
|
},
|
|
219
|
+
// Fetched learn.microsoft.com (2026-09-04), Azure App Registration
|
|
220
|
+
// secret management docs: steps below are the documented
|
|
221
|
+
// create-update-verify-delete rotation flow, not guessed.
|
|
222
|
+
azure_ad_client_secret: {
|
|
223
|
+
label: "Azure AD (Entra ID) client secret",
|
|
224
|
+
consolePath: "Microsoft Entra ID > App registrations > [app] > Certificates & secrets",
|
|
225
|
+
steps: [
|
|
226
|
+
"Create a new client secret on the same app registration first (New client secret)",
|
|
227
|
+
"Update whatever used the old one with the new value, and verify it works",
|
|
228
|
+
"Only then delete the leaked secret (trash icon next to it), to minimize downtime",
|
|
229
|
+
],
|
|
230
|
+
revokeNote: "Deletion is immediate. Prefer create-then-delete over delete-then-create if the app can tolerate two live secrets briefly -- it avoids an outage window for whatever depends on this secret.",
|
|
231
|
+
},
|
|
232
|
+
// Fetched tailscale.com/kb/1085/auth-keys (2026-09-04): exact console
|
|
233
|
+
// path and the important revoke-vs-deauthorize distinction are quoted
|
|
234
|
+
// from that page, not inferred.
|
|
235
|
+
tailscale_auth_key: {
|
|
236
|
+
label: "Tailscale auth key",
|
|
237
|
+
consolePath: "console.tailscale.com/admin/settings/keys",
|
|
238
|
+
steps: [
|
|
239
|
+
"Open the Keys page of the admin console",
|
|
240
|
+
"Find the key in the table and select Revoke",
|
|
241
|
+
"If a node already used this key to join your tailnet, also delete that node from the Machines page -- revoking the key alone does not deauthorize nodes already using it",
|
|
242
|
+
],
|
|
243
|
+
revokeNote: "Revoking is immediate for future use of the key, but any node it already authorized stays connected until separately removed from Machines -- the two are not the same action.",
|
|
244
|
+
},
|
|
219
245
|
// help.openai.com articles 5112595 and 8304786 exist (surfaced by search)
|
|
220
246
|
// but the help center serves HTTP 403 to this project's fetcher, so no URL
|
|
221
247
|
// is shipped: unverifiable end to end fails the bar above.
|
|
@@ -491,6 +517,20 @@ const ROTATION_GUIDANCE = {
|
|
|
491
517
|
],
|
|
492
518
|
revokeNote: "This is the account-level token (sbp_); a project's anon and service_role keys rotate separately in that project's API settings.",
|
|
493
519
|
},
|
|
520
|
+
// supabase.com/docs/guides/api/api-keys (fetched 2026-09-04): sb_secret_
|
|
521
|
+
// is the newer replacement for the JWT-based service_role key, and
|
|
522
|
+
// bypasses Row Level Security the same way that key did.
|
|
523
|
+
supabase_secret_key: {
|
|
524
|
+
label: "Supabase secret API key",
|
|
525
|
+
consolePath: "supabase.com/dashboard > Project > Project Settings > API Keys",
|
|
526
|
+
steps: [
|
|
527
|
+
"Open the project's API Keys page",
|
|
528
|
+
"Revoke the leaked secret key",
|
|
529
|
+
"Generate a replacement and update whatever used the old one",
|
|
530
|
+
"Review recent database/storage/auth activity for anything unexpected while the key was live",
|
|
531
|
+
],
|
|
532
|
+
revokeNote: "This key bypasses Row Level Security -- treat a leak as full database access, not a scoped credential.",
|
|
533
|
+
},
|
|
494
534
|
// Fetched https://planetscale.com/docs/api/reference/service-tokens
|
|
495
535
|
// (2026-09-03): tokens are managed and revoked from the organization's
|
|
496
536
|
// Service tokens page in the PlanetScale dashboard.
|
|
@@ -785,6 +825,21 @@ const ROTATION_GUIDANCE = {
|
|
|
785
825
|
],
|
|
786
826
|
revokeNote: "Deletion is immediate; the key stops authenticating on the next request.",
|
|
787
827
|
},
|
|
828
|
+
// Not a vendor API key with a console to rotate it in -- a session URL
|
|
829
|
+
// that IS the credential. Steps below per code.claude.com/docs/en/
|
|
830
|
+
// remote-control (fetched 2026-09-04): disconnect terminates the URL's
|
|
831
|
+
// access immediately; there is no separate "revoke" step to perform
|
|
832
|
+
// afterward the way there is for a leaked API key.
|
|
833
|
+
claude_code_remote_control_url: {
|
|
834
|
+
label: "Claude Code Remote Control session URL",
|
|
835
|
+
consolePath: "the terminal running the session, or claude.ai/code's session list",
|
|
836
|
+
steps: [
|
|
837
|
+
"In the terminal running the session, run /remote-control again to disconnect (or use the status panel's disconnect option)",
|
|
838
|
+
"If you no longer have terminal access, end the local session entirely -- Remote Control access ends with it",
|
|
839
|
+
"Start a fresh Remote Control session if you still need one; it gets a new, unrelated URL",
|
|
840
|
+
],
|
|
841
|
+
revokeNote: "Disconnecting invalidates the URL immediately -- your local session keeps running in the terminal either way, only the remote-access link is torn down. There is no separate token to also revoke at a vendor console.",
|
|
842
|
+
},
|
|
788
843
|
// Fetched docs.langchain.com/langsmith/create-account-api-key
|
|
789
844
|
// (2026-09-04): both personal access tokens and service keys are
|
|
790
845
|
// created and managed from the workspace's own API Keys settings page.
|