mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-11 03:13:12 +00:00
fix(browser): redact observed event URLs
Squash merge PR #1296 into dev.
This commit is contained in:
1 parent
a2a51c6128
commit
9a2a1dde31
4 files changed
+194
-12
No files matched your search
@@ -1209,7 +1209,18 @@ function getTools() {
|
||||
},
|
||||
event: {
|
||||
type: 'object',
|
||||
description: 'Required event selector.',
|
||||
description:
|
||||
'Required event selector. request events require urlIncludes; download events require urlIncludes or suggestedFilenameIncludes. URLs in returned details are redacted.',
|
||||
properties: {
|
||||
kind: { type: 'string', enum: ['dialog', 'navigation', 'request', 'download'] },
|
||||
dialogType: { type: 'string' },
|
||||
messageIncludes: { type: 'string' },
|
||||
urlIncludes: { type: 'string' },
|
||||
method: { type: 'string' },
|
||||
suggestedFilenameIncludes: { type: 'string' },
|
||||
},
|
||||
required: ['kind'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
required: ['event'],
|
||||
@@ -3348,24 +3359,80 @@ function parseEventCondition(value) {
|
||||
};
|
||||
}
|
||||
if (value.kind === 'request') {
|
||||
const urlIncludes = value.urlIncludes ? String(value.urlIncludes) : undefined;
|
||||
if (!urlIncludes) {
|
||||
throw new Error('request events require urlIncludes to limit network metadata exposure');
|
||||
}
|
||||
return {
|
||||
kind: 'request',
|
||||
urlIncludes: value.urlIncludes ? String(value.urlIncludes) : undefined,
|
||||
urlIncludes,
|
||||
method: value.method ? String(value.method) : undefined,
|
||||
};
|
||||
}
|
||||
if (value.kind === 'download') {
|
||||
const urlIncludes = value.urlIncludes ? String(value.urlIncludes) : undefined;
|
||||
const suggestedFilenameIncludes = value.suggestedFilenameIncludes
|
||||
? String(value.suggestedFilenameIncludes)
|
||||
: undefined;
|
||||
if (!urlIncludes && !suggestedFilenameIncludes) {
|
||||
throw new Error(
|
||||
'download events require urlIncludes or suggestedFilenameIncludes to limit metadata exposure'
|
||||
);
|
||||
}
|
||||
return {
|
||||
kind: 'download',
|
||||
urlIncludes: value.urlIncludes ? String(value.urlIncludes) : undefined,
|
||||
suggestedFilenameIncludes: value.suggestedFilenameIncludes
|
||||
? String(value.suggestedFilenameIncludes)
|
||||
: undefined,
|
||||
urlIncludes,
|
||||
suggestedFilenameIncludes,
|
||||
};
|
||||
}
|
||||
throw new Error(`unknown event kind: ${String(value.kind || '')}`);
|
||||
}
|
||||
|
||||
function redactUrlForModel(value, options = {}) {
|
||||
const rawUrl = String(value || '');
|
||||
if (!rawUrl) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
const url = new URL(rawUrl);
|
||||
if (options.originOnly) {
|
||||
return url.origin;
|
||||
}
|
||||
url.username = '';
|
||||
url.password = '';
|
||||
url.search = '';
|
||||
url.hash = '';
|
||||
return url.toString();
|
||||
} catch {
|
||||
return '[redacted-url]';
|
||||
}
|
||||
}
|
||||
|
||||
function redactObservedEvent(event, observed) {
|
||||
if (!observed || typeof observed !== 'object') {
|
||||
return observed;
|
||||
}
|
||||
if (event.kind === 'request') {
|
||||
return {
|
||||
url: redactUrlForModel(observed.url, { originOnly: true }),
|
||||
method: observed.method || '',
|
||||
};
|
||||
}
|
||||
if (event.kind === 'download') {
|
||||
return {
|
||||
url: redactUrlForModel(observed.url, { originOnly: true }),
|
||||
suggestedFilename: observed.suggestedFilename || '',
|
||||
};
|
||||
}
|
||||
if (event.kind === 'navigation' && Object.prototype.hasOwnProperty.call(observed, 'url')) {
|
||||
return {
|
||||
...observed,
|
||||
url: redactUrlForModel(observed.url, { originOnly: true }),
|
||||
};
|
||||
}
|
||||
return observed;
|
||||
}
|
||||
|
||||
function matchesObservedEvent(event, observed) {
|
||||
if (event.kind === 'dialog') {
|
||||
return (
|
||||
@@ -4819,7 +4886,8 @@ async function handleWaitForEvent(toolArgs) {
|
||||
);
|
||||
const event = parseEventCondition(toolArgs.event);
|
||||
const observed = await waitForMatchingEvent({ page, pageIndex, timeoutMs, event });
|
||||
return `pageIndex: ${pageIndex}\nevent: ${event.kind}\nstatus: observed\ndetail: ${JSON.stringify(observed)}`;
|
||||
const safeObserved = redactObservedEvent(event, observed);
|
||||
return `pageIndex: ${pageIndex}\nevent: ${event.kind}\nstatus: observed\ndetail: ${JSON.stringify(safeObserved)}`;
|
||||
}
|
||||
|
||||
function findInterceptRuleIndex(ruleId) {
|
||||
|
||||
Reference in new issue
Block a user