@trenchwork/erosolar 1.1.24 → 1.1.26
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 +46 -6
- package/SECURITY.md +195 -0
- package/dist/bin/deepseek.js +69 -3
- package/dist/bin/deepseek.js.map +1 -1
- package/dist/core/userApproval.d.ts +74 -0
- package/dist/core/userApproval.d.ts.map +1 -0
- package/dist/core/userApproval.js +194 -0
- package/dist/core/userApproval.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -39,17 +39,51 @@ erosolar
|
|
|
39
39
|
On first launch the CLI:
|
|
40
40
|
|
|
41
41
|
1. Pops a browser tab to `https://ero.solar/auth?port=…`. You sign in
|
|
42
|
-
(Erosolar Auth — Firebase Auth under the hood,
|
|
43
|
-
`erosolar-1b0db`).
|
|
42
|
+
with **Google SSO** (Erosolar Auth — Firebase Auth under the hood,
|
|
43
|
+
project `erosolar-1b0db`). SSO is enforced both at the web auth
|
|
44
|
+
page and at the Firestore-rule layer
|
|
45
|
+
(`request.auth.token.firebase.sign_in_provider == 'google.com'`).
|
|
44
46
|
2. Stores a Firebase ID token + refresh token at `~/.erosolar/auth.json`
|
|
45
47
|
(`0o600`). The refresh token is long-lived; the ID token is auto-
|
|
46
48
|
renewed before expiry.
|
|
47
|
-
3.
|
|
49
|
+
3. **Approval gate.** The CLI checks `approved_users/{your-email}` in
|
|
50
|
+
Firestore. The package ships offsec capabilities (Kali tools /
|
|
51
|
+
AFL++ / gdb / pwntools / Ghidra MCP), so only allowlisted emails
|
|
52
|
+
can launch. If your email isn't approved, the CLI writes a
|
|
53
|
+
pending request to `approval_requests/{uid}` for the operator to
|
|
54
|
+
review and exits with a clear message — re-run after the request
|
|
55
|
+
is approved.
|
|
56
|
+
4. Fetches the shared DeepSeek API key from Firestore at
|
|
48
57
|
`shared_secrets/deepseek` and writes it into `process.env.DEEPSEEK_API_KEY`
|
|
49
58
|
for the duration of the process. **Nothing lands on disk.** Reads
|
|
50
|
-
are gated by Firestore
|
|
51
|
-
writes are admin-only.
|
|
52
|
-
|
|
59
|
+
are gated by Firestore rules to authenticated *and approved*
|
|
60
|
+
users only; writes are admin-only.
|
|
61
|
+
5. Starts the interactive Ink-based shell.
|
|
62
|
+
|
|
63
|
+
### Requesting approval
|
|
64
|
+
|
|
65
|
+
Sign in once via Google SSO. The CLI will detect that your email
|
|
66
|
+
isn't on the allowlist and file a pending request at
|
|
67
|
+
`approval_requests/{uid}`. The operator reviews the queue and
|
|
68
|
+
adds your email via:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
node scripts/approve-user.mjs <your-email>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You can re-run `erosolar` once the operator confirms approval.
|
|
75
|
+
|
|
76
|
+
### Approval gate — admin operations
|
|
77
|
+
|
|
78
|
+
Adding a user (uses the Firebase CLI's stored OAuth token; bypasses
|
|
79
|
+
Firestore rules via owner privileges):
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
node scripts/approve-user.mjs alice@example.com
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Inspecting pending requests via Firebase Console:
|
|
86
|
+
[Firestore → `approval_requests`](https://console.firebase.google.com/project/erosolar-1b0db/firestore/data/~2Fapproval_requests)
|
|
53
87
|
|
|
54
88
|
### Bring-your-own key
|
|
55
89
|
|
|
@@ -397,6 +431,12 @@ that range will print an `npm deprecate` warning. Upgrade to ≥
|
|
|
397
431
|
|
|
398
432
|
## Security posture
|
|
399
433
|
|
|
434
|
+
> **Full threat model + controls live in [SECURITY.md](SECURITY.md).**
|
|
435
|
+
> The summary below is an index; SECURITY.md is the authoritative
|
|
436
|
+
> reference (SSO, allowlist, revocation, profile gating, audit log,
|
|
437
|
+
> threat model, residual risk).
|
|
438
|
+
|
|
439
|
+
|
|
400
440
|
- The CLI is dual-use offensive-security tooling. U.S. classification
|
|
401
441
|
is EAR-controlled (CCL [ECCN 4D004](https://www.federalregister.gov/documents/2021/10/21/2021-22774/information-security-controls-cybersecurity-items)),
|
|
402
442
|
not USML/ITAR. Domestic development and use is unrestricted; export
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Security model
|
|
2
|
+
|
|
3
|
+
`@trenchwork/erosolar` ships dual-use offsec capabilities (Kali
|
|
4
|
+
tooling, AFL++, gdb, pwntools, Ghidra MCP wiring). The package can
|
|
5
|
+
operate against authorized targets — e.g. a research engagement
|
|
6
|
+
with the operator's own infrastructure or an in-scope bug bounty —
|
|
7
|
+
and is potentially harmful if misused. This document describes the
|
|
8
|
+
controls in place, the threat model they address, and the disclosure
|
|
9
|
+
path for issues.
|
|
10
|
+
|
|
11
|
+
The motto is "show, don't tell": each control below corresponds to
|
|
12
|
+
a code path you can read, a Firestore rule you can deploy, or an
|
|
13
|
+
admin script you can run.
|
|
14
|
+
|
|
15
|
+
## Authentication
|
|
16
|
+
|
|
17
|
+
### Google SSO required
|
|
18
|
+
|
|
19
|
+
The CLI signs the user in via Firebase Auth at `https://ero.solar/auth`
|
|
20
|
+
which exposes Google as the only provider. SSO is enforced a second
|
|
21
|
+
time at the Firestore rule layer:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
request.auth.token.firebase.sign_in_provider == 'google.com'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A non-SSO token (anonymous, password, custom) cannot read
|
|
28
|
+
`approved_users/{email}`, `shared_secrets/{name}`, or write
|
|
29
|
+
`usage_logs/{uid}/sessions/{id}`. The gate fails closed: even if
|
|
30
|
+
the auth page were misconfigured, Firestore would deny the read.
|
|
31
|
+
|
|
32
|
+
### Token storage
|
|
33
|
+
|
|
34
|
+
`~/.erosolar/auth.json` (file `0o600`, parent dir `0o700`). Atomic
|
|
35
|
+
writes prevent half-written JSON from breaking subsequent loads.
|
|
36
|
+
The ID token is rotated automatically; the refresh token is
|
|
37
|
+
long-lived and revocable by the user at
|
|
38
|
+
[Google Account → Security → Connections to apps](https://myaccount.google.com/connections).
|
|
39
|
+
|
|
40
|
+
## Authorization — approved users only
|
|
41
|
+
|
|
42
|
+
The CLI is **not open-launch**. Every boot checks
|
|
43
|
+
`approved_users/{lowercased-email}` in Firestore. The doc has the
|
|
44
|
+
shape:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"email": "alice@example.com",
|
|
49
|
+
"approved": true,
|
|
50
|
+
"approvedAt": "2026-05-08T...",
|
|
51
|
+
"revoked": false,
|
|
52
|
+
"profiles_allowed": ["erosolar-code"]
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Three failure modes are surfaced separately (`src/core/userApproval.ts`):
|
|
57
|
+
|
|
58
|
+
- **Not on the list.** Writes a pending request to
|
|
59
|
+
`approval_requests/{uid}` and exits with a clear message. The
|
|
60
|
+
operator reviews requests at the
|
|
61
|
+
[Firebase Console](https://console.firebase.google.com/project/erosolar-1b0db/firestore/data/~2Fapproval_requests).
|
|
62
|
+
|
|
63
|
+
- **Revoked.** `revoked: true` denies access even when `approved: true`.
|
|
64
|
+
Preserved-but-revoked beats deletion so the audit trail of who
|
|
65
|
+
held access when stays intact. Revoked accounts cannot file new
|
|
66
|
+
requests (they must contact the operator).
|
|
67
|
+
|
|
68
|
+
- **Profile not granted.** A user approved for `erosolar-code` but
|
|
69
|
+
not `variant-research` cannot launch the offsec rulebook. New
|
|
70
|
+
approvals via `scripts/approve-user.mjs` default to
|
|
71
|
+
`['erosolar-code']` only — offsec profiles require an explicit
|
|
72
|
+
grant.
|
|
73
|
+
|
|
74
|
+
The Firestore rule for the allowlist requires the request's email to
|
|
75
|
+
exactly match the doc id, preventing enumeration of who else is
|
|
76
|
+
approved.
|
|
77
|
+
|
|
78
|
+
## Secrets
|
|
79
|
+
|
|
80
|
+
The npm tarball **ships zero embedded API keys** since `1.1.20`.
|
|
81
|
+
The audit test at `test/shared-secrets.test.ts` walks the source
|
|
82
|
+
tree and fails CI if a literal `sk-[a-f0-9]{32,64}` is ever
|
|
83
|
+
re-introduced. Resolution order at boot:
|
|
84
|
+
|
|
85
|
+
1. `process.env.DEEPSEEK_API_KEY` — explicit env override
|
|
86
|
+
2. `~/.erosolar/secrets.json` — user-set via `/key` or `/secrets`
|
|
87
|
+
3. Firestore `shared_secrets/deepseek` — admin-managed, rule-gated
|
|
88
|
+
to authenticated *and approved* users
|
|
89
|
+
|
|
90
|
+
Versions `1.1.16` → `1.1.19` are deprecated on npm with a rotation
|
|
91
|
+
warning — they bundled an embedded DeepSeek key that's now revoked.
|
|
92
|
+
|
|
93
|
+
## Audit log
|
|
94
|
+
|
|
95
|
+
Every CLI launch (after the gates pass) writes a session-start
|
|
96
|
+
entry at `usage_logs/{uid}/sessions/{timestampedId}`:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"uid": "...",
|
|
101
|
+
"email": "alice@example.com",
|
|
102
|
+
"startedAt": "2026-05-09T12:34:56.789Z",
|
|
103
|
+
"profile": "erosolar-code",
|
|
104
|
+
"model": "default",
|
|
105
|
+
"version": "1.1.26",
|
|
106
|
+
"platform": "linux"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The Firestore rule allows **create-only** for the owning user —
|
|
111
|
+
no read, no update, no delete. The operator reviews via the
|
|
112
|
+
service account / Firebase Console. A compromised user cannot
|
|
113
|
+
scrub their own history.
|
|
114
|
+
|
|
115
|
+
**No prompt content is logged.** The schema is deliberately minimal:
|
|
116
|
+
session metadata for abuse review, not surveillance. If you object
|
|
117
|
+
to the audit log, please raise a request — the controls here are
|
|
118
|
+
meant to be defensible, not adversarial.
|
|
119
|
+
|
|
120
|
+
## Coordinated disclosure
|
|
121
|
+
|
|
122
|
+
Output of the `variant-research` profile is pinned to coordinated
|
|
123
|
+
channels in the rulebook (`agents/variant-research.rules.json`),
|
|
124
|
+
critical-severity rule `vr.r.no_brokerage`:
|
|
125
|
+
|
|
126
|
+
> Disclosure terminal MUST be one of: hackerone, bugcrowd, vendor
|
|
127
|
+
> PSIRT, CERT/CC, internal-writeup, or published-advisory.
|
|
128
|
+
> NOT broker / NOT silent / NOT 'sit on it'.
|
|
129
|
+
|
|
130
|
+
The model reads the rulebook from its system prompt. This is a
|
|
131
|
+
soft enforcement — the model can in principle ignore guidance —
|
|
132
|
+
but the prose is graded `severity: critical` and the operator's
|
|
133
|
+
delivery is the audit point.
|
|
134
|
+
|
|
135
|
+
## Repo posture
|
|
136
|
+
|
|
137
|
+
- Source repo `Aroxora/deepseek-coder-cli` and the companion
|
|
138
|
+
`Aroxora/patchpivot` workspace are **private**.
|
|
139
|
+
- The npm tarball is public for distribution but cannot be used
|
|
140
|
+
without passing the SSO + allowlist gates above.
|
|
141
|
+
- Pre-push hook at `scripts/git-hooks/pre-push` runs `npm test`
|
|
142
|
+
before every push, including the embedded-key audit and the
|
|
143
|
+
HITL-suspension regression.
|
|
144
|
+
- 2FA on the publisher's GitHub + npm accounts is **required** for
|
|
145
|
+
any contributor with publish rights.
|
|
146
|
+
|
|
147
|
+
## Export controls
|
|
148
|
+
|
|
149
|
+
The agent surface includes offensive cyber tooling. U.S. export
|
|
150
|
+
classification: EAR-controlled (CCL [ECCN 4D004](https://www.federalregister.gov/documents/2021/10/21/2021-22774/information-security-controls-cybersecurity-items)),
|
|
151
|
+
not USML/ITAR. Domestic development and use is unrestricted; export
|
|
152
|
+
controls apply to international transfer. See
|
|
153
|
+
[ero.solar/about](https://ero.solar/about) for the full disclosure
|
|
154
|
+
including BIS / DDTC links and the relevant rulemaking.
|
|
155
|
+
|
|
156
|
+
## Reporting a vulnerability or abuse
|
|
157
|
+
|
|
158
|
+
- **Vulnerability in the CLI itself:** open a private GitHub issue
|
|
159
|
+
on `Aroxora/deepseek-coder-cli`, or email the operator listed in
|
|
160
|
+
the npm package's `bugs` field. Do not include exploit details
|
|
161
|
+
in public issues.
|
|
162
|
+
- **Abuse of an approved-user account:** the operator can revoke
|
|
163
|
+
via `scripts/revoke-user.mjs <email> --reason "…"`; revocation
|
|
164
|
+
is reflected on the next CLI launch.
|
|
165
|
+
- **Coordinated disclosure of a finding the CLI helped uncover:**
|
|
166
|
+
follow the rulebook's coordinated-disclosure terminal — submit
|
|
167
|
+
to the vendor / HackerOne / Bugcrowd / CERT-CC, *not* a broker,
|
|
168
|
+
*not* silent.
|
|
169
|
+
|
|
170
|
+
## Threat model — what we don't claim to defend against
|
|
171
|
+
|
|
172
|
+
This is "show, don't tell" both ways: be honest about residual
|
|
173
|
+
risk.
|
|
174
|
+
|
|
175
|
+
- **Source-level circumvention.** An approved user could fork the
|
|
176
|
+
repo, comment out the `checkApproval()` call, and run with their
|
|
177
|
+
own DeepSeek key. The gate keeps the *shared* key + audit log on
|
|
178
|
+
Erosolar's terms; it does not prevent forks.
|
|
179
|
+
- **Compromised admin credentials.** The firebase-tools OAuth
|
|
180
|
+
token (`~/.config/configstore/firebase-tools.json`) on the
|
|
181
|
+
publisher's machine has owner privileges on `erosolar-1b0db`.
|
|
182
|
+
Treat it like a service-account JSON — if it leaks, the attacker
|
|
183
|
+
can mutate the allowlist. 2FA on the underlying Google account
|
|
184
|
+
is the primary mitigation.
|
|
185
|
+
- **Model-level circumvention.** The rulebook is guidance the
|
|
186
|
+
model reads, not enforced state. A determined operator can
|
|
187
|
+
prompt around it. This is mitigated by who can launch the
|
|
188
|
+
profile (allowlist), not by the model itself.
|
|
189
|
+
- **Offline use.** A user who's already authenticated and pulled
|
|
190
|
+
the shared key into env can run the CLI without network — the
|
|
191
|
+
audit log entry won't land. Subsequent launches re-trigger the
|
|
192
|
+
gate.
|
|
193
|
+
|
|
194
|
+
If you can demonstrate a circumvention not listed here, please
|
|
195
|
+
report it via the vulnerability process above.
|
package/dist/bin/deepseek.js
CHANGED
|
@@ -6,6 +6,21 @@ import { reportStatus, reportStatusError } from '../utils/statusReporter.js';
|
|
|
6
6
|
import { track } from '../utils/analytics.js';
|
|
7
7
|
// Fast path: Handle --version, --help, --key before any heavy imports
|
|
8
8
|
const rawArgs = process.argv.slice(2);
|
|
9
|
+
/** Extract `--profile NAME` or `--profile=NAME` from argv. Used by the
|
|
10
|
+
* approval gate to check profile-specific authorization before the
|
|
11
|
+
* profile manifest is loaded. */
|
|
12
|
+
function pickProfileArg(args) {
|
|
13
|
+
const idx = args.findIndex((a) => a === '--profile');
|
|
14
|
+
if (idx >= 0) {
|
|
15
|
+
const next = args[idx + 1];
|
|
16
|
+
if (next && !next.startsWith('-'))
|
|
17
|
+
return next;
|
|
18
|
+
}
|
|
19
|
+
const eq = args.find((a) => a.startsWith('--profile='));
|
|
20
|
+
if (eq)
|
|
21
|
+
return eq.slice('--profile='.length);
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
9
24
|
// Best-effort, non-blocking analytics ping. Never throws, never awaited.
|
|
10
25
|
const subcommand = rawArgs[0]?.startsWith('-') ? '(flags)' : (rawArgs[0] || 'default');
|
|
11
26
|
track('cli_invoked', { subcommand, arg_count: rawArgs.length });
|
|
@@ -213,15 +228,66 @@ async function main() {
|
|
|
213
228
|
// Require authentication before continuing
|
|
214
229
|
const { requireAuth } = await import('../core/auth.js');
|
|
215
230
|
await requireAuth();
|
|
231
|
+
// Approved-users gate. The CLI carries offsec tooling, so every
|
|
232
|
+
// launch checks the signed-in email against the Firestore allowlist
|
|
233
|
+
// at `approved_users/{email}`. Misses get a request doc written for
|
|
234
|
+
// the operator to review, then the CLI refuses to start. SSO is
|
|
235
|
+
// also enforced at the Firestore-rule layer (sign_in_provider ==
|
|
236
|
+
// 'google.com'), so a non-SSO token can't even read the doc.
|
|
237
|
+
// The check also enforces:
|
|
238
|
+
// - revocation: `revoked: true` on the doc denies access even if
|
|
239
|
+
// `approved: true` (faster than removing the doc — preserves
|
|
240
|
+
// the audit trail of who held access when).
|
|
241
|
+
// - profile gating: `profiles_allowed: ['variant-research', ...]`
|
|
242
|
+
// restricts which agent profiles a user can launch. Missing
|
|
243
|
+
// field = permissive (backward compat). New approvals default
|
|
244
|
+
// to `['erosolar-code']` only.
|
|
245
|
+
const requestedProfile = pickProfileArg(rawArgs) ?? process.env['EROSOLAR_PROFILE'] ?? 'erosolar-code';
|
|
246
|
+
const { checkApproval, requestApproval } = await import('../core/userApproval.js');
|
|
247
|
+
const approval = await checkApproval(requestedProfile);
|
|
248
|
+
if (!approval.approved) {
|
|
249
|
+
process.stderr.write('\n');
|
|
250
|
+
process.stderr.write('Access denied — this account is not authorized.\n');
|
|
251
|
+
process.stderr.write(` Email: ${approval.email ?? '(no email on token — SSO required)'}\n`);
|
|
252
|
+
process.stderr.write(` Profile: ${requestedProfile}\n`);
|
|
253
|
+
process.stderr.write(` Reason: ${approval.reason ?? 'unknown'}\n\n`);
|
|
254
|
+
if (approval.email && approval.uid && !approval.revoked) {
|
|
255
|
+
const req = await requestApproval();
|
|
256
|
+
if (req.ok) {
|
|
257
|
+
process.stderr.write('A request has been recorded. The administrator will review it.\n');
|
|
258
|
+
process.stderr.write('You can re-run `erosolar` once the approval lands.\n');
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
process.stderr.write(`Could not file approval request: ${req.reason}\n`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else if (approval.revoked) {
|
|
265
|
+
process.stderr.write('Revoked accounts cannot file new requests. Contact the operator directly.\n');
|
|
266
|
+
}
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
216
269
|
// Hydrate shared provider keys from Firestore. Runs after requireAuth
|
|
217
|
-
// so a valid Firebase ID token is already on disk
|
|
218
|
-
//
|
|
219
|
-
//
|
|
270
|
+
// + checkApproval so a valid Firebase ID token is already on disk
|
|
271
|
+
// and the user is on the allowlist. If the user has their own
|
|
272
|
+
// DEEPSEEK_API_KEY in env or saved via /secrets, this is a no-op;
|
|
273
|
+
// otherwise it fetches the org-managed key from
|
|
220
274
|
// shared_secrets/deepseek (Firestore-rule-gated by auth) and writes
|
|
221
275
|
// it into process.env before any provider is constructed. The CLI
|
|
222
276
|
// ships zero embedded keys.
|
|
223
277
|
const { prefetchAllSharedSecrets } = await import('../core/sharedSecrets.js');
|
|
224
278
|
await prefetchAllSharedSecrets();
|
|
279
|
+
// Audit log — best-effort write of session metadata to Firestore.
|
|
280
|
+
// Schema is deliberately minimal: profile/model/version/platform.
|
|
281
|
+
// No prompt content is recorded; logs are for abuse review and
|
|
282
|
+
// accountability, not surveillance. Failures here are non-fatal —
|
|
283
|
+
// logging is observability, not a runtime gate.
|
|
284
|
+
const { writeUsageLog } = await import('../core/userApproval.js');
|
|
285
|
+
void writeUsageLog({
|
|
286
|
+
profile: requestedProfile,
|
|
287
|
+
model: process.env[`${requestedProfile.toUpperCase().replace(/[^A-Z0-9]/g, '_')}_MODEL`] || 'default',
|
|
288
|
+
version: process.env['npm_package_version'] || 'unknown',
|
|
289
|
+
platform: process.platform,
|
|
290
|
+
}).catch(() => { });
|
|
225
291
|
// Force color support for TTY terminals
|
|
226
292
|
if (process.stdout.isTTY && !process.env['NO_COLOR']) {
|
|
227
293
|
process.env['FORCE_COLOR'] = process.env['FORCE_COLOR'] ?? '1';
|
package/dist/bin/deepseek.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../../src/bin/deepseek.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../../src/bin/deepseek.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C,sEAAsE;AACtE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEtC;;iCAEiC;AACjC,SAAS,cAAc,CAAC,IAAc;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC;IACrD,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC3B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACjD,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IACxD,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC;AACvF,KAAK,CAAC,aAAa,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAEhE,gEAAgE;AAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACvF,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;IACpB,IAAI,QAA4B,CAAC;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,GAAG,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5E,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAC1B,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC9B,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;oBAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;oBACvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;oBAExD,IAAI,CAAC;wBACH,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;wBAC7C,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;4BACxC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;4BAClD,CAAC,CAAC,EAAE,CAAC;wBACP,QAAQ,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CAAC;wBACxC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;wBACvE,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;wBACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAClB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,YAAY,CAAC,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;wBAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAClB,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,oCAAoC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;KAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnE,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAC1B,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC9B,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBAC5B,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC,CAAC;oBAC7E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;oBAC1D,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;gBAC/D,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;gBACtD,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBb,CAAC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;IAClC,qEAAqE;IACrE,sEAAsE;IACtE,mEAAmE;IACnE,uEAAuE;IACvE,0CAA0C;IAC1C,KAAK,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACnD,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,KAAK,IAAI,EAAE,CAAC;AACd,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAc;IAC3C,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAE/B,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;CAef,CAAC;IAEA,IAAI,CAAC;QACH,IAAI,MAAe,CAAC;QACpB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;gBACpC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACP,OAAO,CAAC,KAAK,CAAC,+EAA+E,CAAC,CAAC;oBAC/F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBACD,MAAM,GAAG,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD,KAAK,OAAO;gBACV,MAAM,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC5C,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC;gBACxD,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;gBAC/C,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC;gBACxD,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;gBAChD,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,MAAM;YACR,KAAK,UAAU,CAAC;YAChB,KAAK,KAAK;gBACR,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC;gBACxD,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;gBAC/C,MAAM;YACR,KAAK,SAAS;gBACZ,MAAM,GAAG,MAAM,YAAY,CAAC,WAAW,EAAE,CAAC;gBAC1C,MAAM;YACR,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,CAAC,IAAI,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC;gBACrD,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACzC,MAAM;YACR,CAAC;YACD,KAAK,OAAO;gBACV,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC;gBACpC,MAAM;YACR,KAAK,SAAS;gBACZ,MAAM,GAAG,MAAM,YAAY,CAAC,WAAW,EAAE,CAAC;gBAC1C,MAAM;YACR,KAAK,QAAQ,CAAC;YACd,KAAK,IAAI,CAAC;YACV,KAAK,MAAM;gBACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB;gBACE,OAAO,CAAC,KAAK,CAAC,uBAAuB,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC;gBACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,2CAA2C;IAC3C,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACxD,MAAM,WAAW,EAAE,CAAC;IAEpB,gEAAgE;IAChE,oEAAoE;IACpE,oEAAoE;IACpE,gEAAgE;IAChE,iEAAiE;IACjE,6DAA6D;IAC7D,2BAA2B;IAC3B,mEAAmE;IACnE,iEAAiE;IACjE,gDAAgD;IAChD,oEAAoE;IACpE,gEAAgE;IAChE,kEAAkE;IAClE,mCAAmC;IACnC,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,eAAe,CAAC;IACvG,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACvD,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,QAAQ,CAAC,KAAK,IAAI,oCAAoC,IAAI,CAAC,CAAC;QAChG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,gBAAgB,IAAI,CAAC,CAAC;QAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,QAAQ,CAAC,MAAM,IAAI,SAAS,MAAM,CAAC,CAAC;QACxE,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,MAAM,eAAe,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;gBACzF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC/E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;aAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QACtG,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,sEAAsE;IACtE,kEAAkE;IAClE,8DAA8D;IAC9D,kEAAkE;IAClE,gDAAgD;IAChD,oEAAoE;IACpE,kEAAkE;IAClE,4BAA4B;IAC5B,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAC9E,MAAM,wBAAwB,EAAE,CAAC;IAEjC,kEAAkE;IAClE,kEAAkE;IAClE,+DAA+D;IAC/D,kEAAkE;IAClE,gDAAgD;IAChD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;IAClE,KAAK,aAAa,CAAC;QACjB,OAAO,EAAE,gBAAgB;QACzB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS;QACrG,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,SAAS;QACxD,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAqB,CAAC,CAAC,CAAC;IAEtC,wCAAwC;IACxC,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC;IACjE,CAAC;IAED,iBAAiB;IACjB,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACpC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QACtD,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,OAAO;IACT,CAAC;IAED,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;IAChF,mBAAmB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrD,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approved-user gate.
|
|
3
|
+
*
|
|
4
|
+
* The CLI ships offsec capabilities (Kali tools, AFL++, gdb, pwntools,
|
|
5
|
+
* Ghidra MCP wiring). To prevent random Google accounts from picking
|
|
6
|
+
* up the package and burning the shared key on toy targets, every
|
|
7
|
+
* launch checks the user's email against `approved_users/{email}` in
|
|
8
|
+
* Firestore. Misses get a `approval_requests/{uid}` doc written for
|
|
9
|
+
* the operator to review, then the CLI exits with an explanatory
|
|
10
|
+
* message.
|
|
11
|
+
*
|
|
12
|
+
* SSO is enforced two ways:
|
|
13
|
+
* 1. The web sign-in page only offers Google.
|
|
14
|
+
* 2. Firestore rules also check `request.auth.token.firebase.sign_in_provider == 'google.com'`
|
|
15
|
+
* so a non-SSO token (anonymous, password) can't read the
|
|
16
|
+
* approved_users doc — defense in depth.
|
|
17
|
+
*
|
|
18
|
+
* Email is the canonical identity here, lowercased + trimmed. UID is
|
|
19
|
+
* recorded on the request doc so the admin can correlate but not used
|
|
20
|
+
* as the primary key (UIDs are opaque; humans review by email).
|
|
21
|
+
*/
|
|
22
|
+
export interface ApprovalResult {
|
|
23
|
+
approved: boolean;
|
|
24
|
+
email: string | null;
|
|
25
|
+
uid: string | null;
|
|
26
|
+
reason?: string;
|
|
27
|
+
revoked?: boolean;
|
|
28
|
+
profilesAllowed?: string[];
|
|
29
|
+
}
|
|
30
|
+
export declare function normalizeEmail(email: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Verify the currently-signed-in user is on the approved list.
|
|
33
|
+
* Side-effect free; just reads. Errors are surfaced as `approved: false`
|
|
34
|
+
* with a reason so the caller can decide whether to file a request
|
|
35
|
+
* doc and/or surface the message.
|
|
36
|
+
*
|
|
37
|
+
* Optional `profile` arg restricts the check: if set, the user's
|
|
38
|
+
* `profiles_allowed` must include either `*` (all) or this profile
|
|
39
|
+
* name. Missing `profiles_allowed` is treated as permissive for
|
|
40
|
+
* backward compatibility with the initial bootstrap docs that
|
|
41
|
+
* predate the field. New approvals via `scripts/approve-user.mjs`
|
|
42
|
+
* default to `['erosolar-code']` only — offsec profiles like
|
|
43
|
+
* `variant-research` require an explicit grant.
|
|
44
|
+
*/
|
|
45
|
+
export declare function checkApproval(profile?: string): Promise<ApprovalResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Idempotently write `approval_requests/{uid}` so the admin sees a
|
|
48
|
+
* pending request. Firestore rules let any authenticated user PATCH
|
|
49
|
+
* their own request doc but no one can read a sibling's. Returning
|
|
50
|
+
* `ok: true` doesn't mean approved — only that the request landed.
|
|
51
|
+
*/
|
|
52
|
+
export declare function requestApproval(): Promise<{
|
|
53
|
+
ok: boolean;
|
|
54
|
+
reason?: string;
|
|
55
|
+
}>;
|
|
56
|
+
export interface UsageLogEntry {
|
|
57
|
+
profile: string;
|
|
58
|
+
model: string;
|
|
59
|
+
version: string;
|
|
60
|
+
platform: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Append an audit-log entry at `usage_logs/{uid}/sessions/{sessionId}`.
|
|
64
|
+
* Best-effort: a Firestore failure does NOT block the user's session
|
|
65
|
+
* — logging is observability, not a runtime gate. Schema is
|
|
66
|
+
* deliberately minimal (no prompt content, no env): just session
|
|
67
|
+
* metadata so the operator can review patterns and detect abuse
|
|
68
|
+
* without retaining user-visible content.
|
|
69
|
+
*/
|
|
70
|
+
export declare function writeUsageLog(entry: UsageLogEntry): Promise<{
|
|
71
|
+
ok: boolean;
|
|
72
|
+
reason?: string;
|
|
73
|
+
}>;
|
|
74
|
+
//# sourceMappingURL=userApproval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userApproval.d.ts","sourceRoot":"","sources":["../../src/core/userApproval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AA6CD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA6C7E;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BjF;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiCnG"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approved-user gate.
|
|
3
|
+
*
|
|
4
|
+
* The CLI ships offsec capabilities (Kali tools, AFL++, gdb, pwntools,
|
|
5
|
+
* Ghidra MCP wiring). To prevent random Google accounts from picking
|
|
6
|
+
* up the package and burning the shared key on toy targets, every
|
|
7
|
+
* launch checks the user's email against `approved_users/{email}` in
|
|
8
|
+
* Firestore. Misses get a `approval_requests/{uid}` doc written for
|
|
9
|
+
* the operator to review, then the CLI exits with an explanatory
|
|
10
|
+
* message.
|
|
11
|
+
*
|
|
12
|
+
* SSO is enforced two ways:
|
|
13
|
+
* 1. The web sign-in page only offers Google.
|
|
14
|
+
* 2. Firestore rules also check `request.auth.token.firebase.sign_in_provider == 'google.com'`
|
|
15
|
+
* so a non-SSO token (anonymous, password) can't read the
|
|
16
|
+
* approved_users doc — defense in depth.
|
|
17
|
+
*
|
|
18
|
+
* Email is the canonical identity here, lowercased + trimmed. UID is
|
|
19
|
+
* recorded on the request doc so the admin can correlate but not used
|
|
20
|
+
* as the primary key (UIDs are opaque; humans review by email).
|
|
21
|
+
*/
|
|
22
|
+
import { FIREBASE_PROJECT_ID, getAuthStatus, getValidIdToken } from './auth.js';
|
|
23
|
+
const FIRESTORE_BASE = `https://firestore.googleapis.com/v1/projects/${FIREBASE_PROJECT_ID}/databases/(default)/documents`;
|
|
24
|
+
export function normalizeEmail(email) {
|
|
25
|
+
return email.trim().toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
function readArrayOfStrings(field) {
|
|
28
|
+
const arr = field?.arrayValue?.values;
|
|
29
|
+
if (!Array.isArray(arr))
|
|
30
|
+
return undefined;
|
|
31
|
+
return arr
|
|
32
|
+
.map((v) => v.stringValue)
|
|
33
|
+
.filter((v) => typeof v === 'string');
|
|
34
|
+
}
|
|
35
|
+
async function fetchApprovalDoc(email) {
|
|
36
|
+
const idToken = await getValidIdToken();
|
|
37
|
+
const url = `${FIRESTORE_BASE}/approved_users/${encodeURIComponent(email)}`;
|
|
38
|
+
const res = await fetch(url, {
|
|
39
|
+
headers: { Authorization: `Bearer ${idToken}`, Accept: 'application/json' },
|
|
40
|
+
});
|
|
41
|
+
if (res.status === 404)
|
|
42
|
+
return null;
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
const body = await res.text().catch(() => '<no body>');
|
|
45
|
+
throw new Error(`Firestore ${res.status} reading approved_users/${email}: ${body.slice(0, 200)}`);
|
|
46
|
+
}
|
|
47
|
+
const doc = (await res.json());
|
|
48
|
+
const approved = doc.fields?.['approved']?.booleanValue === true;
|
|
49
|
+
const revoked = doc.fields?.['revoked']?.booleanValue === true;
|
|
50
|
+
const profilesAllowed = readArrayOfStrings(doc.fields?.['profiles_allowed']);
|
|
51
|
+
return { approved, revoked, profilesAllowed };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Verify the currently-signed-in user is on the approved list.
|
|
55
|
+
* Side-effect free; just reads. Errors are surfaced as `approved: false`
|
|
56
|
+
* with a reason so the caller can decide whether to file a request
|
|
57
|
+
* doc and/or surface the message.
|
|
58
|
+
*
|
|
59
|
+
* Optional `profile` arg restricts the check: if set, the user's
|
|
60
|
+
* `profiles_allowed` must include either `*` (all) or this profile
|
|
61
|
+
* name. Missing `profiles_allowed` is treated as permissive for
|
|
62
|
+
* backward compatibility with the initial bootstrap docs that
|
|
63
|
+
* predate the field. New approvals via `scripts/approve-user.mjs`
|
|
64
|
+
* default to `['erosolar-code']` only — offsec profiles like
|
|
65
|
+
* `variant-research` require an explicit grant.
|
|
66
|
+
*/
|
|
67
|
+
export async function checkApproval(profile) {
|
|
68
|
+
const status = getAuthStatus();
|
|
69
|
+
if (!status.authenticated) {
|
|
70
|
+
return { approved: false, email: null, uid: null, reason: 'not signed in' };
|
|
71
|
+
}
|
|
72
|
+
const email = status.email ? normalizeEmail(status.email) : null;
|
|
73
|
+
const uid = status.uid ?? null;
|
|
74
|
+
if (!email) {
|
|
75
|
+
return { approved: false, email, uid, reason: 'no email on auth token (SSO required)' };
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const doc = await fetchApprovalDoc(email);
|
|
79
|
+
if (!doc) {
|
|
80
|
+
return { approved: false, email, uid, reason: 'email not on approved-users list' };
|
|
81
|
+
}
|
|
82
|
+
if (!doc.approved) {
|
|
83
|
+
return { approved: false, email, uid, reason: 'email not on approved-users list' };
|
|
84
|
+
}
|
|
85
|
+
if (doc.revoked) {
|
|
86
|
+
return {
|
|
87
|
+
approved: false,
|
|
88
|
+
email,
|
|
89
|
+
uid,
|
|
90
|
+
reason: 'access revoked — contact the operator',
|
|
91
|
+
revoked: true,
|
|
92
|
+
profilesAllowed: doc.profilesAllowed,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (profile && doc.profilesAllowed && doc.profilesAllowed.length > 0) {
|
|
96
|
+
const allowed = doc.profilesAllowed.includes('*') || doc.profilesAllowed.includes(profile);
|
|
97
|
+
if (!allowed) {
|
|
98
|
+
return {
|
|
99
|
+
approved: false,
|
|
100
|
+
email,
|
|
101
|
+
uid,
|
|
102
|
+
reason: `profile "${profile}" not granted to this account (allowed: ${doc.profilesAllowed.join(', ')})`,
|
|
103
|
+
profilesAllowed: doc.profilesAllowed,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { approved: true, email, uid, profilesAllowed: doc.profilesAllowed };
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
111
|
+
return { approved: false, email, uid, reason: `approval check failed: ${msg}` };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Idempotently write `approval_requests/{uid}` so the admin sees a
|
|
116
|
+
* pending request. Firestore rules let any authenticated user PATCH
|
|
117
|
+
* their own request doc but no one can read a sibling's. Returning
|
|
118
|
+
* `ok: true` doesn't mean approved — only that the request landed.
|
|
119
|
+
*/
|
|
120
|
+
export async function requestApproval() {
|
|
121
|
+
const status = getAuthStatus();
|
|
122
|
+
if (!status.authenticated || !status.uid) {
|
|
123
|
+
return { ok: false, reason: 'not signed in' };
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const idToken = await getValidIdToken();
|
|
127
|
+
const url = `${FIRESTORE_BASE}/approval_requests/${encodeURIComponent(status.uid)}`;
|
|
128
|
+
const body = {
|
|
129
|
+
fields: {
|
|
130
|
+
email: { stringValue: status.email ?? '' },
|
|
131
|
+
uid: { stringValue: status.uid },
|
|
132
|
+
requestedAt: { timestampValue: new Date().toISOString() },
|
|
133
|
+
status: { stringValue: 'pending' },
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
const res = await fetch(url, {
|
|
137
|
+
method: 'PATCH',
|
|
138
|
+
headers: { Authorization: `Bearer ${idToken}`, 'Content-Type': 'application/json' },
|
|
139
|
+
body: JSON.stringify(body),
|
|
140
|
+
});
|
|
141
|
+
if (!res.ok) {
|
|
142
|
+
const txt = await res.text().catch(() => '<no body>');
|
|
143
|
+
return { ok: false, reason: `Firestore ${res.status}: ${txt.slice(0, 200)}` };
|
|
144
|
+
}
|
|
145
|
+
return { ok: true };
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Append an audit-log entry at `usage_logs/{uid}/sessions/{sessionId}`.
|
|
153
|
+
* Best-effort: a Firestore failure does NOT block the user's session
|
|
154
|
+
* — logging is observability, not a runtime gate. Schema is
|
|
155
|
+
* deliberately minimal (no prompt content, no env): just session
|
|
156
|
+
* metadata so the operator can review patterns and detect abuse
|
|
157
|
+
* without retaining user-visible content.
|
|
158
|
+
*/
|
|
159
|
+
export async function writeUsageLog(entry) {
|
|
160
|
+
const status = getAuthStatus();
|
|
161
|
+
if (!status.authenticated || !status.uid) {
|
|
162
|
+
return { ok: false, reason: 'not signed in' };
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
const idToken = await getValidIdToken();
|
|
166
|
+
const sessionId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
167
|
+
const url = `${FIRESTORE_BASE}/usage_logs/${encodeURIComponent(status.uid)}/sessions?documentId=${encodeURIComponent(sessionId)}`;
|
|
168
|
+
const body = {
|
|
169
|
+
fields: {
|
|
170
|
+
uid: { stringValue: status.uid },
|
|
171
|
+
email: { stringValue: status.email ?? '' },
|
|
172
|
+
startedAt: { timestampValue: new Date().toISOString() },
|
|
173
|
+
profile: { stringValue: entry.profile },
|
|
174
|
+
model: { stringValue: entry.model },
|
|
175
|
+
version: { stringValue: entry.version },
|
|
176
|
+
platform: { stringValue: entry.platform },
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
const res = await fetch(url, {
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: { Authorization: `Bearer ${idToken}`, 'Content-Type': 'application/json' },
|
|
182
|
+
body: JSON.stringify(body),
|
|
183
|
+
});
|
|
184
|
+
if (!res.ok) {
|
|
185
|
+
const txt = await res.text().catch(() => '<no body>');
|
|
186
|
+
return { ok: false, reason: `Firestore ${res.status}: ${txt.slice(0, 200)}` };
|
|
187
|
+
}
|
|
188
|
+
return { ok: true };
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=userApproval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userApproval.js","sourceRoot":"","sources":["../../src/core/userApproval.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trenchwork/erosolar",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.26",
|
|
4
4
|
"description": "DeepSeek AI-powered CLI agent for code assistance and automation",
|
|
5
5
|
"deepseek": {
|
|
6
6
|
"rulebookSchema": "src/contracts/schemas/agent-rules.schema.json"
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"dist",
|
|
18
18
|
"scripts/postinstall.cjs",
|
|
19
19
|
"README.md",
|
|
20
|
+
"SECURITY.md",
|
|
20
21
|
"agents",
|
|
21
22
|
"LICENSE"
|
|
22
23
|
],
|