@apitap/core 1.4.0 → 1.4.1

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.
Files changed (72) hide show
  1. package/README.md +2 -2
  2. package/dist/auth/crypto.d.ts +10 -0
  3. package/dist/auth/crypto.js +30 -6
  4. package/dist/auth/crypto.js.map +1 -1
  5. package/dist/auth/handoff.js +20 -1
  6. package/dist/auth/handoff.js.map +1 -1
  7. package/dist/auth/manager.d.ts +1 -0
  8. package/dist/auth/manager.js +35 -9
  9. package/dist/auth/manager.js.map +1 -1
  10. package/dist/capture/monitor.js +4 -0
  11. package/dist/capture/monitor.js.map +1 -1
  12. package/dist/capture/scrubber.js +10 -0
  13. package/dist/capture/scrubber.js.map +1 -1
  14. package/dist/capture/session.js +7 -17
  15. package/dist/capture/session.js.map +1 -1
  16. package/dist/cli.js +74 -17
  17. package/dist/cli.js.map +1 -1
  18. package/dist/discovery/fetch.js +3 -3
  19. package/dist/discovery/fetch.js.map +1 -1
  20. package/dist/mcp.d.ts +2 -0
  21. package/dist/mcp.js +59 -33
  22. package/dist/mcp.js.map +1 -1
  23. package/dist/native-host.js +2 -2
  24. package/dist/native-host.js.map +1 -1
  25. package/dist/orchestration/browse.js +13 -4
  26. package/dist/orchestration/browse.js.map +1 -1
  27. package/dist/plugin.d.ts +1 -1
  28. package/dist/plugin.js +14 -4
  29. package/dist/plugin.js.map +1 -1
  30. package/dist/read/decoders/reddit.js +4 -0
  31. package/dist/read/decoders/reddit.js.map +1 -1
  32. package/dist/replay/engine.js +60 -17
  33. package/dist/replay/engine.js.map +1 -1
  34. package/dist/serve.d.ts +2 -0
  35. package/dist/serve.js +8 -1
  36. package/dist/serve.js.map +1 -1
  37. package/dist/skill/generator.d.ts +5 -0
  38. package/dist/skill/generator.js +30 -4
  39. package/dist/skill/generator.js.map +1 -1
  40. package/dist/skill/search.js +1 -1
  41. package/dist/skill/search.js.map +1 -1
  42. package/dist/skill/signing.js +19 -1
  43. package/dist/skill/signing.js.map +1 -1
  44. package/dist/skill/ssrf.js +71 -2
  45. package/dist/skill/ssrf.js.map +1 -1
  46. package/dist/skill/store.d.ts +2 -0
  47. package/dist/skill/store.js +23 -10
  48. package/dist/skill/store.js.map +1 -1
  49. package/dist/skill/validate.d.ts +10 -0
  50. package/dist/skill/validate.js +106 -0
  51. package/dist/skill/validate.js.map +1 -0
  52. package/package.json +1 -1
  53. package/src/auth/crypto.ts +14 -6
  54. package/src/auth/handoff.ts +19 -1
  55. package/src/auth/manager.ts +22 -5
  56. package/src/capture/monitor.ts +4 -0
  57. package/src/capture/scrubber.ts +12 -0
  58. package/src/capture/session.ts +5 -14
  59. package/src/cli.ts +71 -11
  60. package/src/discovery/fetch.ts +2 -2
  61. package/src/mcp.ts +58 -31
  62. package/src/orchestration/browse.ts +13 -4
  63. package/src/plugin.ts +17 -5
  64. package/src/read/decoders/reddit.ts +3 -3
  65. package/src/replay/engine.ts +65 -15
  66. package/src/serve.ts +10 -1
  67. package/src/skill/generator.ts +32 -4
  68. package/src/skill/search.ts +1 -1
  69. package/src/skill/signing.ts +20 -1
  70. package/src/skill/ssrf.ts +69 -2
  71. package/src/skill/store.ts +29 -11
  72. package/src/skill/validate.ts +48 -0
@@ -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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"}
@@ -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[]>;
@@ -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 skill = JSON.parse(content);
42
- // If verification requested, check signature
43
- if (options?.verifySignature && options.signingKey) {
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, warn only
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
- // No signature present on non-imported file
50
- throw new Error(`Skill file for ${domain} has no signature — file may be tampered`);
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, options.signingKey)) {
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,
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/skill/store.ts"],"names":[],"mappings":"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"}
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.0",
3
+ "version": "1.4.1",
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",
@@ -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 for migration
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
- // Fallback for old installs (migration note: remove after all users migrated)
52
- return pbkdf2Sync(machineId, 'apitap-v0.2-key-derivation', PBKDF2_ITERATIONS, KEY_LENGTH, 'sha512');
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
 
@@ -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
- const cookies = latestCookies;
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 {
@@ -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
- // Fallback for non-Linux systems
209
- const { hostname } = await import('node:os');
210
- const { homedir } = await import('node:os');
211
- return `${hostname()}-${homedir()}`;
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
  }
@@ -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
 
@@ -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
  }
@@ -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
- // Basic URL validation block non-HTTP schemes and cloud metadata
137
- let parsed: URL;
138
- try { parsed = new URL(action.url); } catch {
139
- return { success: false, error: 'Invalid URL', snapshot: await this.takeSnapshot() };
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' });
package/src/cli.ts CHANGED
@@ -158,6 +158,15 @@ async function handleCapture(positional: string[], flags: Record<string, string
158
158
  const skipVerify = flags['no-verify'] === true;
159
159
  const verifyPosts = flags['verify-posts'] === true;
160
160
 
161
+ // SSRF validation for CLI (H6 fix)
162
+ if (flags['danger-disable-ssrf'] !== true) {
163
+ const ssrfCheck = await resolveAndValidateUrl(fullUrl);
164
+ if (!ssrfCheck.safe) {
165
+ console.error(`Error: URL blocked (SSRF): ${ssrfCheck.reason}`);
166
+ process.exit(1);
167
+ }
168
+ }
169
+
161
170
  if (!json) {
162
171
  const domainOnly = flags['all-domains'] !== true;
163
172
  console.log(`\n 🔍 Capturing ${url}...${duration ? ` (${duration}s)` : ' (Ctrl+C to stop)'}${domainOnly ? ' [domain-only]' : ' [all domains]'}\n`);
@@ -341,7 +350,7 @@ async function handleShow(positional: string[], flags: Record<string, string | b
341
350
  process.exit(1);
342
351
  }
343
352
 
344
- const skill = await readSkillFile(domain, SKILLS_DIR);
353
+ const skill = await readSkillFile(domain, SKILLS_DIR, { trustUnsigned: true });
345
354
  if (!skill) {
346
355
  console.error(`Error: No skill file found for "${domain}". Run \`apitap capture\` first.`);
347
356
  process.exit(1);
@@ -380,7 +389,8 @@ async function handleReplay(positional: string[], flags: Record<string, string |
380
389
 
381
390
  const machineId = await getMachineId();
382
391
  const signingKey = deriveSigningKey(machineId);
383
- const skill = await readSkillFile(domain, SKILLS_DIR, { verifySignature: true, signingKey });
392
+ const trustUnsigned = flags['trust-unsigned'] === true;
393
+ const skill = await readSkillFile(domain, SKILLS_DIR, { verifySignature: true, signingKey, trustUnsigned });
384
394
  if (!skill) {
385
395
  console.error(`Error: No skill file found for "${domain}".`);
386
396
  process.exit(1);
@@ -417,6 +427,10 @@ async function handleReplay(positional: string[], flags: Record<string, string |
417
427
  const fresh = flags.fresh === true;
418
428
  const json = flags.json === true;
419
429
  const maxBytes = typeof flags['max-bytes'] === 'string' ? parseInt(flags['max-bytes'], 10) : undefined;
430
+ const dangerDisableSsrf = flags['danger-disable-ssrf'] === true;
431
+ if (dangerDisableSsrf) {
432
+ console.error('[apitap] WARNING: SSRF protection is disabled via --danger-disable-ssrf');
433
+ }
420
434
 
421
435
  const result = await replayEndpoint(skill, endpointId, {
422
436
  params: Object.keys(params).length > 0 ? params : undefined,
@@ -424,7 +438,7 @@ async function handleReplay(positional: string[], flags: Record<string, string |
424
438
  domain,
425
439
  fresh,
426
440
  maxBytes,
427
- _skipSsrfCheck: process.env.APITAP_SKIP_SSRF_CHECK === '1',
441
+ _skipSsrfCheck: dangerDisableSsrf,
428
442
  });
429
443
 
430
444
  if (json) {
@@ -493,7 +507,8 @@ async function handleRefresh(positional: string[], flags: Record<string, string
493
507
  process.exit(1);
494
508
  }
495
509
 
496
- const skill = await readSkillFile(domain, SKILLS_DIR);
510
+ const trustUnsigned = flags['trust-unsigned'] === true;
511
+ const skill = await readSkillFile(domain, SKILLS_DIR, { trustUnsigned });
497
512
  if (!skill) {
498
513
  console.error(`Error: No skill file found for "${domain}".`);
499
514
  process.exit(1);
@@ -597,8 +612,8 @@ async function handleAuth(positional: string[], flags: Record<string, string | b
597
612
  }
598
613
  }
599
614
 
600
- // Read skill file for OAuth config (non-secret)
601
- const skill = await readSkillFile(domain, SKILLS_DIR);
615
+ // Read skill file for OAuth config (non-secret) — trustUnsigned for display only
616
+ const skill = await readSkillFile(domain, SKILLS_DIR, { trustUnsigned: true });
602
617
  const oauthConfig = skill?.auth?.oauthConfig;
603
618
 
604
619
  const status = {
@@ -660,7 +675,7 @@ async function handleServe(positional: string[], flags: Record<string, string |
660
675
  });
661
676
 
662
677
  // Print tool list to stderr (stdout is the MCP transport)
663
- const skill = await readSkillFile(domain, SKILLS_DIR);
678
+ const skill = await readSkillFile(domain, SKILLS_DIR, { trustUnsigned: true });
664
679
  const tools = buildServeTools(skill!);
665
680
 
666
681
  if (json) {
@@ -682,10 +697,13 @@ async function handleServe(positional: string[], flags: Record<string, string |
682
697
  }
683
698
  }
684
699
 
685
- async function handleMcp(): Promise<void> {
700
+ async function handleMcp(flags: Record<string, string | boolean>): Promise<void> {
701
+ if (flags['danger-disable-ssrf'] === true) {
702
+ console.error('[apitap] WARNING: SSRF protection is disabled via --danger-disable-ssrf');
703
+ }
686
704
  const server = createMcpServer({
687
705
  skillsDir: SKILLS_DIR,
688
- _skipSsrfCheck: process.env.APITAP_SKIP_SSRF_CHECK === '1',
706
+ _skipSsrfCheck: flags['danger-disable-ssrf'] === true,
689
707
  });
690
708
  const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
691
709
  const transport = new StdioServerTransport();
@@ -710,6 +728,16 @@ async function handleInspect(positional: string[], flags: Record<string, string
710
728
  process.exit(1);
711
729
  }
712
730
 
731
+ // SSRF validation for CLI (H6 fix)
732
+ const fullInspectUrl = url.startsWith('http') ? url : `https://${url}`;
733
+ if (flags['danger-disable-ssrf'] !== true) {
734
+ const ssrfCheck = await resolveAndValidateUrl(fullInspectUrl);
735
+ if (!ssrfCheck.safe) {
736
+ console.error(`Error: URL blocked (SSRF): ${ssrfCheck.reason}`);
737
+ process.exit(1);
738
+ }
739
+ }
740
+
713
741
  const json = flags.json === true;
714
742
  const duration = typeof flags.duration === 'string' ? parseInt(flags.duration, 10) : 30;
715
743
 
@@ -799,6 +827,20 @@ async function handleDiscover(positional: string[], flags: Record<string, string
799
827
  const json = flags.json === true;
800
828
  const save = flags.save === true;
801
829
 
830
+ // SSRF validation for CLI (H6 fix)
831
+ const fullDiscoverUrl = url.startsWith('http') ? url : `https://${url}`;
832
+ if (flags['danger-disable-ssrf'] !== true) {
833
+ const ssrfCheck = await resolveAndValidateUrl(fullDiscoverUrl);
834
+ if (!ssrfCheck.safe) {
835
+ if (json) {
836
+ console.log(JSON.stringify({ error: `URL blocked (SSRF): ${ssrfCheck.reason}` }));
837
+ } else {
838
+ console.error(`Error: URL blocked (SSRF): ${ssrfCheck.reason}`);
839
+ }
840
+ process.exit(1);
841
+ }
842
+ }
843
+
802
844
  if (!json) {
803
845
  console.log(`\n Discovering APIs for ${url}...\n`);
804
846
  }
@@ -902,7 +944,7 @@ async function handleBrowse(positional: string[], flags: Record<string, string |
902
944
  skillsDir: SKILLS_DIR,
903
945
  cache: new SessionCache(),
904
946
  maxBytes,
905
- _skipSsrfCheck: process.env.APITAP_SKIP_SSRF_CHECK === '1',
947
+ _skipSsrfCheck: flags['danger-disable-ssrf'] === true,
906
948
  });
907
949
 
908
950
  if (json) {
@@ -933,6 +975,15 @@ async function handlePeek(positional: string[], flags: Record<string, string | b
933
975
  const json = flags.json === true;
934
976
  const fullUrl = url.startsWith('http') ? url : `https://${url}`;
935
977
 
978
+ // SSRF validation for CLI (H6 fix)
979
+ if (flags['danger-disable-ssrf'] !== true) {
980
+ const ssrfCheck = await resolveAndValidateUrl(fullUrl);
981
+ if (!ssrfCheck.safe) {
982
+ console.error(`Error: URL blocked (SSRF): ${ssrfCheck.reason}`);
983
+ process.exit(1);
984
+ }
985
+ }
986
+
936
987
  if (!json) {
937
988
  console.log(`\n Peeking at ${url}...\n`);
938
989
  }
@@ -964,6 +1015,15 @@ async function handleRead(positional: string[], flags: Record<string, string | b
964
1015
  const fullUrl = url.startsWith('http') ? url : `https://${url}`;
965
1016
  const maxBytes = typeof flags['max-bytes'] === 'string' ? parseInt(flags['max-bytes'], 10) : undefined;
966
1017
 
1018
+ // SSRF validation for CLI (H6 fix)
1019
+ if (flags['danger-disable-ssrf'] !== true) {
1020
+ const ssrfCheck = await resolveAndValidateUrl(fullUrl);
1021
+ if (!ssrfCheck.safe) {
1022
+ console.error(`Error: URL blocked (SSRF): ${ssrfCheck.reason}`);
1023
+ process.exit(1);
1024
+ }
1025
+ }
1026
+
967
1027
  if (!json) {
968
1028
  console.log(`\n Reading ${url}...\n`);
969
1029
  }
@@ -1073,7 +1133,7 @@ async function main(): Promise<void> {
1073
1133
  await handleServe(positional, flags);
1074
1134
  break;
1075
1135
  case 'mcp':
1076
- await handleMcp();
1136
+ await handleMcp(flags);
1077
1137
  break;
1078
1138
  case 'inspect':
1079
1139
  await handleInspect(positional, flags);