guardrail-ship 1.0.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/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/mock-implementation.d.ts +1 -0
- package/dist/mock-implementation.d.ts.map +1 -0
- package/dist/mock-implementation.js +2 -0
- package/dist/mock-implementation.js.map +1 -0
- package/dist/mockproof/__tests__/import-graph-scanner.test.d.ts +5 -0
- package/dist/mockproof/__tests__/import-graph-scanner.test.d.ts.map +1 -0
- package/dist/mockproof/__tests__/import-graph-scanner.test.js +92 -0
- package/dist/mockproof/__tests__/import-graph-scanner.test.js.map +1 -0
- package/dist/mockproof/import-graph-scanner.d.ts +93 -0
- package/dist/mockproof/import-graph-scanner.d.ts.map +1 -0
- package/dist/mockproof/import-graph-scanner.js +411 -0
- package/dist/mockproof/import-graph-scanner.js.map +1 -0
- package/dist/mockproof/index.d.ts +10 -0
- package/dist/mockproof/index.d.ts.map +1 -0
- package/dist/mockproof/index.js +10 -0
- package/dist/mockproof/index.js.map +1 -0
- package/dist/reality-mode/auth-enforcer.d.ts +13 -0
- package/dist/reality-mode/auth-enforcer.d.ts.map +1 -0
- package/dist/reality-mode/auth-enforcer.js +90 -0
- package/dist/reality-mode/auth-enforcer.js.map +1 -0
- package/dist/reality-mode/explorer/critical-flows.d.ts +71 -0
- package/dist/reality-mode/explorer/critical-flows.d.ts.map +1 -0
- package/dist/reality-mode/explorer/critical-flows.js +463 -0
- package/dist/reality-mode/explorer/critical-flows.js.map +1 -0
- package/dist/reality-mode/explorer/flow-parser.d.ts +52 -0
- package/dist/reality-mode/explorer/flow-parser.d.ts.map +1 -0
- package/dist/reality-mode/explorer/flow-parser.js +250 -0
- package/dist/reality-mode/explorer/flow-parser.js.map +1 -0
- package/dist/reality-mode/explorer/index.d.ts +11 -0
- package/dist/reality-mode/explorer/index.d.ts.map +1 -0
- package/dist/reality-mode/explorer/index.js +11 -0
- package/dist/reality-mode/explorer/index.js.map +1 -0
- package/dist/reality-mode/explorer/runtime-explorer.d.ts +35 -0
- package/dist/reality-mode/explorer/runtime-explorer.d.ts.map +1 -0
- package/dist/reality-mode/explorer/runtime-explorer.js +688 -0
- package/dist/reality-mode/explorer/runtime-explorer.js.map +1 -0
- package/dist/reality-mode/explorer/surface-discovery.d.ts +60 -0
- package/dist/reality-mode/explorer/surface-discovery.d.ts.map +1 -0
- package/dist/reality-mode/explorer/surface-discovery.js +357 -0
- package/dist/reality-mode/explorer/surface-discovery.js.map +1 -0
- package/dist/reality-mode/explorer/types.d.ts +275 -0
- package/dist/reality-mode/explorer/types.d.ts.map +1 -0
- package/dist/reality-mode/explorer/types.js +8 -0
- package/dist/reality-mode/explorer/types.js.map +1 -0
- package/dist/reality-mode/fake-success-detector.d.ts +10 -0
- package/dist/reality-mode/fake-success-detector.d.ts.map +1 -0
- package/dist/reality-mode/fake-success-detector.js +76 -0
- package/dist/reality-mode/fake-success-detector.js.map +1 -0
- package/dist/reality-mode/index.d.ts +14 -0
- package/dist/reality-mode/index.d.ts.map +1 -0
- package/dist/reality-mode/index.js +14 -0
- package/dist/reality-mode/index.js.map +1 -0
- package/dist/reality-mode/reality-scanner.d.ts +48 -0
- package/dist/reality-mode/reality-scanner.d.ts.map +1 -0
- package/dist/reality-mode/reality-scanner.js +516 -0
- package/dist/reality-mode/reality-scanner.js.map +1 -0
- package/dist/reality-mode/report-generator.d.ts +11 -0
- package/dist/reality-mode/report-generator.d.ts.map +1 -0
- package/dist/reality-mode/report-generator.js +233 -0
- package/dist/reality-mode/report-generator.js.map +1 -0
- package/dist/reality-mode/traffic-classifier.d.ts +14 -0
- package/dist/reality-mode/traffic-classifier.d.ts.map +1 -0
- package/dist/reality-mode/traffic-classifier.js +131 -0
- package/dist/reality-mode/traffic-classifier.js.map +1 -0
- package/dist/reality-mode/types.d.ts +90 -0
- package/dist/reality-mode/types.d.ts.map +1 -0
- package/dist/reality-mode/types.js +2 -0
- package/dist/reality-mode/types.js.map +1 -0
- package/dist/ship-badge/__tests__/ship-badge-generator.test.d.ts +5 -0
- package/dist/ship-badge/__tests__/ship-badge-generator.test.d.ts.map +1 -0
- package/dist/ship-badge/__tests__/ship-badge-generator.test.js +146 -0
- package/dist/ship-badge/__tests__/ship-badge-generator.test.js.map +1 -0
- package/dist/ship-badge/index.d.ts +9 -0
- package/dist/ship-badge/index.d.ts.map +1 -0
- package/dist/ship-badge/index.js +9 -0
- package/dist/ship-badge/index.js.map +1 -0
- package/dist/ship-badge/ship-badge-generator.d.ts +136 -0
- package/dist/ship-badge/ship-badge-generator.d.ts.map +1 -0
- package/dist/ship-badge/ship-badge-generator.js +681 -0
- package/dist/ship-badge/ship-badge-generator.js.map +1 -0
- package/package.json +20 -0
- package/src/index.ts +7 -0
- package/src/mock-implementation.ts +0 -0
- package/src/mockproof/__tests__/import-graph-scanner.test.ts +115 -0
- package/src/mockproof/import-graph-scanner.d.ts +93 -0
- package/src/mockproof/import-graph-scanner.d.ts.map +1 -0
- package/src/mockproof/import-graph-scanner.js +482 -0
- package/src/mockproof/import-graph-scanner.ts +540 -0
- package/src/mockproof/index.ts +18 -0
- package/src/reality-mode/auth-enforcer.ts +97 -0
- package/src/reality-mode/explorer/critical-flows.ts +504 -0
- package/src/reality-mode/explorer/flow-parser.ts +293 -0
- package/src/reality-mode/explorer/index.ts +22 -0
- package/src/reality-mode/explorer/runtime-explorer.ts +715 -0
- package/src/reality-mode/explorer/surface-discovery.ts +498 -0
- package/src/reality-mode/explorer/templates/example-flows/auth-flow.yaml +41 -0
- package/src/reality-mode/explorer/templates/example-flows/checkout-flow.yaml +66 -0
- package/src/reality-mode/explorer/templates/example-flows/contact-form.yaml +43 -0
- package/src/reality-mode/explorer/templates/github-action.yml +132 -0
- package/src/reality-mode/explorer/types.ts +356 -0
- package/src/reality-mode/fake-success-detector.ts +89 -0
- package/src/reality-mode/index.ts +19 -0
- package/src/reality-mode/reality-scanner.d.ts +123 -0
- package/src/reality-mode/reality-scanner.d.ts.map +1 -0
- package/src/reality-mode/reality-scanner.js +526 -0
- package/src/reality-mode/reality-scanner.ts +576 -0
- package/src/reality-mode/report-generator.ts +253 -0
- package/src/reality-mode/traffic-classifier.ts +169 -0
- package/src/reality-mode/types.ts +95 -0
- package/src/ship-badge/__tests__/ship-badge-generator.test.ts +162 -0
- package/src/ship-badge/index.ts +16 -0
- package/src/ship-badge/ship-badge-generator.d.ts +136 -0
- package/src/ship-badge/ship-badge-generator.d.ts.map +1 -0
- package/src/ship-badge/ship-badge-generator.js +779 -0
- package/src/ship-badge/ship-badge-generator.ts +873 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reality Mode - Runtime Fake Detection
|
|
3
|
+
*
|
|
4
|
+
* "Stop shipping pretend features. Guardrail runs your app and catches the lies."
|
|
5
|
+
*
|
|
6
|
+
* This module spins up the app, intercepts network calls, clicks through the UI,
|
|
7
|
+
* and detects:
|
|
8
|
+
* - Calls to localhost, jsonplaceholder, staging domains, ngrok
|
|
9
|
+
* - Routes returning demo/placeholder responses
|
|
10
|
+
* - Silent fallback success patterns
|
|
11
|
+
* - Mock billing and fake invoice IDs
|
|
12
|
+
*
|
|
13
|
+
* The killer feature: a "flight recorder" replay showing exactly what happened.
|
|
14
|
+
*/
|
|
15
|
+
import { TrafficClassifier } from "./traffic-classifier";
|
|
16
|
+
import { FakeSuccessDetector } from "./fake-success-detector";
|
|
17
|
+
import { AuthEnforcer } from "./auth-enforcer";
|
|
18
|
+
// Export constants that are used in the generated test
|
|
19
|
+
export const FAKE_DOMAIN_PATTERNS = [
|
|
20
|
+
/localhost:\d+/i,
|
|
21
|
+
/127\.0\.0\.1:\d+/i,
|
|
22
|
+
/jsonplaceholder\.typicode\.com/i,
|
|
23
|
+
/reqres\.in/i,
|
|
24
|
+
/mockapi\.io/i,
|
|
25
|
+
/mocky\.io/i,
|
|
26
|
+
/httpbin\.org/i,
|
|
27
|
+
/\.ngrok\.io/i,
|
|
28
|
+
/\.ngrok-free\.app/i,
|
|
29
|
+
/staging\./i,
|
|
30
|
+
/\.local\//i,
|
|
31
|
+
/\.test\//i,
|
|
32
|
+
/api\.example\.com/i,
|
|
33
|
+
/fake\.api/i,
|
|
34
|
+
/demo\.api/i,
|
|
35
|
+
];
|
|
36
|
+
export const FAKE_RESPONSE_PATTERNS = [
|
|
37
|
+
{ pattern: /inv_demo_/i, name: "Demo invoice ID" },
|
|
38
|
+
{ pattern: /user_demo_/i, name: "Demo user ID" },
|
|
39
|
+
{ pattern: /cus_demo_/i, name: "Demo customer ID" },
|
|
40
|
+
{ pattern: /sub_demo_/i, name: "Demo subscription ID" },
|
|
41
|
+
{ pattern: /sk_test_/i, name: "Test Stripe key" },
|
|
42
|
+
{ pattern: /pk_test_/i, name: "Test Stripe public key" },
|
|
43
|
+
{ pattern: /"success":\s*true.*"demo"/i, name: "Demo success response" },
|
|
44
|
+
{ pattern: /lorem\s+ipsum/i, name: "Lorem ipsum placeholder" },
|
|
45
|
+
{ pattern: /john\.doe|jane\.doe/i, name: "Placeholder name" },
|
|
46
|
+
{ pattern: /user@example\.com/i, name: "Placeholder email" },
|
|
47
|
+
{ pattern: /placeholder\.(com|jpg|png)/i, name: "Placeholder domain/image" },
|
|
48
|
+
{
|
|
49
|
+
pattern: /"id":\s*("demo"|"test"|"fake"|1234567890)/i,
|
|
50
|
+
name: "Fake ID pattern",
|
|
51
|
+
},
|
|
52
|
+
{ pattern: /"status":\s*"simulated"/i, name: "Simulated status" },
|
|
53
|
+
{ pattern: /"mock":\s*true/i, name: "Mock flag enabled" },
|
|
54
|
+
{ pattern: /"isDemo":\s*true/i, name: "Demo mode flag" },
|
|
55
|
+
];
|
|
56
|
+
export const SILENT_FALLBACK_PATTERNS = [
|
|
57
|
+
{
|
|
58
|
+
pattern: /"error":\s*null.*"data":\s*\[\]/i,
|
|
59
|
+
name: "Empty success on error",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
pattern: /catch.*return\s*\{\s*success:\s*true/i,
|
|
63
|
+
name: "Success on catch",
|
|
64
|
+
},
|
|
65
|
+
{ pattern: /"fallback":\s*true/i, name: "Fallback flag" },
|
|
66
|
+
];
|
|
67
|
+
export const DEFAULT_FAKE_PATTERNS = [
|
|
68
|
+
// Fake domain patterns
|
|
69
|
+
{
|
|
70
|
+
id: "fake-api-domain",
|
|
71
|
+
name: "Mock Backend (Domain)",
|
|
72
|
+
description: "Request to a mock/staging/localhost API domain",
|
|
73
|
+
severity: "critical",
|
|
74
|
+
detect: (item) => {
|
|
75
|
+
if (item.type !== "request")
|
|
76
|
+
return false;
|
|
77
|
+
return FAKE_DOMAIN_PATTERNS.some((p) => p.test(item.url));
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
// Demo response patterns
|
|
81
|
+
{
|
|
82
|
+
id: "demo-response-data",
|
|
83
|
+
name: "Mock Backend (Data)",
|
|
84
|
+
description: "Response contains demo/placeholder data",
|
|
85
|
+
severity: "critical",
|
|
86
|
+
detect: (item) => {
|
|
87
|
+
if (item.type !== "response" || !item.body)
|
|
88
|
+
return false;
|
|
89
|
+
return FAKE_RESPONSE_PATTERNS.some(({ pattern }) => pattern.test(item.body));
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
// Silent fallback
|
|
93
|
+
{
|
|
94
|
+
id: "silent-fallback-success",
|
|
95
|
+
name: "Fake Success (Fallback)",
|
|
96
|
+
description: "Code silently returns success on error (catch returns default)",
|
|
97
|
+
severity: "warning",
|
|
98
|
+
detect: (item) => {
|
|
99
|
+
if (item.type !== "response" || !item.body)
|
|
100
|
+
return false;
|
|
101
|
+
return SILENT_FALLBACK_PATTERNS.some(({ pattern }) => pattern.test(item.body));
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
// HTTP status checks
|
|
105
|
+
{
|
|
106
|
+
id: "mock-status-code",
|
|
107
|
+
name: "Mock Backend (Status)",
|
|
108
|
+
description: "Response with unusual status indicating mock (418, 999)",
|
|
109
|
+
severity: "warning",
|
|
110
|
+
detect: (item) => {
|
|
111
|
+
if (item.type !== "response")
|
|
112
|
+
return false;
|
|
113
|
+
return [418, 999, 0].includes(item.status);
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
// Test keys in production
|
|
117
|
+
{
|
|
118
|
+
id: "test-api-keys",
|
|
119
|
+
name: "Security Risk (Test Keys)",
|
|
120
|
+
description: "Test/demo API keys detected in request or response",
|
|
121
|
+
severity: "critical",
|
|
122
|
+
detect: (item) => {
|
|
123
|
+
const content = item.type === "request"
|
|
124
|
+
? JSON.stringify(item.headers) + (item.body || "")
|
|
125
|
+
: item.body || "";
|
|
126
|
+
return /sk_test_|pk_test_|api_key_test|demo_api_key/i.test(content);
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
// Billing simulation
|
|
130
|
+
{
|
|
131
|
+
id: "simulated-billing",
|
|
132
|
+
name: "Mock Backend (Billing)",
|
|
133
|
+
description: "Billing/payment response appears to be simulated",
|
|
134
|
+
severity: "critical",
|
|
135
|
+
detect: (item) => {
|
|
136
|
+
if (item.type !== "response" || !item.body)
|
|
137
|
+
return false;
|
|
138
|
+
const billingUrls = /stripe|billing|payment|checkout|subscription/i;
|
|
139
|
+
const isBillingEndpoint = billingUrls.test(item.url);
|
|
140
|
+
const hasDemoData = /demo|test|simulate|fake|mock/i.test(item.body);
|
|
141
|
+
return isBillingEndpoint && hasDemoData;
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
export class RealityScanner {
|
|
146
|
+
config;
|
|
147
|
+
trafficClassifier;
|
|
148
|
+
fakeSuccessDetector;
|
|
149
|
+
authEnforcer;
|
|
150
|
+
constructor(config = {}) {
|
|
151
|
+
this.config = {
|
|
152
|
+
timeout: 30000,
|
|
153
|
+
patterns: DEFAULT_FAKE_PATTERNS,
|
|
154
|
+
screenshotOnDetection: true,
|
|
155
|
+
headless: true,
|
|
156
|
+
checkAuth: true,
|
|
157
|
+
...config,
|
|
158
|
+
};
|
|
159
|
+
this.trafficClassifier = new TrafficClassifier(this.config.patterns || DEFAULT_FAKE_PATTERNS);
|
|
160
|
+
this.fakeSuccessDetector = new FakeSuccessDetector();
|
|
161
|
+
this.authEnforcer = new AuthEnforcer();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Generate Playwright test code for Reality Mode scanning
|
|
165
|
+
*/
|
|
166
|
+
generatePlaywrightTest(config) {
|
|
167
|
+
const { baseUrl, clickPaths, outputDir } = config;
|
|
168
|
+
const authTestCode = this.config.checkAuth
|
|
169
|
+
? this.authEnforcer.generateAuthCheckTest({ baseUrl, outputDir })
|
|
170
|
+
: "";
|
|
171
|
+
return `/**
|
|
172
|
+
* Reality Mode - Auto-generated Playwright Test
|
|
173
|
+
*
|
|
174
|
+
* This test runs your app and intercepts all network calls to detect fake data.
|
|
175
|
+
* Generated by Guardrail Reality Mode.
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
import { test, expect, Page, Request, Response } from '@playwright/test';
|
|
179
|
+
import * as fs from 'fs';
|
|
180
|
+
import * as path from 'path';
|
|
181
|
+
|
|
182
|
+
const FAKE_DOMAIN_PATTERNS = ${JSON.stringify(FAKE_DOMAIN_PATTERNS.map((r) => r.source), null, 2)};
|
|
183
|
+
|
|
184
|
+
const FAKE_RESPONSE_PATTERNS = ${JSON.stringify(FAKE_RESPONSE_PATTERNS, null, 2)};
|
|
185
|
+
|
|
186
|
+
interface Detection {
|
|
187
|
+
type: string;
|
|
188
|
+
severity: 'critical' | 'warning';
|
|
189
|
+
url: string;
|
|
190
|
+
evidence: string;
|
|
191
|
+
timestamp: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface ReplayStep {
|
|
195
|
+
timestamp: number;
|
|
196
|
+
type: 'request' | 'response' | 'action' | 'console';
|
|
197
|
+
data: any;
|
|
198
|
+
detections: Detection[];
|
|
199
|
+
screenshot?: string;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
test.describe('Reality Mode Scan', () => {
|
|
203
|
+
let detections: Detection[] = [];
|
|
204
|
+
let replay: ReplayStep[] = [];
|
|
205
|
+
|
|
206
|
+
test.beforeEach(async ({ page }) => {
|
|
207
|
+
detections = [];
|
|
208
|
+
replay = [];
|
|
209
|
+
|
|
210
|
+
// Capture console logs
|
|
211
|
+
page.on('console', msg => {
|
|
212
|
+
replay.push({
|
|
213
|
+
timestamp: Date.now(),
|
|
214
|
+
type: 'console',
|
|
215
|
+
data: { type: msg.type(), text: msg.text() },
|
|
216
|
+
detections: []
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Intercept all network requests
|
|
221
|
+
page.on('request', (request: Request) => {
|
|
222
|
+
const url = request.url();
|
|
223
|
+
// Skip static assets to reduce noise
|
|
224
|
+
if (url.match(/\\.(js|css|png|jpg|svg|ico|woff|woff2|ttf)$/)) return;
|
|
225
|
+
|
|
226
|
+
const step: ReplayStep = {
|
|
227
|
+
timestamp: Date.now(),
|
|
228
|
+
type: 'request',
|
|
229
|
+
data: { url, method: request.method(), headers: request.headers() },
|
|
230
|
+
detections: []
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Check for fake domains
|
|
234
|
+
for (const pattern of FAKE_DOMAIN_PATTERNS) {
|
|
235
|
+
if (new RegExp(pattern, 'i').test(url)) {
|
|
236
|
+
const detection: Detection = {
|
|
237
|
+
type: 'fake-api-domain',
|
|
238
|
+
severity: 'critical',
|
|
239
|
+
url,
|
|
240
|
+
evidence: \`URL matches fake domain pattern: \${pattern}\`,
|
|
241
|
+
timestamp: Date.now()
|
|
242
|
+
};
|
|
243
|
+
step.detections.push(detection);
|
|
244
|
+
detections.push(detection);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
replay.push(step);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
page.on('response', async (response: Response) => {
|
|
252
|
+
const url = response.url();
|
|
253
|
+
if (url.match(/\\.(js|css|png|jpg|svg|ico|woff|woff2|ttf)$/)) return;
|
|
254
|
+
|
|
255
|
+
let body = '';
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
body = await response.text();
|
|
259
|
+
} catch (e) {
|
|
260
|
+
// Some responses can't be read
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const step: ReplayStep = {
|
|
264
|
+
timestamp: Date.now(),
|
|
265
|
+
type: 'response',
|
|
266
|
+
data: { url, status: response.status(), bodyPreview: body.slice(0, 500) },
|
|
267
|
+
detections: []
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// Check for demo data patterns
|
|
271
|
+
for (const { pattern, name } of FAKE_RESPONSE_PATTERNS) {
|
|
272
|
+
if (new RegExp(pattern.source || pattern, 'i').test(body)) {
|
|
273
|
+
const detection: Detection = {
|
|
274
|
+
type: 'demo-response-data',
|
|
275
|
+
severity: 'critical',
|
|
276
|
+
url,
|
|
277
|
+
evidence: \`Response contains \${name}\`,
|
|
278
|
+
timestamp: Date.now()
|
|
279
|
+
};
|
|
280
|
+
step.detections.push(detection);
|
|
281
|
+
detections.push(detection);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
replay.push(step);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
test('should detect fake data in production flow', async ({ page }) => {
|
|
290
|
+
// Navigate to the app
|
|
291
|
+
await page.goto('${baseUrl}');
|
|
292
|
+
|
|
293
|
+
// Initial screenshot
|
|
294
|
+
const initScreenshot = \`init-\${Date.now()}.png\`;
|
|
295
|
+
const outputDir = '${outputDir.replace(/\\/g, "\\\\")}';
|
|
296
|
+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
297
|
+
|
|
298
|
+
await page.screenshot({ path: path.join(outputDir, initScreenshot) });
|
|
299
|
+
|
|
300
|
+
replay.push({
|
|
301
|
+
timestamp: Date.now(),
|
|
302
|
+
type: 'action',
|
|
303
|
+
data: { type: 'navigation', url: '${baseUrl}' },
|
|
304
|
+
detections: [],
|
|
305
|
+
screenshot: initScreenshot
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Execute click paths
|
|
309
|
+
const clickPaths = ${JSON.stringify(clickPaths, null, 4)};
|
|
310
|
+
|
|
311
|
+
for (const path of clickPaths) {
|
|
312
|
+
for (const selector of path) {
|
|
313
|
+
try {
|
|
314
|
+
await page.waitForSelector(selector, { timeout: 5000 });
|
|
315
|
+
await page.click(selector);
|
|
316
|
+
|
|
317
|
+
// Wait for network activity to settle
|
|
318
|
+
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {});
|
|
319
|
+
|
|
320
|
+
// Take screenshot after action
|
|
321
|
+
const stepScreenshot = \`step-\${Date.now()}.png\`;
|
|
322
|
+
await page.screenshot({ path: path.join(outputDir, stepScreenshot) });
|
|
323
|
+
|
|
324
|
+
replay.push({
|
|
325
|
+
timestamp: Date.now(),
|
|
326
|
+
type: 'action',
|
|
327
|
+
data: { type: 'click', selector },
|
|
328
|
+
detections: [],
|
|
329
|
+
screenshot: stepScreenshot
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
} catch (e) {
|
|
333
|
+
// Selector not found, skip
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Save raw replay data for post-analysis
|
|
339
|
+
fs.writeFileSync(
|
|
340
|
+
path.join(outputDir, 'reality-replay.json'),
|
|
341
|
+
JSON.stringify(replay, null, 2)
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
// Fail if critical fake data detected (NO-GO)
|
|
345
|
+
// Warnings do NOT fail the build (GO/WARN)
|
|
346
|
+
const criticalIssues = detections.filter(d => d.severity === 'critical');
|
|
347
|
+
|
|
348
|
+
if (criticalIssues.length > 0) {
|
|
349
|
+
console.log(\`\\n 🛑 NO-GO: Found \${criticalIssues.length} critical reality issues.\`);
|
|
350
|
+
criticalIssues.forEach(d => console.log(\` - \${d.evidence} (\${d.url})\`));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
expect(criticalIssues.length, \`Found \${criticalIssues.length} critical fake data issues\`).toBe(0);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
${authTestCode}
|
|
357
|
+
});
|
|
358
|
+
`;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Post-process the replay to apply advanced detection logic
|
|
362
|
+
*/
|
|
363
|
+
processReplay(replay, authViolations = []) {
|
|
364
|
+
const trafficAnalysis = [];
|
|
365
|
+
const fakeSuccessResults = this.fakeSuccessDetector.detect(replay);
|
|
366
|
+
const detections = [];
|
|
367
|
+
// 1. Analyze Traffic (Green/Yellow/Red)
|
|
368
|
+
const responseHistory = new Map(); // url -> body hash/content
|
|
369
|
+
let hasMutation = false;
|
|
370
|
+
for (const step of replay) {
|
|
371
|
+
if (step.type === "request") {
|
|
372
|
+
const req = {
|
|
373
|
+
type: "request",
|
|
374
|
+
url: step.data.url,
|
|
375
|
+
method: step.data.method,
|
|
376
|
+
headers: step.data.headers || {},
|
|
377
|
+
timestamp: step.timestamp,
|
|
378
|
+
};
|
|
379
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(req.method)) {
|
|
380
|
+
hasMutation = true;
|
|
381
|
+
}
|
|
382
|
+
// Find corresponding response? (Simplification: analyze request independently first)
|
|
383
|
+
const classification = this.trafficClassifier.classify(req);
|
|
384
|
+
trafficAnalysis.push(classification);
|
|
385
|
+
// Convert classifier reasons to detections
|
|
386
|
+
if (classification.verdict === "red") {
|
|
387
|
+
detections.push({
|
|
388
|
+
pattern: {
|
|
389
|
+
id: "traffic-classifier-red",
|
|
390
|
+
name: "Fake Traffic",
|
|
391
|
+
description: classification.reasons.join(", "),
|
|
392
|
+
severity: "critical",
|
|
393
|
+
detect: () => true,
|
|
394
|
+
},
|
|
395
|
+
request: req,
|
|
396
|
+
timestamp: step.timestamp,
|
|
397
|
+
evidence: classification.reasons.join(", "),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else if (step.type === "response") {
|
|
402
|
+
const res = {
|
|
403
|
+
type: "response",
|
|
404
|
+
url: step.data.url,
|
|
405
|
+
status: step.data.status,
|
|
406
|
+
headers: {},
|
|
407
|
+
body: step.data.bodyPreview,
|
|
408
|
+
timestamp: step.timestamp,
|
|
409
|
+
};
|
|
410
|
+
const classification = this.trafficClassifier.classify({
|
|
411
|
+
type: "request",
|
|
412
|
+
url: res.url,
|
|
413
|
+
method: "GET",
|
|
414
|
+
headers: {},
|
|
415
|
+
timestamp: 0,
|
|
416
|
+
}, res);
|
|
417
|
+
trafficAnalysis.push(classification);
|
|
418
|
+
if (classification.verdict === "red") {
|
|
419
|
+
detections.push({
|
|
420
|
+
pattern: {
|
|
421
|
+
id: "traffic-classifier-red-res",
|
|
422
|
+
name: "Fake Response",
|
|
423
|
+
description: classification.reasons.join(", "),
|
|
424
|
+
severity: "critical",
|
|
425
|
+
detect: () => true,
|
|
426
|
+
},
|
|
427
|
+
response: res,
|
|
428
|
+
timestamp: step.timestamp,
|
|
429
|
+
evidence: classification.reasons.join(", "),
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
// Consistency Check (Fake Mutation)
|
|
433
|
+
// If we have seen this URL before, and there was a mutation, the body should ideally change
|
|
434
|
+
if (hasMutation &&
|
|
435
|
+
responseHistory.has(res.url) &&
|
|
436
|
+
responseHistory.get(res.url) === res.body) {
|
|
437
|
+
// Ignore static assets/config
|
|
438
|
+
if (!res.url.includes("/config") &&
|
|
439
|
+
!res.url.includes("/me") &&
|
|
440
|
+
!res.url.includes(".json")) {
|
|
441
|
+
const warning = {
|
|
442
|
+
verdict: "yellow",
|
|
443
|
+
score: 70,
|
|
444
|
+
reasons: [
|
|
445
|
+
`Data for ${res.url} did not change after a write operation (Fake Mutation?)`,
|
|
446
|
+
],
|
|
447
|
+
};
|
|
448
|
+
trafficAnalysis.push(warning);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
responseHistory.set(res.url, res.body || "");
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
// 2. Score Calculation
|
|
455
|
+
let score = 100;
|
|
456
|
+
score -= detections.length * 10;
|
|
457
|
+
score -= fakeSuccessResults.filter((f) => f.isFake).length * 20;
|
|
458
|
+
score -= authViolations.length * 25; // Auth violations are heavy penalties
|
|
459
|
+
// Penalize Red Traffic (Mock Backend / No-Wire)
|
|
460
|
+
const redTraffic = trafficAnalysis.filter((t) => t.verdict === "red");
|
|
461
|
+
score -= redTraffic.length * 15;
|
|
462
|
+
score = Math.max(0, score);
|
|
463
|
+
const verdict = score > 80 ? "real" : score > 50 ? "suspicious" : "fake";
|
|
464
|
+
return {
|
|
465
|
+
verdict,
|
|
466
|
+
score,
|
|
467
|
+
detections,
|
|
468
|
+
replay,
|
|
469
|
+
trafficAnalysis,
|
|
470
|
+
fakeSuccessAnalysis: fakeSuccessResults,
|
|
471
|
+
authViolations,
|
|
472
|
+
summary: {
|
|
473
|
+
totalRequests: replay.filter((r) => r.type === "request").length,
|
|
474
|
+
fakeRequests: detections.length + redTraffic.length,
|
|
475
|
+
totalActions: replay.filter((r) => r.type === "action").length,
|
|
476
|
+
criticalIssues: detections.length +
|
|
477
|
+
redTraffic.length +
|
|
478
|
+
fakeSuccessResults.filter((f) => f.isFake).length +
|
|
479
|
+
authViolations.length,
|
|
480
|
+
warnings: fakeSuccessResults.filter((f) => f.isFake).length,
|
|
481
|
+
},
|
|
482
|
+
timestamp: new Date().toISOString(),
|
|
483
|
+
duration: 0,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
generateReport(result) {
|
|
487
|
+
// This is now handled by ReportGenerator, but we keep a simple string version for console output if needed
|
|
488
|
+
return `Reality Check Complete. Score: ${result.score}/100. Verdict: ${result.verdict.toUpperCase()}`;
|
|
489
|
+
}
|
|
490
|
+
generateDefaultClickPaths() {
|
|
491
|
+
return [
|
|
492
|
+
// 1. Login / Auth Flow
|
|
493
|
+
[
|
|
494
|
+
'input[name="email"]',
|
|
495
|
+
'input[name="password"]',
|
|
496
|
+
'button[type="submit"]',
|
|
497
|
+
'[data-testid="login-submit"]',
|
|
498
|
+
],
|
|
499
|
+
// 2. Dashboard Access
|
|
500
|
+
['[href*="/dashboard"]', '[data-testid="nav-dashboard"]'],
|
|
501
|
+
// 3. View Report/Runs
|
|
502
|
+
['[href*="/runs"]', '[href*="/reports"]', '[data-testid="view-report"]'],
|
|
503
|
+
// 4. Open Findings/Details
|
|
504
|
+
['[data-testid="finding-item"]', 'tr[role="row"]'],
|
|
505
|
+
// 5. Settings / Configuration (Write actions often live here)
|
|
506
|
+
[
|
|
507
|
+
'[href*="/settings"]',
|
|
508
|
+
'[data-testid="nav-settings"]',
|
|
509
|
+
'button:has-text("Save")',
|
|
510
|
+
'[data-testid="save-changes"]',
|
|
511
|
+
],
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
export const realityScanner = new RealityScanner();
|
|
516
|
+
//# sourceMappingURL=reality-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reality-scanner.js","sourceRoot":"","sources":["../../src/reality-mode/reality-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RealityModeResult } from "./types";
|
|
2
|
+
export declare class ReportGenerator {
|
|
3
|
+
generateHtml(result: RealityModeResult): string;
|
|
4
|
+
private getBrandedChip;
|
|
5
|
+
private renderDetections;
|
|
6
|
+
private renderFakeSuccess;
|
|
7
|
+
private renderTrafficAnalysis;
|
|
8
|
+
private renderAuthViolations;
|
|
9
|
+
private renderReplayStep;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=report-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-generator.d.ts","sourceRoot":"","sources":["../../src/reality-mode/report-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,qBAAa,eAAe;IAC1B,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;IAmG/C,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,qBAAqB;IA2B7B,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,gBAAgB;CAoCzB"}
|