Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove trailing "/" from folder names #1858

Merged
merged 2 commits into from
Nov 8, 2024
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
6 changes: 3 additions & 3 deletions backend/src/controllers/imap.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ export function sanitizeImapInput(input: string): string {
}
// Remove CRLF characters to prevent injection
const sanitized = input.replace(/[\r\n]+/g, '');
// Remove dangerous IMAP special characters
const safeInput = sanitized.replace(/[{}()"\\*]/g, '');
// Escape trailing folder separator (if present)
const cleaned = sanitized.replace(/\/$/, '');
// Strip leading and trailing whitespace
const trimmedInput = safeInput.trim();
const trimmedInput = cleaned.trim();

if (trimmedInput.length > 255) {
// exceeds max length defined in RFC
Expand Down
16 changes: 15 additions & 1 deletion backend/src/services/imap/ImapEmailsFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ export default class ImapEmailsFetcher {
(folder) => !EXCLUDED_IMAP_FOLDERS.includes(folder)
);

logger.debug(
`[${this.constructor.name}:getTotalMessages] fetching total messages`,
{
miningId: this.miningId,
email: this.userEmail,
folders: this.folders
}
);

const totalPromises = folders.map(
(folder) =>
new Promise<number>((resolve, reject) => {
Expand Down Expand Up @@ -151,7 +160,12 @@ export default class ImapEmailsFetcher {
});
});
} catch (err) {
logger.error('Failed fetching total messages', err);
logger.error('Failed fetching total messages', {
miningId: this.miningId,
email: this.userEmail,
folders: this.folders,
error: err
});
throw err;
} finally {
if (imapConnection) {
Expand Down
23 changes: 5 additions & 18 deletions backend/test/unit/imapHelpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ describe('sanitizeImapInput', () => {
expect(sanitizeImapInput('')).toBe('');
});

it('should return an empty string for inputs with only special characters', () => {
expect(sanitizeImapInput('{*()}')).toBe('');
});

it('should return valid input without changes', () => {
expect(sanitizeImapInput('ValidFolderName')).toBe('ValidFolderName');
});
Expand All @@ -90,25 +86,11 @@ describe('sanitizeImapInput', () => {
expect(sanitizeImapInput('Folder-Name_123')).toBe('Folder-Name_123');
});

it('should strip out IMAP injection characters', () => {
expect(sanitizeImapInput('Folder{Name}')).toBe('FolderName');
expect(sanitizeImapInput('Folder(Name)')).toBe('FolderName');
expect(sanitizeImapInput('Folder*Name')).toBe('FolderName');
expect(sanitizeImapInput('Folder\\"Name')).toBe('FolderName');
});

it('should strip out CRLF sequences', () => {
expect(sanitizeImapInput('Folder\r\nName')).toBe('FolderName');
expect(sanitizeImapInput('Folder\nName')).toBe('FolderName');
});

it('should remove special IMAP characters', () => {
expect(sanitizeImapInput('Folder"Name')).toBe('FolderName');
expect(sanitizeImapInput('Folder{Name}*Test("123")')).toBe(
'FolderNameTest123'
);
});

it('should throw a TypeError for non-string inputs', () => {
expect(() => sanitizeImapInput(123 as any)).toThrow(TypeError);
expect(() => sanitizeImapInput(null as any)).toThrow(TypeError);
Expand All @@ -123,6 +105,11 @@ describe('sanitizeImapInput', () => {
expect(sanitizeImapInput('FolderñName')).toBe('FolderñName');
});

it('should escape the separator at the end of folder name', () => {
const folderName = sanitizeImapInput('folder1/');
expect(folderName).toBe('folder1');
});

it('should throw an error if input exceeds maximum length', () => {
const longInput = 'A'.repeat(256); // 256 characters
expect(() => sanitizeImapInput(longInput)).toThrow('Max length exceeded');
Expand Down
Loading