Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions feedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const {
rankLocalChunks,
supportQueries,
} = require('./retrieval');
const { redactPublic } = require('./helpcenter');

const SITEMAP = 'https://feedback.omi.me/sitemap.xml';
const CACHE_MS = 60 * 60 * 1000;
Expand Down Expand Up @@ -125,12 +126,6 @@ function feedbackPostFromHtml(html) {
return result;
}

function redactPublic(text) {
return String(text || '')
.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '[email]')
.replace(/(?<![\d#])\+?(?:\d[\s().-]*){7,14}\d(?!\d)/g, '[phone]');
}

function categoryName(category) {
const value = category?.name;
if (typeof value === 'string') return value;
Expand Down
6 changes: 4 additions & 2 deletions helpcenter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const SITEMAP = 'https://help.omi.me/sitemap.xml';
const HELP_FORUM = () => String(process.env.HELP_FORUM_CHANNEL_ID || '').trim();
const { cleanDocument } = require('./retrieval');
const { redactSensitive } = require('./privacy');

function articleUrls(xml) {
return [...String(xml || '').matchAll(/<loc>(https:\/\/help\.omi\.me\/en\/articles\/[^<]+)<\/loc>/g)].map(
Expand All @@ -14,9 +15,10 @@ function htmlToText(html) {
return cleanDocument(chunk);
}

// A stored copy of a Discord thread or a Feedback post is shown to the model and can be quoted to
// another customer. It passes the public issue boundary first, then loses any long digit run left.
function redactPublic(text) {
return String(text || '')
.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '[email]')
return redactSensitive(text, { issue: true })
.replace(/(?<![\d#])\+?(?:\d[\s().-]*){7,14}\d(?!\d)/g, '[phone]');
}

Expand Down
11 changes: 11 additions & 0 deletions test/feedback.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,14 @@ test('relevant Feedback is labeled as an issue signal and saved without comments
assert.doesNotMatch(text, /Advanced and continue|person@example\.com/);
assert.equal(saved.length, 1);
});

test('a Feedback report is stored without a pasted key, address or order number', () => {
const page = feedbackPage('https://feedback.omi.me/p/sync-fails', {
title: 'Sync fails for order #22777',
content: 'Sync fails with my key sk-abcdefgh12345678.\nI am at 12 Baker Street, London',
});
for (const value of ['abcdefgh', '22777', 'Baker Street']) {
assert.equal(`${page.title}\n${page.body}`.includes(value), false, value);
}
assert.match(page.body, /Sync fails with my key \[token\]/);
});
18 changes: 18 additions & 0 deletions test/helpcenter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,21 @@ test('the help center sitemap yields article urls and the page text keeps the re
assert.equal(/menu junk/.test(text), false);
assert.equal(redactPublic('mail me at taj@example.com'), 'mail me at [email]');
});

test('a stored Discord help message passes the same redaction as a public issue', () => {
const out = redactPublic([
'My API key is sk-abcdefgh12345678 and the header was Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc',
'Order #22777 never arrived.',
'Ship it to 12 Baker Street, London',
'Ask @DorkKnight or <@123456789012345678>, or mail ada@example.com',
'The app shows error 1011 on build 1.0.552.',
].join('\n'));
for (const value of ['abcdefgh', 'eyJhbGci', '22777', 'Baker Street', 'DorkKnight', '123456789012345678', 'ada@example.com']) {
assert.equal(out.includes(value), false, value);
}
assert.match(out, /\[token\]/);
assert.match(out, /\[order number\]/);
assert.match(out, /\[address\]/);
assert.match(out, /\[Discord user\]/);
assert.match(out, /The app shows error 1011 on build 1\.0\.552\./);
});