opensoma 0.8.0 → 0.9.0
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/dist/package.json +1 -3
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +6 -6
- package/dist/src/client.js.map +1 -1
- package/dist/src/commands/auth.d.ts +1 -11
- package/dist/src/commands/auth.d.ts.map +1 -1
- package/dist/src/commands/auth.js +4 -81
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/helpers.d.ts +1 -5
- package/dist/src/commands/helpers.d.ts.map +1 -1
- package/dist/src/commands/helpers.js +4 -32
- package/dist/src/commands/helpers.js.map +1 -1
- package/dist/src/commands/team.js +1 -1
- package/dist/src/commands/team.js.map +1 -1
- package/dist/src/errors.d.ts +0 -4
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +1 -5
- package/dist/src/errors.js.map +1 -1
- package/package.json +1 -3
- package/src/client.test.ts +55 -4
- package/src/client.ts +7 -8
- package/src/commands/auth.test.ts +6 -98
- package/src/commands/auth.ts +2 -115
- package/src/commands/helpers.test.ts +5 -116
- package/src/commands/helpers.ts +3 -35
- package/src/commands/team.ts +1 -1
- package/src/errors.ts +1 -5
- package/dist/src/token-extractor.d.ts +0 -43
- package/dist/src/token-extractor.d.ts.map +0 -1
- package/dist/src/token-extractor.js +0 -302
- package/dist/src/token-extractor.js.map +0 -1
- package/src/token-extractor.test.ts +0 -220
- package/src/token-extractor.ts +0 -392
package/src/commands/helpers.ts
CHANGED
|
@@ -1,42 +1,29 @@
|
|
|
1
1
|
import { CredentialManager } from '../credential-manager'
|
|
2
2
|
import { SomaHttp } from '../http'
|
|
3
3
|
import { recoverSession } from '../session-recovery'
|
|
4
|
-
import * as stderr from '../shared/utils/stderr'
|
|
5
4
|
import type { Credentials } from '../types'
|
|
6
5
|
|
|
7
6
|
type CredentialStore = Pick<CredentialManager, 'clearSessionState' | 'getCredentials' | 'setCredentials'>
|
|
8
7
|
type AuthenticatedHttp = Pick<SomaHttp, 'checkLogin'>
|
|
9
8
|
type ReloginHttp = Pick<SomaHttp, 'checkLogin' | 'getCsrfToken' | 'getSessionCookie' | 'login'>
|
|
10
|
-
type BrowserExtractor = () => Promise<{ csrfToken: string; sessionCookie: string } | null>
|
|
11
9
|
|
|
12
|
-
const NOT_LOGGED_IN_MESSAGE = 'Not logged in. Run: opensoma auth login
|
|
13
|
-
const STALE_SESSION_MESSAGE =
|
|
14
|
-
'Session expired. Run: opensoma auth login or opensoma auth extract (saved id/password were preserved)'
|
|
10
|
+
const NOT_LOGGED_IN_MESSAGE = 'Not logged in. Run: opensoma auth login'
|
|
11
|
+
const STALE_SESSION_MESSAGE = 'Session expired. Run: opensoma auth login (saved id/password were preserved)'
|
|
15
12
|
|
|
16
13
|
function defaultCreateHttp(credentials: Credentials): SomaHttp {
|
|
17
14
|
return new SomaHttp({ sessionCookie: credentials.sessionCookie, csrfToken: credentials.csrfToken })
|
|
18
15
|
}
|
|
19
16
|
|
|
20
|
-
async function defaultExtractBrowserCredentials(): Promise<{ csrfToken: string; sessionCookie: string } | null> {
|
|
21
|
-
const { TokenExtractor } = await import('../token-extractor')
|
|
22
|
-
const { resolveExtractedCredentials } = await import('./auth')
|
|
23
|
-
const candidates = await new TokenExtractor().extractCandidates()
|
|
24
|
-
if (candidates.length === 0) return null
|
|
25
|
-
return resolveExtractedCredentials(candidates)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
17
|
export function createAuthenticatedHttp(): Promise<SomaHttp>
|
|
29
18
|
export function createAuthenticatedHttp<T extends AuthenticatedHttp>(
|
|
30
19
|
manager: CredentialStore,
|
|
31
20
|
createHttp: (credentials: Credentials) => T,
|
|
32
21
|
createReloginHttp?: () => ReloginHttp,
|
|
33
|
-
recoverViaBrowser?: BrowserExtractor,
|
|
34
22
|
): Promise<T>
|
|
35
23
|
export async function createAuthenticatedHttp<T extends AuthenticatedHttp>(
|
|
36
24
|
manager: CredentialStore = new CredentialManager(),
|
|
37
25
|
createHttp?: (credentials: Credentials) => T,
|
|
38
26
|
createReloginHttp: () => ReloginHttp = () => new SomaHttp(),
|
|
39
|
-
recoverViaBrowser: BrowserExtractor = defaultExtractBrowserCredentials,
|
|
40
27
|
): Promise<SomaHttp | T> {
|
|
41
28
|
const creds = await manager.getCredentials()
|
|
42
29
|
if (!creds) {
|
|
@@ -52,26 +39,7 @@ export async function createAuthenticatedHttp<T extends AuthenticatedHttp>(
|
|
|
52
39
|
if (refreshedCredentials) {
|
|
53
40
|
return createHttp ? createHttp(refreshedCredentials) : defaultCreateHttp(refreshedCredentials)
|
|
54
41
|
}
|
|
55
|
-
} catch {
|
|
56
|
-
// Password recovery failed — try browser extraction next
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
try {
|
|
60
|
-
stderr.info('Session expired. Attempting browser token extraction...')
|
|
61
|
-
const extracted = await recoverViaBrowser()
|
|
62
|
-
if (extracted) {
|
|
63
|
-
const browserCredentials: Credentials = {
|
|
64
|
-
sessionCookie: extracted.sessionCookie,
|
|
65
|
-
csrfToken: extracted.csrfToken,
|
|
66
|
-
loggedInAt: new Date().toISOString(),
|
|
67
|
-
}
|
|
68
|
-
await manager.setCredentials(browserCredentials)
|
|
69
|
-
stderr.info('Browser token extraction successful.')
|
|
70
|
-
return createHttp ? createHttp(browserCredentials) : defaultCreateHttp(browserCredentials)
|
|
71
|
-
}
|
|
72
|
-
} catch {
|
|
73
|
-
// Browser extraction also failed
|
|
74
|
-
}
|
|
42
|
+
} catch {}
|
|
75
43
|
|
|
76
44
|
await manager.clearSessionState()
|
|
77
45
|
throw new Error(STALE_SESSION_MESSAGE)
|
package/src/commands/team.ts
CHANGED
|
@@ -49,7 +49,7 @@ async function runTeamAction(params: {
|
|
|
49
49
|
try {
|
|
50
50
|
const http = await getHttpOrExit()
|
|
51
51
|
const user = await http.checkLogin()
|
|
52
|
-
if (!user) throw new Error('Not logged in. Run: opensoma auth login
|
|
52
|
+
if (!user) throw new Error('Not logged in. Run: opensoma auth login')
|
|
53
53
|
if (!user.userNo) throw new Error('현재 사용자의 userNo를 확인할 수 없습니다.')
|
|
54
54
|
|
|
55
55
|
const response = await http.postJson<{ resultCode?: string }>(
|
package/src/errors.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error thrown when authentication is required but not valid.
|
|
3
|
-
* Provides a clear message indicating the need to authenticate.
|
|
4
|
-
*/
|
|
5
1
|
export class AuthenticationError extends Error {
|
|
6
|
-
constructor(message = 'Authentication required. Please login with: opensoma auth login
|
|
2
|
+
constructor(message = 'Authentication required. Please login with: opensoma auth login') {
|
|
7
3
|
super(message)
|
|
8
4
|
this.name = 'AuthenticationError'
|
|
9
5
|
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
type BrowserConfig = {
|
|
2
|
-
name: string;
|
|
3
|
-
macPath: string;
|
|
4
|
-
linuxPath: string;
|
|
5
|
-
keychainService: string;
|
|
6
|
-
keychainAccount: string;
|
|
7
|
-
};
|
|
8
|
-
export interface ExtractedSessionCandidate {
|
|
9
|
-
browser: string;
|
|
10
|
-
lastAccessUtc: number;
|
|
11
|
-
profile: string;
|
|
12
|
-
sessionCookie: string;
|
|
13
|
-
}
|
|
14
|
-
export declare const BROWSERS: BrowserConfig[];
|
|
15
|
-
export type TokenExtractorOptions = {
|
|
16
|
-
platform?: NodeJS.Platform;
|
|
17
|
-
homeDirectory?: string;
|
|
18
|
-
debug?: boolean;
|
|
19
|
-
};
|
|
20
|
-
export declare class TokenExtractor {
|
|
21
|
-
private readonly platform;
|
|
22
|
-
private readonly homeDirectory;
|
|
23
|
-
private readonly debugEnabled;
|
|
24
|
-
constructor(options?: TokenExtractorOptions);
|
|
25
|
-
constructor(platform?: NodeJS.Platform, homeDirectory?: string, debug?: boolean);
|
|
26
|
-
private log;
|
|
27
|
-
extract(): Promise<{
|
|
28
|
-
sessionCookie: string;
|
|
29
|
-
} | null>;
|
|
30
|
-
extractCandidates(): Promise<ExtractedSessionCandidate[]>;
|
|
31
|
-
findCookieDatabases(): string[];
|
|
32
|
-
private decryptCookie;
|
|
33
|
-
private getMacOSEncryptionKey;
|
|
34
|
-
private decryptChromiumValue;
|
|
35
|
-
private getBrowserByPath;
|
|
36
|
-
private addCandidate;
|
|
37
|
-
private findBrowserCookieDatabases;
|
|
38
|
-
private getBrowserRoot;
|
|
39
|
-
private isSupportedProfileDirectory;
|
|
40
|
-
private normalizeLastAccessUtc;
|
|
41
|
-
}
|
|
42
|
-
export {};
|
|
43
|
-
//# sourceMappingURL=token-extractor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"token-extractor.d.ts","sourceRoot":"","sources":["../../src/token-extractor.ts"],"names":[],"mappings":"AAeA,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAQD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,eAAO,MAAM,QAAQ,EAAE,aAAa,EA2CnC,CAAA;AA+CD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,OAAO,CAAC,EAAE,qBAAqB;gBAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;IAa/E,OAAO,CAAC,GAAG;IAML,OAAO,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAWpD,iBAAiB,IAAI,OAAO,CAAC,yBAAyB,EAAE,CAAC;IAsE/D,mBAAmB,IAAI,MAAM,EAAE;YAQjB,aAAa;YAqBb,qBAAqB;IAanC,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,0BAA0B;IAmBlC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,sBAAsB;CAO/B"}
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import { createDecipheriv, pbkdf2Sync } from 'node:crypto';
|
|
3
|
-
import { copyFileSync, existsSync, mkdtempSync, readdirSync, rmSync } from 'node:fs';
|
|
4
|
-
import { createRequire } from 'node:module';
|
|
5
|
-
import { homedir, tmpdir } from 'node:os';
|
|
6
|
-
import { basename, dirname, join } from 'node:path';
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
const COOKIE_QUERY = "SELECT encrypted_value, last_access_utc, value FROM cookies WHERE (host_key LIKE '%swmaestro.ai' OR host_key LIKE '%opensoma.dev') AND name = 'JSESSIONID' ORDER BY last_access_utc DESC LIMIT 1";
|
|
9
|
-
const CHROMIUM_SALT = 'saltysalt';
|
|
10
|
-
const CHROMIUM_IV = Buffer.alloc(16, 0x20);
|
|
11
|
-
const PROFILE_DIR_PATTERN = /^Profile\s+\d+$/;
|
|
12
|
-
export const BROWSERS = [
|
|
13
|
-
{
|
|
14
|
-
name: 'Chrome',
|
|
15
|
-
macPath: 'Google Chrome',
|
|
16
|
-
linuxPath: 'google-chrome',
|
|
17
|
-
keychainService: 'Chrome Safe Storage',
|
|
18
|
-
keychainAccount: 'Chrome',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: 'Edge',
|
|
22
|
-
macPath: 'Microsoft Edge',
|
|
23
|
-
linuxPath: 'microsoft-edge',
|
|
24
|
-
keychainService: 'Microsoft Edge Safe Storage',
|
|
25
|
-
keychainAccount: 'Microsoft Edge',
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'Brave',
|
|
29
|
-
macPath: 'BraveSoftware/Brave-Browser',
|
|
30
|
-
linuxPath: 'BraveSoftware/Brave-Browser',
|
|
31
|
-
keychainService: 'Brave Safe Storage',
|
|
32
|
-
keychainAccount: 'Brave',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
name: 'Arc',
|
|
36
|
-
macPath: join('Arc', 'User Data'),
|
|
37
|
-
linuxPath: join('Arc', 'User Data'),
|
|
38
|
-
keychainService: 'Arc Safe Storage',
|
|
39
|
-
keychainAccount: 'Arc',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'Vivaldi',
|
|
43
|
-
macPath: 'Vivaldi',
|
|
44
|
-
linuxPath: 'Vivaldi',
|
|
45
|
-
keychainService: 'Vivaldi Safe Storage',
|
|
46
|
-
keychainAccount: 'Vivaldi',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: 'Chromium',
|
|
50
|
-
macPath: 'Chromium',
|
|
51
|
-
linuxPath: 'Chromium',
|
|
52
|
-
keychainService: 'Chromium Safe Storage',
|
|
53
|
-
keychainAccount: 'Chromium',
|
|
54
|
-
},
|
|
55
|
-
];
|
|
56
|
-
function queryCookieDb(dbPath) {
|
|
57
|
-
if (typeof globalThis.Bun !== 'undefined') {
|
|
58
|
-
const { Database } = require('bun:sqlite');
|
|
59
|
-
const db = new Database(dbPath, { readonly: true });
|
|
60
|
-
try {
|
|
61
|
-
const row = db.query(COOKIE_QUERY).get();
|
|
62
|
-
return row ?? undefined;
|
|
63
|
-
}
|
|
64
|
-
finally {
|
|
65
|
-
db.close();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
try {
|
|
69
|
-
const Database = require('better-sqlite3');
|
|
70
|
-
const db = new Database(dbPath, { readonly: true });
|
|
71
|
-
try {
|
|
72
|
-
return db.prepare(COOKIE_QUERY).get() ?? undefined;
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
db.close();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
const { DatabaseSync } = require('node:sqlite');
|
|
80
|
-
const db = new DatabaseSync(dbPath, { readonly: true });
|
|
81
|
-
try {
|
|
82
|
-
return db.prepare(COOKIE_QUERY).get() ?? undefined;
|
|
83
|
-
}
|
|
84
|
-
finally {
|
|
85
|
-
db.close();
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
export class TokenExtractor {
|
|
90
|
-
platform;
|
|
91
|
-
homeDirectory;
|
|
92
|
-
debugEnabled;
|
|
93
|
-
constructor(platformOrOptions, homeDirectory, debug) {
|
|
94
|
-
if (typeof platformOrOptions === 'object' && platformOrOptions !== null) {
|
|
95
|
-
this.platform = platformOrOptions.platform ?? process.platform;
|
|
96
|
-
this.homeDirectory = platformOrOptions.homeDirectory ?? homedir();
|
|
97
|
-
this.debugEnabled = platformOrOptions.debug ?? false;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
this.platform = platformOrOptions ?? process.platform;
|
|
101
|
-
this.homeDirectory = homeDirectory ?? homedir();
|
|
102
|
-
this.debugEnabled = debug ?? false;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
log(...args) {
|
|
106
|
-
if (!this.debugEnabled)
|
|
107
|
-
return;
|
|
108
|
-
const message = args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ');
|
|
109
|
-
process.stderr.write(`[extract] ${message}\n`);
|
|
110
|
-
}
|
|
111
|
-
async extract() {
|
|
112
|
-
const candidates = await this.extractCandidates();
|
|
113
|
-
const firstCandidate = candidates[0];
|
|
114
|
-
if (!firstCandidate) {
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
return { sessionCookie: firstCandidate.sessionCookie };
|
|
118
|
-
}
|
|
119
|
-
async extractCandidates() {
|
|
120
|
-
const candidates = new Map();
|
|
121
|
-
const cookieDatabases = this.findCookieDatabases();
|
|
122
|
-
this.log(`Found ${cookieDatabases.length} cookie database(s)`);
|
|
123
|
-
for (const databasePath of cookieDatabases) {
|
|
124
|
-
const browser = this.getBrowserByPath(databasePath);
|
|
125
|
-
if (!browser) {
|
|
126
|
-
this.log(`Skipping ${databasePath} (no matching browser config)`);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
const profile = basename(dirname(databasePath));
|
|
130
|
-
this.log(`Processing ${browser.name} / ${profile}`);
|
|
131
|
-
const tempDirectory = mkdtempSync(join(tmpdir(), 'opensoma-cookie-db-'));
|
|
132
|
-
const tempDatabasePath = join(tempDirectory, 'Cookies');
|
|
133
|
-
try {
|
|
134
|
-
copySqliteDatabase(databasePath, tempDatabasePath);
|
|
135
|
-
this.log(` Copied DB to ${tempDatabasePath}`);
|
|
136
|
-
const row = queryCookieDb(tempDatabasePath);
|
|
137
|
-
if (!row) {
|
|
138
|
-
this.log(' No JSESSIONID cookie found');
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
const plaintextValue = normalizeCookieText(row.value);
|
|
142
|
-
if (plaintextValue) {
|
|
143
|
-
this.log(` Found plaintext cookie (${plaintextValue.length} chars)`);
|
|
144
|
-
this.addCandidate(candidates, {
|
|
145
|
-
browser: browser.name,
|
|
146
|
-
lastAccessUtc: this.normalizeLastAccessUtc(row.last_access_utc),
|
|
147
|
-
profile,
|
|
148
|
-
sessionCookie: plaintextValue,
|
|
149
|
-
});
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
const encryptedValue = normalizeCookieBytes(row.encrypted_value);
|
|
153
|
-
if (!encryptedValue || encryptedValue.length === 0) {
|
|
154
|
-
this.log(' No plaintext or encrypted value');
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
this.log(` Decrypting encrypted cookie (${encryptedValue.length} bytes)...`);
|
|
158
|
-
const decryptedValue = await this.decryptCookie(encryptedValue, browser.name);
|
|
159
|
-
if (decryptedValue) {
|
|
160
|
-
this.log(` Decrypted successfully (${decryptedValue.length} chars)`);
|
|
161
|
-
this.addCandidate(candidates, {
|
|
162
|
-
browser: browser.name,
|
|
163
|
-
lastAccessUtc: this.normalizeLastAccessUtc(row.last_access_utc),
|
|
164
|
-
profile,
|
|
165
|
-
sessionCookie: decryptedValue,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
this.log(' Decryption returned empty value');
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
catch (error) {
|
|
173
|
-
this.log(` Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
174
|
-
}
|
|
175
|
-
finally {
|
|
176
|
-
rmSync(tempDirectory, { recursive: true, force: true });
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
this.log(`Total unique candidates: ${candidates.size}`);
|
|
180
|
-
return [...candidates.values()].sort((left, right) => right.lastAccessUtc - left.lastAccessUtc);
|
|
181
|
-
}
|
|
182
|
-
findCookieDatabases() {
|
|
183
|
-
const results = BROWSERS.flatMap((browser) => this.findBrowserCookieDatabases(browser));
|
|
184
|
-
if (results.length === 0) {
|
|
185
|
-
this.log('No cookie databases found. Searched browsers:', BROWSERS.map((b) => b.name).join(', '));
|
|
186
|
-
}
|
|
187
|
-
return results;
|
|
188
|
-
}
|
|
189
|
-
async decryptCookie(encryptedValue, browserName) {
|
|
190
|
-
if (encryptedValue.length === 0) {
|
|
191
|
-
return '';
|
|
192
|
-
}
|
|
193
|
-
if (this.platform === 'linux') {
|
|
194
|
-
this.log(' Using Linux PBKDF2 decryption');
|
|
195
|
-
return this.decryptChromiumValue(encryptedValue, pbkdf2Sync('peanuts', CHROMIUM_SALT, 1, 16, 'sha1'));
|
|
196
|
-
}
|
|
197
|
-
if (this.platform === 'darwin') {
|
|
198
|
-
this.log(` Fetching macOS Keychain key for ${browserName}...`);
|
|
199
|
-
const key = await this.getMacOSEncryptionKey(browserName);
|
|
200
|
-
this.log(' Keychain key obtained');
|
|
201
|
-
return this.decryptChromiumValue(encryptedValue, key);
|
|
202
|
-
}
|
|
203
|
-
this.log(` Unsupported platform for decryption: ${this.platform}`);
|
|
204
|
-
return '';
|
|
205
|
-
}
|
|
206
|
-
async getMacOSEncryptionKey(browserName) {
|
|
207
|
-
const browser = BROWSERS.find((entry) => entry.name === browserName);
|
|
208
|
-
if (!browser) {
|
|
209
|
-
throw new Error(`Unsupported browser: ${browserName}`);
|
|
210
|
-
}
|
|
211
|
-
const command = `security find-generic-password -s ${JSON.stringify(browser.keychainService)} -a ${JSON.stringify(browser.keychainAccount)} -w`;
|
|
212
|
-
this.log(` Keychain command: ${command}`);
|
|
213
|
-
const password = execSync(command, { encoding: 'utf8' }).trimEnd();
|
|
214
|
-
return pbkdf2Sync(password, CHROMIUM_SALT, 1003, 16, 'sha1');
|
|
215
|
-
}
|
|
216
|
-
decryptChromiumValue(encryptedValue, key) {
|
|
217
|
-
const encryptedPayload = encryptedValue.subarray(0, 3).toString('utf8') === 'v10' ? encryptedValue.subarray(3) : encryptedValue;
|
|
218
|
-
const decipher = createDecipheriv('aes-128-cbc', key, CHROMIUM_IV);
|
|
219
|
-
decipher.setAutoPadding(true);
|
|
220
|
-
const decrypted = Buffer.concat([decipher.update(encryptedPayload), decipher.final()]);
|
|
221
|
-
// Chromium v130+ prepends a 32-byte integrity hash before the actual cookie value
|
|
222
|
-
if (decrypted.length > 32) {
|
|
223
|
-
const hasNonPrintablePrefix = decrypted.subarray(0, 32).some((b) => b < 0x20 || b > 0x7e);
|
|
224
|
-
if (hasNonPrintablePrefix) {
|
|
225
|
-
return decrypted.subarray(32).toString('utf8');
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return decrypted.toString('utf8');
|
|
229
|
-
}
|
|
230
|
-
getBrowserByPath(databasePath) {
|
|
231
|
-
return BROWSERS.find((browser) => databasePath.includes(`${browser.macPath}/`) || databasePath.includes(`${browser.linuxPath}/`));
|
|
232
|
-
}
|
|
233
|
-
addCandidate(candidates, candidate) {
|
|
234
|
-
const existing = candidates.get(candidate.sessionCookie);
|
|
235
|
-
if (!existing || existing.lastAccessUtc < candidate.lastAccessUtc) {
|
|
236
|
-
candidates.set(candidate.sessionCookie, candidate);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
findBrowserCookieDatabases(browser) {
|
|
240
|
-
const browserRoot = this.getBrowserRoot(browser);
|
|
241
|
-
if (!browserRoot || !existsSync(browserRoot)) {
|
|
242
|
-
this.log(`${browser.name}: not found at ${browserRoot ?? '(unsupported platform)'}`);
|
|
243
|
-
return [];
|
|
244
|
-
}
|
|
245
|
-
const profiles = readdirSync(browserRoot, { withFileTypes: true })
|
|
246
|
-
.filter((entry) => entry.isDirectory() && this.isSupportedProfileDirectory(entry.name))
|
|
247
|
-
.sort((left, right) => left.name.localeCompare(right.name));
|
|
248
|
-
const databases = profiles
|
|
249
|
-
.map((entry) => join(browserRoot, entry.name, 'Cookies'))
|
|
250
|
-
.filter((databasePath) => existsSync(databasePath));
|
|
251
|
-
this.log(`${browser.name}: ${profiles.length} profile(s), ${databases.length} cookie DB(s)`);
|
|
252
|
-
return databases;
|
|
253
|
-
}
|
|
254
|
-
getBrowserRoot(browser) {
|
|
255
|
-
if (this.platform === 'darwin') {
|
|
256
|
-
return join(this.homeDirectory, 'Library', 'Application Support', browser.macPath);
|
|
257
|
-
}
|
|
258
|
-
if (this.platform === 'linux') {
|
|
259
|
-
return join(this.homeDirectory, '.config', browser.linuxPath);
|
|
260
|
-
}
|
|
261
|
-
return null;
|
|
262
|
-
}
|
|
263
|
-
isSupportedProfileDirectory(profileName) {
|
|
264
|
-
return profileName === 'Default' || PROFILE_DIR_PATTERN.test(profileName);
|
|
265
|
-
}
|
|
266
|
-
normalizeLastAccessUtc(lastAccessUtc) {
|
|
267
|
-
if (typeof lastAccessUtc === 'bigint') {
|
|
268
|
-
return Number(lastAccessUtc);
|
|
269
|
-
}
|
|
270
|
-
return typeof lastAccessUtc === 'number' ? lastAccessUtc : 0;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
function copySqliteDatabase(sourcePath, targetPath) {
|
|
274
|
-
copyFileSync(sourcePath, targetPath);
|
|
275
|
-
for (const suffix of ['-wal', '-shm']) {
|
|
276
|
-
const sidecarSourcePath = `${sourcePath}${suffix}`;
|
|
277
|
-
if (!existsSync(sidecarSourcePath)) {
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
copyFileSync(sidecarSourcePath, `${targetPath}${suffix}`);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
function normalizeCookieBytes(value) {
|
|
284
|
-
if (!value) {
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
if (Buffer.isBuffer(value)) {
|
|
288
|
-
return value;
|
|
289
|
-
}
|
|
290
|
-
if (value instanceof Uint8Array) {
|
|
291
|
-
return Buffer.from(value);
|
|
292
|
-
}
|
|
293
|
-
return Buffer.from(value);
|
|
294
|
-
}
|
|
295
|
-
function normalizeCookieText(value) {
|
|
296
|
-
if (typeof value === 'string') {
|
|
297
|
-
return value.trim();
|
|
298
|
-
}
|
|
299
|
-
const bytes = normalizeCookieBytes(value);
|
|
300
|
-
return bytes ? bytes.toString('utf8').trim() : '';
|
|
301
|
-
}
|
|
302
|
-
//# sourceMappingURL=token-extractor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"token-extractor.js","sourceRoot":"","sources":["../../src/token-extractor.ts"],"names":[],"mappings":"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"}
|