@apitap/core 1.4.0 → 1.4.2
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 +4 -2
- package/dist/auth/crypto.d.ts +10 -0
- package/dist/auth/crypto.js +30 -6
- package/dist/auth/crypto.js.map +1 -1
- package/dist/auth/handoff.js +20 -1
- package/dist/auth/handoff.js.map +1 -1
- package/dist/auth/manager.d.ts +1 -0
- package/dist/auth/manager.js +35 -9
- package/dist/auth/manager.js.map +1 -1
- package/dist/capture/monitor.js +4 -0
- package/dist/capture/monitor.js.map +1 -1
- package/dist/capture/scrubber.js +10 -0
- package/dist/capture/scrubber.js.map +1 -1
- package/dist/capture/session.js +7 -17
- package/dist/capture/session.js.map +1 -1
- package/dist/cli.js +74 -17
- package/dist/cli.js.map +1 -1
- package/dist/discovery/fetch.js +3 -3
- package/dist/discovery/fetch.js.map +1 -1
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +59 -33
- package/dist/mcp.js.map +1 -1
- package/dist/native-host.js +2 -2
- package/dist/native-host.js.map +1 -1
- package/dist/orchestration/browse.js +13 -4
- package/dist/orchestration/browse.js.map +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +14 -4
- package/dist/plugin.js.map +1 -1
- package/dist/read/decoders/reddit.js +4 -0
- package/dist/read/decoders/reddit.js.map +1 -1
- package/dist/replay/engine.js +60 -17
- package/dist/replay/engine.js.map +1 -1
- package/dist/serve.d.ts +2 -0
- package/dist/serve.js +8 -1
- package/dist/serve.js.map +1 -1
- package/dist/skill/generator.d.ts +5 -0
- package/dist/skill/generator.js +30 -4
- package/dist/skill/generator.js.map +1 -1
- package/dist/skill/search.js +1 -1
- package/dist/skill/search.js.map +1 -1
- package/dist/skill/signing.js +19 -1
- package/dist/skill/signing.js.map +1 -1
- package/dist/skill/ssrf.js +71 -2
- package/dist/skill/ssrf.js.map +1 -1
- package/dist/skill/store.d.ts +2 -0
- package/dist/skill/store.js +23 -10
- package/dist/skill/store.js.map +1 -1
- package/dist/skill/validate.d.ts +10 -0
- package/dist/skill/validate.js +106 -0
- package/dist/skill/validate.js.map +1 -0
- package/package.json +1 -1
- package/src/auth/crypto.ts +14 -6
- package/src/auth/handoff.ts +19 -1
- package/src/auth/manager.ts +22 -5
- package/src/capture/monitor.ts +4 -0
- package/src/capture/scrubber.ts +12 -0
- package/src/capture/session.ts +5 -14
- package/src/cli.ts +215 -12
- package/src/discovery/fetch.ts +2 -2
- package/src/index/reader.ts +65 -0
- package/src/mcp.ts +64 -31
- package/src/native-host.ts +29 -2
- package/src/orchestration/browse.ts +13 -4
- package/src/plugin.ts +17 -5
- package/src/read/decoders/reddit.ts +3 -3
- package/src/replay/engine.ts +65 -15
- package/src/serve.ts +10 -1
- package/src/skill/generator.ts +32 -4
- package/src/skill/search.ts +1 -1
- package/src/skill/signing.ts +20 -1
- package/src/skill/ssrf.ts +69 -2
- package/src/skill/store.ts +29 -11
- package/src/skill/validate.ts +48 -0
package/dist/skill/ssrf.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../../src/skill/ssrf.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../../src/skill/ssrf.ts"],"names":[],"mappings":"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"}
|
package/dist/skill/store.d.ts
CHANGED
|
@@ -3,5 +3,7 @@ export declare function writeSkillFile(skill: SkillFile, skillsDir?: string): Pr
|
|
|
3
3
|
export declare function readSkillFile(domain: string, skillsDir?: string, options?: {
|
|
4
4
|
verifySignature?: boolean;
|
|
5
5
|
signingKey?: Buffer;
|
|
6
|
+
/** Allow loading unsigned files without throwing. Tampered signed files still reject. */
|
|
7
|
+
trustUnsigned?: boolean;
|
|
6
8
|
}): Promise<SkillFile | null>;
|
|
7
9
|
export declare function listSkillFiles(skillsDir?: string): Promise<SkillSummary[]>;
|
package/dist/skill/store.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { readFile, writeFile, mkdir, readdir, access } from 'node:fs/promises';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
|
+
import { validateSkillFile } from './validate.js';
|
|
5
6
|
const DEFAULT_SKILLS_DIR = join(homedir(), '.apitap', 'skills');
|
|
6
7
|
const BASE_GITIGNORE = `# ApiTap — prevent accidental credential commits
|
|
7
8
|
auth.enc
|
|
@@ -27,7 +28,7 @@ async function ensureGitignore(skillsDir) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
export async function writeSkillFile(skill, skillsDir = DEFAULT_SKILLS_DIR) {
|
|
30
|
-
await mkdir(skillsDir, { recursive: true });
|
|
31
|
+
await mkdir(skillsDir, { recursive: true, mode: 0o700 });
|
|
31
32
|
await ensureGitignore(skillsDir);
|
|
32
33
|
const filePath = skillPath(skill.domain, skillsDir);
|
|
33
34
|
await writeFile(filePath, JSON.stringify(skill, null, 2) + '\n', { mode: 0o600 });
|
|
@@ -38,20 +39,32 @@ export async function readSkillFile(domain, skillsDir = DEFAULT_SKILLS_DIR, opti
|
|
|
38
39
|
const path = skillPath(domain, skillsDir);
|
|
39
40
|
try {
|
|
40
41
|
const content = await readFile(path, 'utf-8');
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const raw = JSON.parse(content);
|
|
43
|
+
const skill = validateSkillFile(raw);
|
|
44
|
+
// Signature verification is ON by default (H1 fix)
|
|
45
|
+
const shouldVerify = options?.verifySignature !== false;
|
|
46
|
+
if (shouldVerify) {
|
|
47
|
+
// Auto-derive signing key if not provided
|
|
48
|
+
let signingKey = options?.signingKey;
|
|
49
|
+
if (!signingKey) {
|
|
50
|
+
const { deriveSigningKey } = await import('../auth/crypto.js');
|
|
51
|
+
const { getMachineId } = await import('../auth/manager.js');
|
|
52
|
+
const machineId = await getMachineId();
|
|
53
|
+
signingKey = deriveSigningKey(machineId);
|
|
54
|
+
}
|
|
44
55
|
if (skill.provenance === 'imported') {
|
|
45
|
-
// Imported files had foreign signature stripped — can't verify
|
|
46
|
-
// Future: re-sign on import with local key
|
|
56
|
+
// Imported files had foreign signature stripped — can't verify
|
|
47
57
|
}
|
|
48
58
|
else if (!skill.signature) {
|
|
49
|
-
//
|
|
50
|
-
|
|
59
|
+
// Unsigned files are rejected unless trustUnsigned is set
|
|
60
|
+
if (!options?.trustUnsigned) {
|
|
61
|
+
throw new Error(`Skill file for ${domain} is unsigned and cannot be verified. ` +
|
|
62
|
+
`Re-capture or re-import the skill file, or use --trust-unsigned to load it.`);
|
|
63
|
+
}
|
|
51
64
|
}
|
|
52
65
|
else {
|
|
53
66
|
const { verifySignature } = await import('./signing.js');
|
|
54
|
-
if (!verifySignature(skill,
|
|
67
|
+
if (!verifySignature(skill, signingKey)) {
|
|
55
68
|
throw new Error(`Skill file signature verification failed for ${domain} — file may be tampered`);
|
|
56
69
|
}
|
|
57
70
|
}
|
|
@@ -80,7 +93,7 @@ export async function listSkillFiles(skillsDir = DEFAULT_SKILLS_DIR) {
|
|
|
80
93
|
const domain = file.replace(/\.json$/, '');
|
|
81
94
|
if (!DOMAIN_RE.test(domain))
|
|
82
95
|
continue; // skip non-conforming filenames
|
|
83
|
-
const skill = await readSkillFile(domain, skillsDir);
|
|
96
|
+
const skill = await readSkillFile(domain, skillsDir, { trustUnsigned: true });
|
|
84
97
|
if (skill) {
|
|
85
98
|
summaries.push({
|
|
86
99
|
domain: skill.domain,
|
package/dist/skill/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/skill/store.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/skill/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SkillFile } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate a parsed JSON object as a SkillFile.
|
|
4
|
+
* Throws on invalid input — fail fast, fail loud.
|
|
5
|
+
* SSRF checks are optional here (default: off) because the replay engine
|
|
6
|
+
* already enforces SSRF at request time with DNS resolution.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateSkillFile(raw: unknown, options?: {
|
|
9
|
+
checkSsrf?: boolean;
|
|
10
|
+
}): SkillFile;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { validateUrl } from './ssrf.js';
|
|
2
|
+
const ALLOWED_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']);
|
|
3
|
+
/**
|
|
4
|
+
* Validate a parsed JSON object as a SkillFile.
|
|
5
|
+
* Throws on invalid input — fail fast, fail loud.
|
|
6
|
+
* SSRF checks are optional here (default: off) because the replay engine
|
|
7
|
+
* already enforces SSRF at request time with DNS resolution.
|
|
8
|
+
*/
|
|
9
|
+
export function validateSkillFile(raw, options) {
|
|
10
|
+
if (!raw || typeof raw !== 'object') {
|
|
11
|
+
throw new Error('Skill file must be an object');
|
|
12
|
+
}
|
|
13
|
+
const obj = raw;
|
|
14
|
+
// domain
|
|
15
|
+
if (typeof obj.domain !== 'string' || obj.domain.length === 0 || obj.domain.length > 253) {
|
|
16
|
+
throw new Error('Invalid domain: must be a string of 1-253 characters');
|
|
17
|
+
}
|
|
18
|
+
// baseUrl — must be a valid URL; SSRF checked at replay time
|
|
19
|
+
if (typeof obj.baseUrl !== 'string') {
|
|
20
|
+
throw new Error('Missing baseUrl');
|
|
21
|
+
}
|
|
22
|
+
let baseUrlHostname;
|
|
23
|
+
try {
|
|
24
|
+
const url = new URL(obj.baseUrl);
|
|
25
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
26
|
+
throw new Error('non-HTTP scheme');
|
|
27
|
+
}
|
|
28
|
+
baseUrlHostname = url.hostname;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error(`Invalid baseUrl: must be a valid HTTP(S) URL`);
|
|
32
|
+
}
|
|
33
|
+
// Domain-lock: baseUrl hostname must match or be a subdomain of domain (C1 fix)
|
|
34
|
+
const domainStr = obj.domain;
|
|
35
|
+
if (baseUrlHostname !== domainStr && !baseUrlHostname.endsWith('.' + domainStr)) {
|
|
36
|
+
throw new Error(`baseUrl hostname "${baseUrlHostname}" does not match domain "${domainStr}". ` +
|
|
37
|
+
`Skill files cannot redirect requests to unrelated hosts.`);
|
|
38
|
+
}
|
|
39
|
+
if (options?.checkSsrf) {
|
|
40
|
+
const ssrf = validateUrl(obj.baseUrl);
|
|
41
|
+
if (!ssrf.safe) {
|
|
42
|
+
throw new Error(`Unsafe baseUrl: ${ssrf.reason}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// endpoints
|
|
46
|
+
if (!Array.isArray(obj.endpoints)) {
|
|
47
|
+
throw new Error('Missing or invalid endpoints array');
|
|
48
|
+
}
|
|
49
|
+
if (obj.endpoints.length > 500) {
|
|
50
|
+
throw new Error('Too many endpoints (max 500)');
|
|
51
|
+
}
|
|
52
|
+
for (let i = 0; i < obj.endpoints.length; i++) {
|
|
53
|
+
const ep = obj.endpoints[i];
|
|
54
|
+
if (!ep || typeof ep !== 'object') {
|
|
55
|
+
throw new Error(`Endpoint ${i}: must be an object`);
|
|
56
|
+
}
|
|
57
|
+
const e = ep;
|
|
58
|
+
if (typeof e.id !== 'string' || e.id.length === 0 || e.id.length > 200) {
|
|
59
|
+
throw new Error(`Endpoint ${i}: id must be a string of 1-200 characters`);
|
|
60
|
+
}
|
|
61
|
+
if (typeof e.method !== 'string' || !ALLOWED_METHODS.has(e.method)) {
|
|
62
|
+
throw new Error(`Endpoint ${i}: method must be one of ${[...ALLOWED_METHODS].join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
if (typeof e.path !== 'string' || !e.path.startsWith('/')) {
|
|
65
|
+
throw new Error(`Endpoint ${i}: path must start with /`);
|
|
66
|
+
}
|
|
67
|
+
if (e.path.length > 2000) {
|
|
68
|
+
throw new Error(`Endpoint ${i}: path exceeds 2000 characters`);
|
|
69
|
+
}
|
|
70
|
+
// M11: Deep type validation on nested structures
|
|
71
|
+
if ('headers' in e && e.headers !== undefined) {
|
|
72
|
+
if (typeof e.headers !== 'object' || e.headers === null || Array.isArray(e.headers)) {
|
|
73
|
+
throw new Error(`Endpoint ${i}: headers must be an object`);
|
|
74
|
+
}
|
|
75
|
+
for (const [hk, hv] of Object.entries(e.headers)) {
|
|
76
|
+
if (typeof hv !== 'string') {
|
|
77
|
+
throw new Error(`Endpoint ${i}: header "${hk}" value must be a string`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if ('queryParams' in e && e.queryParams !== undefined) {
|
|
82
|
+
if (typeof e.queryParams !== 'object' || e.queryParams === null || Array.isArray(e.queryParams)) {
|
|
83
|
+
throw new Error(`Endpoint ${i}: queryParams must be an object`);
|
|
84
|
+
}
|
|
85
|
+
for (const [qk, qv] of Object.entries(e.queryParams)) {
|
|
86
|
+
if (typeof qv !== 'object' || qv === null || typeof qv.example !== 'string') {
|
|
87
|
+
throw new Error(`Endpoint ${i}: queryParam "${qk}" must have a string example`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if ('requestBody' in e && e.requestBody !== undefined) {
|
|
92
|
+
const rb = e.requestBody;
|
|
93
|
+
if (typeof rb !== 'object' || rb === null) {
|
|
94
|
+
throw new Error(`Endpoint ${i}: requestBody must be an object`);
|
|
95
|
+
}
|
|
96
|
+
if (typeof rb.contentType !== 'string') {
|
|
97
|
+
throw new Error(`Endpoint ${i}: requestBody.contentType must be a string`);
|
|
98
|
+
}
|
|
99
|
+
if (rb.variables !== undefined && !Array.isArray(rb.variables)) {
|
|
100
|
+
throw new Error(`Endpoint ${i}: requestBody.variables must be an array`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return raw;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/skill/validate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apitap/core",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Intercept web API traffic during browsing. Generate portable skill files so AI agents can call APIs directly instead of scraping.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/src/auth/crypto.ts
CHANGED
|
@@ -24,9 +24,14 @@ function getInstallSalt(saltFile?: string): string {
|
|
|
24
24
|
// Generate and save new salt
|
|
25
25
|
const salt = randomBytes(32).toString('hex');
|
|
26
26
|
try {
|
|
27
|
-
mkdirSync(saltPath.replace(/\/[^/]+$/, ''), { recursive: true });
|
|
27
|
+
mkdirSync(saltPath.replace(/\/[^/]+$/, ''), { recursive: true, mode: 0o700 });
|
|
28
28
|
writeFileSync(saltPath, salt, { mode: 0o600 });
|
|
29
|
-
} catch {
|
|
29
|
+
} catch (err: any) {
|
|
30
|
+
// M2 fix: only swallow EEXIST (dir already exists), throw on permission errors etc.
|
|
31
|
+
if (err?.code !== 'EEXIST') {
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
30
35
|
return salt;
|
|
31
36
|
}
|
|
32
37
|
|
|
@@ -44,12 +49,15 @@ export interface EncryptedData {
|
|
|
44
49
|
* being stretched through 100K iterations.
|
|
45
50
|
*/
|
|
46
51
|
export function deriveKey(machineId: string, saltFile?: string): Buffer {
|
|
47
|
-
// Try per-install salt first, fallback to old constant
|
|
52
|
+
// Try per-install salt first, fallback to old constant only on ENOENT (M2 fix)
|
|
48
53
|
try {
|
|
49
54
|
return pbkdf2Sync(machineId, getInstallSalt(saltFile), PBKDF2_ITERATIONS, KEY_LENGTH, 'sha512');
|
|
50
|
-
} catch {
|
|
51
|
-
//
|
|
52
|
-
|
|
55
|
+
} catch (err: any) {
|
|
56
|
+
// Only fall back to legacy salt on file-not-found (ENOENT) — not on permission errors, corrupt files, etc.
|
|
57
|
+
if (err?.code === 'ENOENT') {
|
|
58
|
+
return pbkdf2Sync(machineId, 'apitap-v0.2-key-derivation', PBKDF2_ITERATIONS, KEY_LENGTH, 'sha512');
|
|
59
|
+
}
|
|
60
|
+
throw err;
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
|
package/src/auth/handoff.ts
CHANGED
|
@@ -198,8 +198,20 @@ async function doHandoff(
|
|
|
198
198
|
let detectedOAuth: OAuthTokenDetection | undefined;
|
|
199
199
|
let latestCookies: Array<{ name: string; value: string; domain: string; path: string; expires: number; httpOnly: boolean; secure: boolean; sameSite: 'Strict' | 'Lax' | 'None' }> = [];
|
|
200
200
|
|
|
201
|
+
// M13 fix: Only capture auth from requests targeting the handoff domain
|
|
202
|
+
const targetDomain = domain;
|
|
203
|
+
|
|
201
204
|
// Watch network responses for auth signals (bearer tokens, API keys, OAuth tokens)
|
|
202
205
|
page.on('response', async (response) => {
|
|
206
|
+
// M13: Filter by request origin — only capture auth from target domain
|
|
207
|
+
let reqHost: string;
|
|
208
|
+
try {
|
|
209
|
+
reqHost = new URL(response.request().url()).hostname;
|
|
210
|
+
} catch { return; }
|
|
211
|
+
if (reqHost !== targetDomain && !reqHost.endsWith('.' + targetDomain)) {
|
|
212
|
+
return; // Skip cross-origin requests
|
|
213
|
+
}
|
|
214
|
+
|
|
203
215
|
const reqHeaders = response.request().headers();
|
|
204
216
|
|
|
205
217
|
// Detect auth from request headers
|
|
@@ -279,7 +291,13 @@ async function doHandoff(
|
|
|
279
291
|
// Browser disconnected — use last snapshot from interval
|
|
280
292
|
}
|
|
281
293
|
|
|
282
|
-
|
|
294
|
+
// M4 fix: Filter cookies to only the target domain and its subdomains
|
|
295
|
+
const cookies = latestCookies.filter(c => {
|
|
296
|
+
const cookieDomain = (c.domain || '').replace(/^\./, ''); // Remove leading dot
|
|
297
|
+
return cookieDomain === domain ||
|
|
298
|
+
cookieDomain.endsWith('.' + domain) ||
|
|
299
|
+
domain.endsWith('.' + cookieDomain);
|
|
300
|
+
});
|
|
283
301
|
|
|
284
302
|
if (cookies.length === 0 && !authDetected) {
|
|
285
303
|
return {
|
package/src/auth/manager.ts
CHANGED
|
@@ -157,7 +157,7 @@ export class AuthManager {
|
|
|
157
157
|
|
|
158
158
|
private async saveAll(data: Record<string, StoredAuth>): Promise<void> {
|
|
159
159
|
const dir = join(this.authPath, '..');
|
|
160
|
-
await mkdir(dir, { recursive: true });
|
|
160
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
161
161
|
|
|
162
162
|
const plaintext = JSON.stringify(data);
|
|
163
163
|
const encrypted = encrypt(plaintext, this.key);
|
|
@@ -201,13 +201,30 @@ export function getParentDomains(domain: string): string[] {
|
|
|
201
201
|
* Fallback: hostname + homedir (less secure but portable)
|
|
202
202
|
*/
|
|
203
203
|
export async function getMachineId(): Promise<string> {
|
|
204
|
+
// Allow override for testing
|
|
205
|
+
if (process.env.APITAP_MACHINE_ID) {
|
|
206
|
+
return process.env.APITAP_MACHINE_ID;
|
|
207
|
+
}
|
|
208
|
+
|
|
204
209
|
try {
|
|
205
210
|
const id = await readFile('/etc/machine-id', 'utf-8');
|
|
206
211
|
return id.trim();
|
|
207
212
|
} catch {
|
|
208
|
-
//
|
|
209
|
-
const {
|
|
210
|
-
const
|
|
211
|
-
|
|
213
|
+
// M1 fix: generate a random per-install ID instead of hostname+homedir
|
|
214
|
+
const { homedir: hd } = await import('node:os');
|
|
215
|
+
const installIdPath = join(hd(), '.apitap', 'install-id');
|
|
216
|
+
try {
|
|
217
|
+
const existing = await readFile(installIdPath, 'utf-8');
|
|
218
|
+
return existing.trim();
|
|
219
|
+
} catch {
|
|
220
|
+
// Generate and save new random ID
|
|
221
|
+
const { randomBytes } = await import('node:crypto');
|
|
222
|
+
const newId = randomBytes(32).toString('hex');
|
|
223
|
+
try {
|
|
224
|
+
await mkdir(join(hd(), '.apitap'), { recursive: true, mode: 0o700 });
|
|
225
|
+
await writeFile(installIdPath, newId, { mode: 0o600 });
|
|
226
|
+
} catch { /* best effort save — use the generated ID anyway */ }
|
|
227
|
+
return newId;
|
|
228
|
+
}
|
|
212
229
|
}
|
|
213
230
|
}
|
package/src/capture/monitor.ts
CHANGED
|
@@ -34,6 +34,10 @@ export interface CaptureResult {
|
|
|
34
34
|
domBytes?: number; // v1.0: measured DOM size for browser cost comparison
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// SECURITY NOTE (M9): CDP connections use unauthenticated HTTP on localhost.
|
|
38
|
+
// Any local process can connect to the same port. This is a known limitation of
|
|
39
|
+
// Chrome DevTools Protocol. Prefer Playwright's built-in launch over connecting
|
|
40
|
+
// to an existing browser when possible. Never expose CDP ports on non-loopback interfaces.
|
|
37
41
|
const DEFAULT_CDP_PORTS = [18792, 18800, 9222];
|
|
38
42
|
const APITAP_DIR = process.env.APITAP_DIR || join(homedir(), '.apitap');
|
|
39
43
|
|
package/src/capture/scrubber.ts
CHANGED
|
@@ -22,6 +22,12 @@ const SSN_RE = /\b\d{3}-\d{2}-\d{4}\b/g;
|
|
|
22
22
|
const BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/-]+=*\b/g;
|
|
23
23
|
const JWT_RE = /\beyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/g;
|
|
24
24
|
|
|
25
|
+
// M12: Cloud provider keys and private key material
|
|
26
|
+
const AWS_ACCESS_KEY_RE = /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g;
|
|
27
|
+
const GCP_API_KEY_RE = /\bAIza[A-Za-z0-9_-]{35}\b/g;
|
|
28
|
+
const PRIVATE_KEY_RE = /-----BEGIN[\s]+(?:RSA\s+|EC\s+|DSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END[\s]+(?:RSA\s+|EC\s+|DSA\s+)?PRIVATE\s+KEY-----/g;
|
|
29
|
+
const BASIC_AUTH_RE = /\bBasic\s+[A-Za-z0-9+/]{8,}={0,2}\b/g;
|
|
30
|
+
|
|
25
31
|
/**
|
|
26
32
|
* Scrub PII from a string. Returns the string with PII replaced by placeholders.
|
|
27
33
|
* Order matters: SSN before phone (SSN is more specific).
|
|
@@ -53,5 +59,11 @@ export function scrubPII(input: string): string {
|
|
|
53
59
|
result = result.replace(BEARER_TOKEN_RE, '[token]');
|
|
54
60
|
result = result.replace(JWT_RE, '[token]');
|
|
55
61
|
|
|
62
|
+
// M12: Cloud provider keys and private key material
|
|
63
|
+
result = result.replace(PRIVATE_KEY_RE, '[private-key]');
|
|
64
|
+
result = result.replace(AWS_ACCESS_KEY_RE, '[aws-key]');
|
|
65
|
+
result = result.replace(GCP_API_KEY_RE, '[gcp-key]');
|
|
66
|
+
result = result.replace(BASIC_AUTH_RE, '[token]');
|
|
67
|
+
|
|
56
68
|
return result;
|
|
57
69
|
}
|
package/src/capture/session.ts
CHANGED
|
@@ -133,20 +133,11 @@ export class CaptureSession {
|
|
|
133
133
|
case 'navigate': {
|
|
134
134
|
if (!action.url) return { success: false, error: 'url required for navigate', snapshot: await this.takeSnapshot() };
|
|
135
135
|
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// Block non-HTTP schemes (file://, ftp://, etc.)
|
|
143
|
-
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
144
|
-
return { success: false, error: `Blocked scheme: ${parsed.protocol}`, snapshot: await this.takeSnapshot() };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Block cloud metadata endpoint specifically (high-value target)
|
|
148
|
-
if (parsed.hostname === '169.254.169.254') {
|
|
149
|
-
return { success: false, error: 'Navigation blocked: cloud metadata endpoint', snapshot: await this.takeSnapshot() };
|
|
136
|
+
// M7 fix: Full SSRF validation on navigate URLs (same checks as ssrf.ts)
|
|
137
|
+
const { validateUrl: validateNavUrl } = await import('../skill/ssrf.js');
|
|
138
|
+
const navResult = validateNavUrl(action.url);
|
|
139
|
+
if (!navResult.safe) {
|
|
140
|
+
return { success: false, error: `Navigation blocked: ${navResult.reason}`, snapshot: await this.takeSnapshot() };
|
|
150
141
|
}
|
|
151
142
|
|
|
152
143
|
await this.page.goto(action.url, { waitUntil: 'domcontentloaded' });
|