fix: inspect shared scalar metadata

This commit is contained in:
Danny Avila 2026-07-26 23:46:00 -04:00
parent 3ff4752c4e
commit 32bd4c1ae7
2 changed files with 119 additions and 1 deletions

View file

@ -396,6 +396,124 @@ describe('shared file metadata protection', () => {
},
);
it.each([
[
'file status',
fileContentFilters,
{
isCreatedByUser: true,
files: [{ status: 'PRIVATE-SENTINEL' }],
},
'file',
'content',
],
[
'attachment preview error',
attachmentFilters,
{
isCreatedByUser: true,
attachments: [{ previewError: 'PRIVATE-SENTINEL' }],
},
'message',
'attachment_reference',
],
[
'tool call identifier',
toolOutputFilters,
{
isCreatedByUser: false,
attachments: [{ toolCallId: 'PRIVATE-SENTINEL' }],
},
'tool_argument',
'output',
],
])(
'checks a standard serialized %s under its semantic provenance',
(_label, filters, message, source, field) => {
const error = capturePolicyError(() =>
assertSharedFileMetadataAllowed({
filters,
messages: [message],
shareId: 'share-123',
}),
);
expect(error).toBeInstanceOf(ContentFilterError);
expect(error.body).toMatchObject({
error: 'content_filter_block',
source,
field,
});
expect(JSON.stringify(error.body)).not.toContain('PRIVATE-SENTINEL');
},
);
it('keeps a user-submitted toolCallId under message provenance', () => {
const error = capturePolicyError(() =>
assertSharedFileMetadataAllowed({
filters: attachmentFilters,
messages: [
{
isCreatedByUser: true,
attachments: [{ toolCallId: 'PRIVATE-SENTINEL' }],
},
],
shareId: 'share-123',
}),
);
expect(error).toBeInstanceOf(ContentFilterError);
expect(error.body).toMatchObject({
error: 'content_filter_block',
source: 'message',
field: 'attachment_reference',
});
});
it('preserves field granularity for standard serialized strings', () => {
expect(() =>
assertSharedFileMetadataAllowed({
filters: {
files: {
pii: {
fields: ['name'],
starterPatterns: [],
customPatterns: [BLOCK_PATTERN],
},
},
},
messages: [
{
isCreatedByUser: true,
files: [{ status: 'PRIVATE-SENTINEL' }],
},
],
shareId: 'share-123',
}),
).not.toThrow();
});
it('keeps standard serialized string protection default-off', () => {
expect(() =>
assertSharedFileMetadataAllowed({
filters: {},
messages: [
{
isCreatedByUser: true,
files: [{ status: 'PRIVATE-SENTINEL' }],
attachments: [
{
previewError: 'PRIVATE-SENTINEL',
toolCallId: 'PRIVATE-SENTINEL',
},
],
},
],
shareId: 'share-123',
}),
).not.toThrow();
});
it.each([
[
'web-search result',

View file

@ -868,7 +868,7 @@ function extractNestedSerializedPayloadFragments(
if (typeof value === 'string') {
if (SERIALIZED_LOCATOR_KEYS.includes(key as (typeof SERIALIZED_LOCATOR_KEYS)[number])) {
continue;
} else if (activeClassifications.length > 0 && FILE_FIELD_BY_STANDARD_KEY.has(key)) {
} else if (activeClassifications.length > 0) {
for (const classification of activeClassifications) {
inspectSerializedString(
state,