@trenchwork/erosolar 1.1.25 → 1.1.27
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 +6 -0
- package/SECURITY.md +195 -0
- package/dist/bin/deepseek.js +45 -5
- package/dist/bin/deepseek.js.map +1 -1
- package/dist/capabilities/ghidraHeadlessCapability.d.ts +25 -0
- package/dist/capabilities/ghidraHeadlessCapability.d.ts.map +1 -0
- package/dist/capabilities/ghidraHeadlessCapability.js +593 -0
- package/dist/capabilities/ghidraHeadlessCapability.js.map +1 -0
- package/dist/capabilities/index.d.ts +1 -0
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +1 -0
- package/dist/capabilities/index.js.map +1 -1
- package/dist/core/userApproval.d.ts +29 -1
- package/dist/core/userApproval.d.ts.map +1 -1
- package/dist/core/userApproval.js +92 -5
- package/dist/core/userApproval.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -431,6 +431,12 @@ that range will print an `npm deprecate` warning. Upgrade to ≥
|
|
|
431
431
|
|
|
432
432
|
## Security posture
|
|
433
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
|
+
|
|
434
440
|
- The CLI is dual-use offensive-security tooling. U.S. classification
|
|
435
441
|
is EAR-controlled (CCL [ECCN 4D004](https://www.federalregister.gov/documents/2021/10/21/2021-22774/information-security-controls-cybersecurity-items)),
|
|
436
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 });
|
|
@@ -219,14 +234,24 @@ async function main() {
|
|
|
219
234
|
// the operator to review, then the CLI refuses to start. SSO is
|
|
220
235
|
// also enforced at the Firestore-rule layer (sign_in_provider ==
|
|
221
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';
|
|
222
246
|
const { checkApproval, requestApproval } = await import('../core/userApproval.js');
|
|
223
|
-
const approval = await checkApproval();
|
|
247
|
+
const approval = await checkApproval(requestedProfile);
|
|
224
248
|
if (!approval.approved) {
|
|
225
249
|
process.stderr.write('\n');
|
|
226
|
-
process.stderr.write('Access denied — this account is not
|
|
227
|
-
process.stderr.write(` Email:
|
|
228
|
-
process.stderr.write(`
|
|
229
|
-
|
|
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) {
|
|
230
255
|
const req = await requestApproval();
|
|
231
256
|
if (req.ok) {
|
|
232
257
|
process.stderr.write('A request has been recorded. The administrator will review it.\n');
|
|
@@ -236,6 +261,9 @@ async function main() {
|
|
|
236
261
|
process.stderr.write(`Could not file approval request: ${req.reason}\n`);
|
|
237
262
|
}
|
|
238
263
|
}
|
|
264
|
+
else if (approval.revoked) {
|
|
265
|
+
process.stderr.write('Revoked accounts cannot file new requests. Contact the operator directly.\n');
|
|
266
|
+
}
|
|
239
267
|
process.exit(1);
|
|
240
268
|
}
|
|
241
269
|
// Hydrate shared provider keys from Firestore. Runs after requireAuth
|
|
@@ -248,6 +276,18 @@ async function main() {
|
|
|
248
276
|
// ships zero embedded keys.
|
|
249
277
|
const { prefetchAllSharedSecrets } = await import('../core/sharedSecrets.js');
|
|
250
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(() => { });
|
|
251
291
|
// Force color support for TTY terminals
|
|
252
292
|
if (process.stdout.isTTY && !process.env['NO_COLOR']) {
|
|
253
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":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ghidra `analyzeHeadless` wrappers — direct binding to the
|
|
3
|
+
* support/analyzeHeadless driver Project Zero / NSA / Trail of Bits
|
|
4
|
+
* use at scale, no MCP bridge required. Each tool spawns
|
|
5
|
+
* analyzeHeadless with one of the embedded Jython post-scripts;
|
|
6
|
+
* scripts write JSON to a temp file the TS handler reads. Project
|
|
7
|
+
* databases live under ~/.erosolar/ghidra-projects/<project>/ so
|
|
8
|
+
* a follow-up tool call (decompile, xrefs, list-functions) reuses
|
|
9
|
+
* the analysis from the prior `ghidra_analyze` run.
|
|
10
|
+
*
|
|
11
|
+
* The post-script approach is preferred over running scripts via
|
|
12
|
+
* the Ghidra GUI / MCP bridge because:
|
|
13
|
+
* - No process to keep alive; analyzeHeadless exits per call.
|
|
14
|
+
* - Version-stable; the Jython script API is much more stable
|
|
15
|
+
* than the MCP server's surface.
|
|
16
|
+
* - First-class to Ghidra; this is the path the security
|
|
17
|
+
* research community already uses.
|
|
18
|
+
*/
|
|
19
|
+
import type { CapabilityContext, CapabilityContribution, CapabilityModule } from '../runtime/agentHost.js';
|
|
20
|
+
export declare class GhidraHeadlessCapabilityModule implements CapabilityModule {
|
|
21
|
+
readonly id = "capability.ghidraHeadless";
|
|
22
|
+
readonly description = "Ghidra analyzeHeadless wrappers \u2014 ghidra_analyze, ghidra_list_functions, ghidra_decompile, ghidra_xrefs, ghidra_fid_matches, ghidra_function_diff, ghidra_delete_project. Each tool spawns analyzeHeadless once with an embedded Jython post-script; project databases persist under ~/.erosolar/ghidra-projects/.";
|
|
23
|
+
create(_context: CapabilityContext): Promise<CapabilityContribution>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ghidraHeadlessCapability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ghidraHeadlessCapability.d.ts","sourceRoot":"","sources":["../../src/capabilities/ghidraHeadlessCapability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH,OAAO,KAAK,EACV,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAqkBjC,qBAAa,8BAA+B,YAAW,gBAAgB;IACrE,QAAQ,CAAC,EAAE,+BAA+B;IAC1C,QAAQ,CAAC,WAAW,6TAAwT;IAEtU,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAU3E"}
|
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ghidra `analyzeHeadless` wrappers — direct binding to the
|
|
3
|
+
* support/analyzeHeadless driver Project Zero / NSA / Trail of Bits
|
|
4
|
+
* use at scale, no MCP bridge required. Each tool spawns
|
|
5
|
+
* analyzeHeadless with one of the embedded Jython post-scripts;
|
|
6
|
+
* scripts write JSON to a temp file the TS handler reads. Project
|
|
7
|
+
* databases live under ~/.erosolar/ghidra-projects/<project>/ so
|
|
8
|
+
* a follow-up tool call (decompile, xrefs, list-functions) reuses
|
|
9
|
+
* the analysis from the prior `ghidra_analyze` run.
|
|
10
|
+
*
|
|
11
|
+
* The post-script approach is preferred over running scripts via
|
|
12
|
+
* the Ghidra GUI / MCP bridge because:
|
|
13
|
+
* - No process to keep alive; analyzeHeadless exits per call.
|
|
14
|
+
* - Version-stable; the Jython script API is much more stable
|
|
15
|
+
* than the MCP server's surface.
|
|
16
|
+
* - First-class to Ghidra; this is the path the security
|
|
17
|
+
* research community already uses.
|
|
18
|
+
*/
|
|
19
|
+
import { spawn } from 'node:child_process';
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
21
|
+
import { homedir, tmpdir } from 'node:os';
|
|
22
|
+
import { join } from 'node:path';
|
|
23
|
+
import { logDebug } from '../utils/debugLogger.js';
|
|
24
|
+
const GHIDRA_HEADLESS = process.env['GHIDRA_HEADLESS']
|
|
25
|
+
|| (existsSync('/usr/share/ghidra/support/analyzeHeadless')
|
|
26
|
+
? '/usr/share/ghidra/support/analyzeHeadless'
|
|
27
|
+
: '/opt/ghidra/support/analyzeHeadless');
|
|
28
|
+
const PROJECTS_ROOT = join(homedir(), '.erosolar', 'ghidra-projects');
|
|
29
|
+
const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // analyzeHeadless can take a while on large binaries
|
|
30
|
+
const SCRIPT_DIR = join(tmpdir(), 'erosolar-ghidra-scripts');
|
|
31
|
+
/* ------------------------------------------------------------------
|
|
32
|
+
* Embedded Java GhidraScript post-scripts.
|
|
33
|
+
*
|
|
34
|
+
* Modern Ghidra (12.x in Kali 2026) replaced Jython with PyGhidra
|
|
35
|
+
* (CPython bridge), which requires `pip install pyghidra`. Java
|
|
36
|
+
* GhidraScripts compile at script-load time inside Ghidra's JVM —
|
|
37
|
+
* no extra deps for end users. Each script writes a JSON file the
|
|
38
|
+
* TS handler reads back.
|
|
39
|
+
*
|
|
40
|
+
* All scripts share the same shape:
|
|
41
|
+
* public class <Name> extends GhidraScript {
|
|
42
|
+
* public void run() throws Exception {
|
|
43
|
+
* String[] args = getScriptArgs();
|
|
44
|
+
* String out = args[0];
|
|
45
|
+
* // ... build JSON, write to out ...
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* JSON is hand-built. The shape is small per-call and Ghidra's
|
|
50
|
+
* classpath doesn't reliably expose Jackson/Gson to scripts.
|
|
51
|
+
* ----------------------------------------------------------------*/
|
|
52
|
+
const JSON_HELPERS = `
|
|
53
|
+
private static String jsonStr(String s) {
|
|
54
|
+
if (s == null) return "null";
|
|
55
|
+
StringBuilder sb = new StringBuilder("\\"");
|
|
56
|
+
for (int i = 0; i < s.length(); i++) {
|
|
57
|
+
char c = s.charAt(i);
|
|
58
|
+
switch (c) {
|
|
59
|
+
case '\\\\': sb.append("\\\\\\\\"); break;
|
|
60
|
+
case '"': sb.append("\\\\\\""); break;
|
|
61
|
+
case '\\n': sb.append("\\\\n"); break;
|
|
62
|
+
case '\\r': sb.append("\\\\r"); break;
|
|
63
|
+
case '\\t': sb.append("\\\\t"); break;
|
|
64
|
+
case '\\b': sb.append("\\\\b"); break;
|
|
65
|
+
case '\\f': sb.append("\\\\f"); break;
|
|
66
|
+
default:
|
|
67
|
+
if (c < 0x20) {
|
|
68
|
+
sb.append(String.format("\\\\u%04x", (int) c));
|
|
69
|
+
} else {
|
|
70
|
+
sb.append(c);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
sb.append("\\"");
|
|
75
|
+
return sb.toString();
|
|
76
|
+
}
|
|
77
|
+
private static String hex(long v) { return "0x" + Long.toHexString(v); }
|
|
78
|
+
`;
|
|
79
|
+
const SCRIPT_LIST_FUNCTIONS = `// EvrpListFunctions.java
|
|
80
|
+
import ghidra.app.script.GhidraScript;
|
|
81
|
+
import ghidra.program.model.listing.Function;
|
|
82
|
+
import java.io.FileWriter;
|
|
83
|
+
import java.util.ArrayList;
|
|
84
|
+
import java.util.List;
|
|
85
|
+
|
|
86
|
+
public class EvrpListFunctions extends GhidraScript {
|
|
87
|
+
${JSON_HELPERS}
|
|
88
|
+
@Override
|
|
89
|
+
public void run() throws Exception {
|
|
90
|
+
String[] args = getScriptArgs();
|
|
91
|
+
String out = args[0];
|
|
92
|
+
List<String> entries = new ArrayList<>();
|
|
93
|
+
for (Function f : currentProgram.getFunctionManager().getFunctions(true)) {
|
|
94
|
+
String sig;
|
|
95
|
+
try { sig = f.getPrototypeString(true, true); } catch (Exception e) { sig = f.getName() + "()"; }
|
|
96
|
+
entries.add("{\\"name\\":" + jsonStr(f.getName())
|
|
97
|
+
+ ",\\"entry\\":" + jsonStr(hex(f.getEntryPoint().getOffset()))
|
|
98
|
+
+ ",\\"size\\":" + f.getBody().getNumAddresses()
|
|
99
|
+
+ ",\\"signature\\":" + jsonStr(sig)
|
|
100
|
+
+ ",\\"thunk\\":" + f.isThunk()
|
|
101
|
+
+ ",\\"external\\":" + f.isExternal() + "}");
|
|
102
|
+
}
|
|
103
|
+
StringBuilder sb = new StringBuilder();
|
|
104
|
+
sb.append("{\\"program\\":").append(jsonStr(currentProgram.getName()));
|
|
105
|
+
sb.append(",\\"functionCount\\":").append(entries.size());
|
|
106
|
+
sb.append(",\\"functions\\":[");
|
|
107
|
+
for (int i = 0; i < entries.size(); i++) {
|
|
108
|
+
if (i > 0) sb.append(",");
|
|
109
|
+
sb.append(entries.get(i));
|
|
110
|
+
}
|
|
111
|
+
sb.append("]}");
|
|
112
|
+
try (FileWriter fw = new FileWriter(out)) { fw.write(sb.toString()); }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
const SCRIPT_DECOMPILE = `// EvrpDecompile.java
|
|
117
|
+
import ghidra.app.script.GhidraScript;
|
|
118
|
+
import ghidra.app.decompiler.DecompInterface;
|
|
119
|
+
import ghidra.app.decompiler.DecompileResults;
|
|
120
|
+
import ghidra.program.model.address.Address;
|
|
121
|
+
import ghidra.program.model.listing.Function;
|
|
122
|
+
import ghidra.program.model.listing.FunctionManager;
|
|
123
|
+
import ghidra.util.task.ConsoleTaskMonitor;
|
|
124
|
+
import java.io.FileWriter;
|
|
125
|
+
|
|
126
|
+
public class EvrpDecompile extends GhidraScript {
|
|
127
|
+
${JSON_HELPERS}
|
|
128
|
+
@Override
|
|
129
|
+
public void run() throws Exception {
|
|
130
|
+
String[] args = getScriptArgs();
|
|
131
|
+
String out = args[0];
|
|
132
|
+
String target = args[1];
|
|
133
|
+
|
|
134
|
+
FunctionManager fm = currentProgram.getFunctionManager();
|
|
135
|
+
Function fn = null;
|
|
136
|
+
if (target.startsWith("0x")) {
|
|
137
|
+
Address addr = currentProgram.getAddressFactory().getAddress(target);
|
|
138
|
+
fn = fm.getFunctionAt(addr);
|
|
139
|
+
if (fn == null) fn = fm.getFunctionContaining(addr);
|
|
140
|
+
} else {
|
|
141
|
+
for (Function f : fm.getFunctions(true)) {
|
|
142
|
+
if (f.getName().equals(target)) { fn = f; break; }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try (FileWriter fw = new FileWriter(out)) {
|
|
147
|
+
if (fn == null) {
|
|
148
|
+
fw.write("{\\"error\\":\\"function not found\\",\\"target\\":" + jsonStr(target) + "}");
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
DecompInterface di = new DecompInterface();
|
|
152
|
+
di.openProgram(currentProgram);
|
|
153
|
+
DecompileResults res = di.decompileFunction(fn, 60, new ConsoleTaskMonitor());
|
|
154
|
+
if (res.decompileCompleted()) {
|
|
155
|
+
String code = res.getDecompiledFunction().getC();
|
|
156
|
+
fw.write("{\\"name\\":" + jsonStr(fn.getName())
|
|
157
|
+
+ ",\\"entry\\":" + jsonStr(hex(fn.getEntryPoint().getOffset()))
|
|
158
|
+
+ ",\\"signature\\":" + jsonStr(fn.getPrototypeString(true, true))
|
|
159
|
+
+ ",\\"decompilation\\":" + jsonStr(code) + "}");
|
|
160
|
+
} else {
|
|
161
|
+
fw.write("{\\"name\\":" + jsonStr(fn.getName())
|
|
162
|
+
+ ",\\"error\\":" + jsonStr(res.getErrorMessage() != null ? res.getErrorMessage() : "decompile failed") + "}");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
`;
|
|
168
|
+
const SCRIPT_XREFS = `// EvrpXrefs.java
|
|
169
|
+
import ghidra.app.script.GhidraScript;
|
|
170
|
+
import ghidra.program.model.address.Address;
|
|
171
|
+
import ghidra.program.model.listing.Function;
|
|
172
|
+
import ghidra.program.model.listing.FunctionManager;
|
|
173
|
+
import ghidra.program.model.symbol.Reference;
|
|
174
|
+
import ghidra.util.task.ConsoleTaskMonitor;
|
|
175
|
+
import java.io.FileWriter;
|
|
176
|
+
import java.util.Set;
|
|
177
|
+
import java.util.TreeSet;
|
|
178
|
+
|
|
179
|
+
public class EvrpXrefs extends GhidraScript {
|
|
180
|
+
${JSON_HELPERS}
|
|
181
|
+
@Override
|
|
182
|
+
public void run() throws Exception {
|
|
183
|
+
String[] args = getScriptArgs();
|
|
184
|
+
String out = args[0];
|
|
185
|
+
String target = args[1];
|
|
186
|
+
|
|
187
|
+
FunctionManager fm = currentProgram.getFunctionManager();
|
|
188
|
+
Function fn = null;
|
|
189
|
+
if (target.startsWith("0x")) {
|
|
190
|
+
Address addr = currentProgram.getAddressFactory().getAddress(target);
|
|
191
|
+
fn = fm.getFunctionAt(addr);
|
|
192
|
+
if (fn == null) fn = fm.getFunctionContaining(addr);
|
|
193
|
+
} else {
|
|
194
|
+
for (Function f : fm.getFunctions(true)) {
|
|
195
|
+
if (f.getName().equals(target)) { fn = f; break; }
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
try (FileWriter fw = new FileWriter(out)) {
|
|
200
|
+
if (fn == null) {
|
|
201
|
+
fw.write("{\\"error\\":\\"function not found\\",\\"target\\":" + jsonStr(target) + "}");
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
Set<String> callers = new TreeSet<>();
|
|
205
|
+
for (Reference ref : currentProgram.getReferenceManager().getReferencesTo(fn.getEntryPoint())) {
|
|
206
|
+
Function cf = fm.getFunctionContaining(ref.getFromAddress());
|
|
207
|
+
if (cf != null) callers.add(cf.getName());
|
|
208
|
+
}
|
|
209
|
+
Set<String> callees = new TreeSet<>();
|
|
210
|
+
for (Function callee : fn.getCalledFunctions(new ConsoleTaskMonitor())) {
|
|
211
|
+
callees.add(callee.getName());
|
|
212
|
+
}
|
|
213
|
+
StringBuilder sb = new StringBuilder();
|
|
214
|
+
sb.append("{\\"name\\":").append(jsonStr(fn.getName()));
|
|
215
|
+
sb.append(",\\"entry\\":").append(jsonStr(hex(fn.getEntryPoint().getOffset())));
|
|
216
|
+
sb.append(",\\"callers\\":[");
|
|
217
|
+
int i = 0;
|
|
218
|
+
for (String c : callers) { if (i > 0) sb.append(","); sb.append(jsonStr(c)); i++; }
|
|
219
|
+
sb.append("],\\"callees\\":[");
|
|
220
|
+
i = 0;
|
|
221
|
+
for (String c : callees) { if (i > 0) sb.append(","); sb.append(jsonStr(c)); i++; }
|
|
222
|
+
sb.append("]}");
|
|
223
|
+
fw.write(sb.toString());
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
`;
|
|
228
|
+
const SCRIPT_FID_MATCHES = `// EvrpFidMatches.java
|
|
229
|
+
import ghidra.app.script.GhidraScript;
|
|
230
|
+
import ghidra.program.model.listing.Function;
|
|
231
|
+
import java.io.FileWriter;
|
|
232
|
+
import java.util.ArrayList;
|
|
233
|
+
import java.util.List;
|
|
234
|
+
|
|
235
|
+
public class EvrpFidMatches extends GhidraScript {
|
|
236
|
+
${JSON_HELPERS}
|
|
237
|
+
@Override
|
|
238
|
+
public void run() throws Exception {
|
|
239
|
+
String[] args = getScriptArgs();
|
|
240
|
+
String out = args[0];
|
|
241
|
+
List<String> recognized = new ArrayList<>();
|
|
242
|
+
int unrecognized = 0;
|
|
243
|
+
for (Function f : currentProgram.getFunctionManager().getFunctions(true)) {
|
|
244
|
+
String name = f.getName();
|
|
245
|
+
if (name.startsWith("FUN_") || name.startsWith("sub_")) { unrecognized++; continue; }
|
|
246
|
+
if (f.isThunk() || f.isExternal()) continue;
|
|
247
|
+
if (recognized.size() < 1000) {
|
|
248
|
+
recognized.add("{\\"name\\":" + jsonStr(name)
|
|
249
|
+
+ ",\\"entry\\":" + jsonStr(hex(f.getEntryPoint().getOffset()))
|
|
250
|
+
+ ",\\"size\\":" + f.getBody().getNumAddresses() + "}");
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
StringBuilder sb = new StringBuilder();
|
|
254
|
+
sb.append("{\\"program\\":").append(jsonStr(currentProgram.getName()));
|
|
255
|
+
sb.append(",\\"recognized_count\\":").append(recognized.size());
|
|
256
|
+
sb.append(",\\"unrecognized_count\\":").append(unrecognized);
|
|
257
|
+
sb.append(",\\"recognized\\":[");
|
|
258
|
+
for (int i = 0; i < recognized.size(); i++) {
|
|
259
|
+
if (i > 0) sb.append(",");
|
|
260
|
+
sb.append(recognized.get(i));
|
|
261
|
+
}
|
|
262
|
+
sb.append("]}");
|
|
263
|
+
try (FileWriter fw = new FileWriter(out)) { fw.write(sb.toString()); }
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
`;
|
|
267
|
+
function ensureScriptDir() {
|
|
268
|
+
if (!existsSync(SCRIPT_DIR))
|
|
269
|
+
mkdirSync(SCRIPT_DIR, { recursive: true });
|
|
270
|
+
return SCRIPT_DIR;
|
|
271
|
+
}
|
|
272
|
+
function ensureProjectDir(name) {
|
|
273
|
+
if (!/^[A-Za-z0-9._-]+$/.test(name)) {
|
|
274
|
+
throw new Error(`bad project name "${name}" — use [A-Za-z0-9._-]+`);
|
|
275
|
+
}
|
|
276
|
+
if (!existsSync(PROJECTS_ROOT))
|
|
277
|
+
mkdirSync(PROJECTS_ROOT, { recursive: true });
|
|
278
|
+
const dir = join(PROJECTS_ROOT, name);
|
|
279
|
+
if (!existsSync(dir))
|
|
280
|
+
mkdirSync(dir, { recursive: true });
|
|
281
|
+
return dir;
|
|
282
|
+
}
|
|
283
|
+
async function runGhidra(options) {
|
|
284
|
+
const scriptDir = ensureScriptDir();
|
|
285
|
+
const scriptPath = join(scriptDir, options.scriptName);
|
|
286
|
+
writeFileSync(scriptPath, options.scriptBody, 'utf8');
|
|
287
|
+
const projectDir = ensureProjectDir(options.project);
|
|
288
|
+
const outFile = join(tmpdir(), `evrp-ghidra-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`);
|
|
289
|
+
const argv = [projectDir, options.project];
|
|
290
|
+
if (options.importBinary) {
|
|
291
|
+
argv.push('-import', options.importBinary, '-overwrite');
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
argv.push('-process', '-noanalysis');
|
|
295
|
+
}
|
|
296
|
+
if (options.readOnly)
|
|
297
|
+
argv.push('-readOnly');
|
|
298
|
+
argv.push('-scriptPath', scriptDir);
|
|
299
|
+
argv.push('-postScript', options.scriptName, outFile, ...options.scriptArgs);
|
|
300
|
+
argv.push('-analysisTimeoutPerFile', '600');
|
|
301
|
+
return await new Promise((resolve, reject) => {
|
|
302
|
+
const start = Date.now();
|
|
303
|
+
const child = spawn(GHIDRA_HEADLESS, argv, {
|
|
304
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
305
|
+
});
|
|
306
|
+
let stdout = '';
|
|
307
|
+
let stderr = '';
|
|
308
|
+
let stdoutBytes = 0;
|
|
309
|
+
let stderrBytes = 0;
|
|
310
|
+
const MAX = 1 * 1024 * 1024;
|
|
311
|
+
child.stdout?.on('data', (b) => {
|
|
312
|
+
if (stdoutBytes < MAX) {
|
|
313
|
+
const room = MAX - stdoutBytes;
|
|
314
|
+
const slice = b.length > room ? b.subarray(0, room) : b;
|
|
315
|
+
stdout += slice.toString();
|
|
316
|
+
stdoutBytes += slice.length;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
child.stderr?.on('data', (b) => {
|
|
320
|
+
if (stderrBytes < MAX) {
|
|
321
|
+
const room = MAX - stderrBytes;
|
|
322
|
+
const slice = b.length > room ? b.subarray(0, room) : b;
|
|
323
|
+
stderr += slice.toString();
|
|
324
|
+
stderrBytes += slice.length;
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
const timer = setTimeout(() => {
|
|
328
|
+
child.kill('SIGTERM');
|
|
329
|
+
setTimeout(() => child.kill('SIGKILL'), 1500);
|
|
330
|
+
}, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
331
|
+
child.on('error', (err) => {
|
|
332
|
+
clearTimeout(timer);
|
|
333
|
+
reject(err);
|
|
334
|
+
});
|
|
335
|
+
child.on('close', (code) => {
|
|
336
|
+
clearTimeout(timer);
|
|
337
|
+
let output = null;
|
|
338
|
+
if (existsSync(outFile)) {
|
|
339
|
+
try {
|
|
340
|
+
output = JSON.parse(readFileSync(outFile, 'utf8'));
|
|
341
|
+
}
|
|
342
|
+
catch (e) {
|
|
343
|
+
output = { error: `failed to parse script output: ${e.message}` };
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
unlinkSync(outFile);
|
|
347
|
+
}
|
|
348
|
+
catch { /* ignore */ }
|
|
349
|
+
}
|
|
350
|
+
resolve({ exitCode: code, stdout, stderr, output, durationMs: Date.now() - start });
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function summarize(stdout, stderr) {
|
|
355
|
+
// analyzeHeadless is loud — extract just the final ERROR/WARN lines so
|
|
356
|
+
// the LLM-visible string isn't dominated by JVM banner text.
|
|
357
|
+
const lines = (stdout + '\n' + stderr).split('\n');
|
|
358
|
+
const interesting = lines.filter((l) => /\b(ERROR|WARN|FATAL|Exception|Traceback)\b/.test(l) ||
|
|
359
|
+
/^Analyzing|^DECOMPILER|^FID/i.test(l));
|
|
360
|
+
return interesting.slice(-20).join('\n');
|
|
361
|
+
}
|
|
362
|
+
function buildGhidraTools() {
|
|
363
|
+
return [
|
|
364
|
+
{
|
|
365
|
+
name: 'ghidra_analyze',
|
|
366
|
+
description: 'Run Ghidra analyzeHeadless against a binary. Creates / overwrites a project under ~/.erosolar/ghidra-projects/<project>/. Subsequent ghidra_decompile / ghidra_xrefs / ghidra_list_functions / ghidra_fid_matches calls reuse this project (no re-analysis). Use after any binary change.',
|
|
367
|
+
parameters: {
|
|
368
|
+
type: 'object',
|
|
369
|
+
properties: {
|
|
370
|
+
binary: { type: 'string', description: 'Absolute path to the binary to analyze' },
|
|
371
|
+
project: { type: 'string', description: 'Project name (alphanum/_-./) — pick one per binary so subsequent reads target the right db' },
|
|
372
|
+
processor: { type: 'string', description: 'Optional Ghidra languageID (e.g. "x86:LE:64:default") to skip auto-detect' },
|
|
373
|
+
timeoutMs: { type: 'number', description: 'Wall-clock cap; default 30min' },
|
|
374
|
+
},
|
|
375
|
+
required: ['binary', 'project'],
|
|
376
|
+
},
|
|
377
|
+
handler: async (args) => {
|
|
378
|
+
const r = await runGhidra({
|
|
379
|
+
project: String(args.project),
|
|
380
|
+
scriptName: 'EvrpListFunctions.java',
|
|
381
|
+
scriptBody: SCRIPT_LIST_FUNCTIONS,
|
|
382
|
+
scriptArgs: [],
|
|
383
|
+
importBinary: String(args.binary),
|
|
384
|
+
timeoutMs: typeof args.timeoutMs === 'number' ? args.timeoutMs : undefined,
|
|
385
|
+
});
|
|
386
|
+
const out = r.output;
|
|
387
|
+
const lines = [
|
|
388
|
+
`analyzed binary=${args.binary} project=${args.project}`,
|
|
389
|
+
`exit=${r.exitCode} duration=${r.durationMs}ms`,
|
|
390
|
+
`program=${out?.program ?? '?'} functions=${out?.functionCount ?? 0}`,
|
|
391
|
+
`project_dir=${join(PROJECTS_ROOT, String(args.project))}`,
|
|
392
|
+
];
|
|
393
|
+
const tail = summarize(r.stdout, r.stderr);
|
|
394
|
+
if (tail)
|
|
395
|
+
lines.push('--- analyzeHeadless tail ---', tail);
|
|
396
|
+
return lines.join('\n');
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
name: 'ghidra_list_functions',
|
|
401
|
+
description: 'List every defined function in an already-analyzed project (name, entry, size, signature, thunk/external flag). Run ghidra_analyze first.',
|
|
402
|
+
parameters: {
|
|
403
|
+
type: 'object',
|
|
404
|
+
properties: {
|
|
405
|
+
project: { type: 'string' },
|
|
406
|
+
},
|
|
407
|
+
required: ['project'],
|
|
408
|
+
},
|
|
409
|
+
handler: async (args) => {
|
|
410
|
+
const r = await runGhidra({
|
|
411
|
+
project: String(args.project),
|
|
412
|
+
scriptName: 'EvrpListFunctions.java',
|
|
413
|
+
scriptBody: SCRIPT_LIST_FUNCTIONS,
|
|
414
|
+
scriptArgs: [],
|
|
415
|
+
readOnly: true,
|
|
416
|
+
});
|
|
417
|
+
if (r.output === null) {
|
|
418
|
+
return `ghidra_list_functions failed (exit ${r.exitCode})\n${summarize(r.stdout, r.stderr)}`;
|
|
419
|
+
}
|
|
420
|
+
return JSON.stringify(r.output);
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
name: 'ghidra_decompile',
|
|
425
|
+
description: 'Decompile one function in an already-analyzed project. Target by name or 0x-address. Returns C pseudocode + signature.',
|
|
426
|
+
parameters: {
|
|
427
|
+
type: 'object',
|
|
428
|
+
properties: {
|
|
429
|
+
project: { type: 'string' },
|
|
430
|
+
target: { type: 'string', description: 'Function name (e.g. "main") or hex address (e.g. "0x401040")' },
|
|
431
|
+
},
|
|
432
|
+
required: ['project', 'target'],
|
|
433
|
+
},
|
|
434
|
+
handler: async (args) => {
|
|
435
|
+
const r = await runGhidra({
|
|
436
|
+
project: String(args.project),
|
|
437
|
+
scriptName: 'EvrpDecompile.java',
|
|
438
|
+
scriptBody: SCRIPT_DECOMPILE,
|
|
439
|
+
scriptArgs: [String(args.target)],
|
|
440
|
+
readOnly: true,
|
|
441
|
+
});
|
|
442
|
+
if (r.output === null) {
|
|
443
|
+
return `ghidra_decompile failed (exit ${r.exitCode})\n${summarize(r.stdout, r.stderr)}`;
|
|
444
|
+
}
|
|
445
|
+
return JSON.stringify(r.output);
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: 'ghidra_xrefs',
|
|
450
|
+
description: 'List callers and callees of one function in an already-analyzed project. Target by name or 0x-address.',
|
|
451
|
+
parameters: {
|
|
452
|
+
type: 'object',
|
|
453
|
+
properties: {
|
|
454
|
+
project: { type: 'string' },
|
|
455
|
+
target: { type: 'string' },
|
|
456
|
+
},
|
|
457
|
+
required: ['project', 'target'],
|
|
458
|
+
},
|
|
459
|
+
handler: async (args) => {
|
|
460
|
+
const r = await runGhidra({
|
|
461
|
+
project: String(args.project),
|
|
462
|
+
scriptName: 'EvrpXrefs.java',
|
|
463
|
+
scriptBody: SCRIPT_XREFS,
|
|
464
|
+
scriptArgs: [String(args.target)],
|
|
465
|
+
readOnly: true,
|
|
466
|
+
});
|
|
467
|
+
if (r.output === null) {
|
|
468
|
+
return `ghidra_xrefs failed (exit ${r.exitCode})\n${summarize(r.stdout, r.stderr)}`;
|
|
469
|
+
}
|
|
470
|
+
return JSON.stringify(r.output);
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
name: 'ghidra_fid_matches',
|
|
475
|
+
description: 'Dump library-function name recognition results from Ghidra FID. Useful for reasoning about library calls inside a stripped binary.',
|
|
476
|
+
parameters: {
|
|
477
|
+
type: 'object',
|
|
478
|
+
properties: {
|
|
479
|
+
project: { type: 'string' },
|
|
480
|
+
},
|
|
481
|
+
required: ['project'],
|
|
482
|
+
},
|
|
483
|
+
handler: async (args) => {
|
|
484
|
+
const r = await runGhidra({
|
|
485
|
+
project: String(args.project),
|
|
486
|
+
scriptName: 'EvrpFidMatches.java',
|
|
487
|
+
scriptBody: SCRIPT_FID_MATCHES,
|
|
488
|
+
scriptArgs: [],
|
|
489
|
+
readOnly: true,
|
|
490
|
+
});
|
|
491
|
+
if (r.output === null) {
|
|
492
|
+
return `ghidra_fid_matches failed (exit ${r.exitCode})\n${summarize(r.stdout, r.stderr)}`;
|
|
493
|
+
}
|
|
494
|
+
return JSON.stringify(r.output);
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
name: 'ghidra_function_diff',
|
|
499
|
+
description: 'Compare two already-analyzed projects at function-set granularity. Returns: only-in-A names, only-in-B names, and signature-changed pairs. For deep semantic diff, decompile each changed function in both projects and compare the C pseudocode.',
|
|
500
|
+
parameters: {
|
|
501
|
+
type: 'object',
|
|
502
|
+
properties: {
|
|
503
|
+
projectA: { type: 'string', description: 'Vulnerable / pre-patch project' },
|
|
504
|
+
projectB: { type: 'string', description: 'Patched project' },
|
|
505
|
+
},
|
|
506
|
+
required: ['projectA', 'projectB'],
|
|
507
|
+
},
|
|
508
|
+
handler: async (args) => {
|
|
509
|
+
const projA = String(args.projectA);
|
|
510
|
+
const projB = String(args.projectB);
|
|
511
|
+
const [rA, rB] = await Promise.all([
|
|
512
|
+
runGhidra({
|
|
513
|
+
project: projA,
|
|
514
|
+
scriptName: 'EvrpListFunctions.java',
|
|
515
|
+
scriptBody: SCRIPT_LIST_FUNCTIONS,
|
|
516
|
+
scriptArgs: [],
|
|
517
|
+
readOnly: true,
|
|
518
|
+
}),
|
|
519
|
+
runGhidra({
|
|
520
|
+
project: projB,
|
|
521
|
+
scriptName: 'EvrpListFunctions.java',
|
|
522
|
+
scriptBody: SCRIPT_LIST_FUNCTIONS,
|
|
523
|
+
scriptArgs: [],
|
|
524
|
+
readOnly: true,
|
|
525
|
+
}),
|
|
526
|
+
]);
|
|
527
|
+
const a = rA.output?.functions ?? [];
|
|
528
|
+
const b = rB.output?.functions ?? [];
|
|
529
|
+
const aMap = new Map(a.map((f) => [f.name, f]));
|
|
530
|
+
const bMap = new Map(b.map((f) => [f.name, f]));
|
|
531
|
+
const onlyInA = [];
|
|
532
|
+
const onlyInB = [];
|
|
533
|
+
const sigChanged = [];
|
|
534
|
+
for (const [name, fa] of aMap) {
|
|
535
|
+
const fb = bMap.get(name);
|
|
536
|
+
if (!fb) {
|
|
537
|
+
onlyInA.push(name);
|
|
538
|
+
}
|
|
539
|
+
else if (fa.signature !== fb.signature) {
|
|
540
|
+
sigChanged.push({ name, a: fa.signature, b: fb.signature });
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
for (const name of bMap.keys()) {
|
|
544
|
+
if (!aMap.has(name))
|
|
545
|
+
onlyInB.push(name);
|
|
546
|
+
}
|
|
547
|
+
return JSON.stringify({
|
|
548
|
+
projectA: projA,
|
|
549
|
+
projectB: projB,
|
|
550
|
+
functionsA: a.length,
|
|
551
|
+
functionsB: b.length,
|
|
552
|
+
onlyInA: onlyInA.slice(0, 200),
|
|
553
|
+
onlyInB: onlyInB.slice(0, 200),
|
|
554
|
+
signatureChanged: sigChanged.slice(0, 200),
|
|
555
|
+
});
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
name: 'ghidra_delete_project',
|
|
560
|
+
description: 'Delete a Ghidra project directory under ~/.erosolar/ghidra-projects/. Use sparingly — projects represent expensive analysis runs.',
|
|
561
|
+
parameters: {
|
|
562
|
+
type: 'object',
|
|
563
|
+
properties: { project: { type: 'string' } },
|
|
564
|
+
required: ['project'],
|
|
565
|
+
},
|
|
566
|
+
handler: async (args) => {
|
|
567
|
+
const dir = join(PROJECTS_ROOT, String(args.project));
|
|
568
|
+
if (!/^[A-Za-z0-9._-]+$/.test(String(args.project))) {
|
|
569
|
+
return `bad project name "${args.project}"`;
|
|
570
|
+
}
|
|
571
|
+
if (!existsSync(dir))
|
|
572
|
+
return `no such project: ${args.project}`;
|
|
573
|
+
rmSync(dir, { recursive: true, force: true });
|
|
574
|
+
return `deleted ${dir}`;
|
|
575
|
+
},
|
|
576
|
+
},
|
|
577
|
+
];
|
|
578
|
+
}
|
|
579
|
+
export class GhidraHeadlessCapabilityModule {
|
|
580
|
+
id = 'capability.ghidraHeadless';
|
|
581
|
+
description = 'Ghidra analyzeHeadless wrappers — ghidra_analyze, ghidra_list_functions, ghidra_decompile, ghidra_xrefs, ghidra_fid_matches, ghidra_function_diff, ghidra_delete_project. Each tool spawns analyzeHeadless once with an embedded Jython post-script; project databases persist under ~/.erosolar/ghidra-projects/.';
|
|
582
|
+
async create(_context) {
|
|
583
|
+
void _context;
|
|
584
|
+
logDebug('[GhidraHeadless] Capability initialized');
|
|
585
|
+
const toolSuite = {
|
|
586
|
+
id: 'ghidraHeadless.tools',
|
|
587
|
+
description: 'Ghidra analyzeHeadless wrappers',
|
|
588
|
+
tools: buildGhidraTools(),
|
|
589
|
+
};
|
|
590
|
+
return { id: this.id, description: this.description, toolSuite };
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
//# sourceMappingURL=ghidraHeadlessCapability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ghidraHeadlessCapability.js","sourceRoot":"","sources":["../../src/capabilities/ghidraHeadlessCapability.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,5 +13,6 @@ export { AflppCapabilityModule } from './aflppCapability.js';
|
|
|
13
13
|
export { GdbCapabilityModule } from './gdbCapability.js';
|
|
14
14
|
export { BinaryAnalysisCapabilityModule } from './binaryAnalysisCapability.js';
|
|
15
15
|
export { PwntoolsCapabilityModule } from './pwntoolsCapability.js';
|
|
16
|
+
export { GhidraHeadlessCapabilityModule } from './ghidraHeadlessCapability.js';
|
|
16
17
|
export { BaseCapabilityModule, type BaseCapabilityOptions, ToolSuiteBuilder, SharedUtilities } from './baseCapability.js';
|
|
17
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,6BAA6B,EAAE,KAAK,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGvI,OAAO,EAAE,0BAA0B,EAAE,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,6BAA6B,EAAE,KAAK,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGvI,OAAO,EAAE,0BAA0B,EAAE,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAI/E,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -15,6 +15,7 @@ export { AflppCapabilityModule } from './aflppCapability.js';
|
|
|
15
15
|
export { GdbCapabilityModule } from './gdbCapability.js';
|
|
16
16
|
export { BinaryAnalysisCapabilityModule } from './binaryAnalysisCapability.js';
|
|
17
17
|
export { PwntoolsCapabilityModule } from './pwntoolsCapability.js';
|
|
18
|
+
export { GhidraHeadlessCapabilityModule } from './ghidraHeadlessCapability.js';
|
|
18
19
|
// CoworkCapabilityModule moved to ~/GitHub/erosolar-cowork (2026-05) —
|
|
19
20
|
// productivity-assistant surface kept separate from the coding CLI.
|
|
20
21
|
// See CLAUDE.md "Capability separation".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,OAAO,EAAE,6BAA6B,EAAE,6BAA6B,EAA6B,MAAM,8BAA8B,CAAC;AAEvI,4BAA4B;AAC5B,OAAO,EAAE,0BAA0B,EAAoC,MAAM,2BAA2B,CAAC;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAA8B,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAgC,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAA6B,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAA8B,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,uEAAuE;AACvE,oEAAoE;AACpE,yCAAyC;AACzC,OAAO,EAAE,oBAAoB,EAA8B,gBAAgB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,OAAO,EAAE,6BAA6B,EAAE,6BAA6B,EAA6B,MAAM,8BAA8B,CAAC;AAEvI,4BAA4B;AAC5B,OAAO,EAAE,0BAA0B,EAAoC,MAAM,2BAA2B,CAAC;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAA8B,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAgC,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAA6B,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAA8B,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,uEAAuE;AACvE,oEAAoE;AACpE,yCAAyC;AACzC,OAAO,EAAE,oBAAoB,EAA8B,gBAAgB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -24,6 +24,8 @@ export interface ApprovalResult {
|
|
|
24
24
|
email: string | null;
|
|
25
25
|
uid: string | null;
|
|
26
26
|
reason?: string;
|
|
27
|
+
revoked?: boolean;
|
|
28
|
+
profilesAllowed?: string[];
|
|
27
29
|
}
|
|
28
30
|
export declare function normalizeEmail(email: string): string;
|
|
29
31
|
/**
|
|
@@ -31,8 +33,16 @@ export declare function normalizeEmail(email: string): string;
|
|
|
31
33
|
* Side-effect free; just reads. Errors are surfaced as `approved: false`
|
|
32
34
|
* with a reason so the caller can decide whether to file a request
|
|
33
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.
|
|
34
44
|
*/
|
|
35
|
-
export declare function checkApproval(): Promise<ApprovalResult>;
|
|
45
|
+
export declare function checkApproval(profile?: string): Promise<ApprovalResult>;
|
|
36
46
|
/**
|
|
37
47
|
* Idempotently write `approval_requests/{uid}` so the admin sees a
|
|
38
48
|
* pending request. Firestore rules let any authenticated user PATCH
|
|
@@ -43,4 +53,22 @@ export declare function requestApproval(): Promise<{
|
|
|
43
53
|
ok: boolean;
|
|
44
54
|
reason?: string;
|
|
45
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
|
+
}>;
|
|
46
74
|
//# sourceMappingURL=userApproval.d.ts.map
|
|
@@ -1 +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;
|
|
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"}
|
|
@@ -24,6 +24,14 @@ const FIRESTORE_BASE = `https://firestore.googleapis.com/v1/projects/${FIREBASE_
|
|
|
24
24
|
export function normalizeEmail(email) {
|
|
25
25
|
return email.trim().toLowerCase();
|
|
26
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
|
+
}
|
|
27
35
|
async function fetchApprovalDoc(email) {
|
|
28
36
|
const idToken = await getValidIdToken();
|
|
29
37
|
const url = `${FIRESTORE_BASE}/approved_users/${encodeURIComponent(email)}`;
|
|
@@ -38,15 +46,25 @@ async function fetchApprovalDoc(email) {
|
|
|
38
46
|
}
|
|
39
47
|
const doc = (await res.json());
|
|
40
48
|
const approved = doc.fields?.['approved']?.booleanValue === true;
|
|
41
|
-
|
|
49
|
+
const revoked = doc.fields?.['revoked']?.booleanValue === true;
|
|
50
|
+
const profilesAllowed = readArrayOfStrings(doc.fields?.['profiles_allowed']);
|
|
51
|
+
return { approved, revoked, profilesAllowed };
|
|
42
52
|
}
|
|
43
53
|
/**
|
|
44
54
|
* Verify the currently-signed-in user is on the approved list.
|
|
45
55
|
* Side-effect free; just reads. Errors are surfaced as `approved: false`
|
|
46
56
|
* with a reason so the caller can decide whether to file a request
|
|
47
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.
|
|
48
66
|
*/
|
|
49
|
-
export async function checkApproval() {
|
|
67
|
+
export async function checkApproval(profile) {
|
|
50
68
|
const status = getAuthStatus();
|
|
51
69
|
if (!status.authenticated) {
|
|
52
70
|
return { approved: false, email: null, uid: null, reason: 'not signed in' };
|
|
@@ -58,9 +76,35 @@ export async function checkApproval() {
|
|
|
58
76
|
}
|
|
59
77
|
try {
|
|
60
78
|
const doc = await fetchApprovalDoc(email);
|
|
61
|
-
if (doc
|
|
62
|
-
return { approved:
|
|
63
|
-
|
|
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 };
|
|
64
108
|
}
|
|
65
109
|
catch (err) {
|
|
66
110
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -104,4 +148,47 @@ export async function requestApproval() {
|
|
|
104
148
|
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
105
149
|
}
|
|
106
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
|
+
}
|
|
107
194
|
//# sourceMappingURL=userApproval.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userApproval.js","sourceRoot":"","sources":["../../src/core/userApproval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEhF,MAAM,cAAc,GAAG,gDAAgD,mBAAmB,gCAAgC,CAAC;
|
|
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.27",
|
|
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
|
],
|