diff --git a/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py b/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py index 39eb91e50e..591de01669 100644 --- a/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py +++ b/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py @@ -92,7 +92,7 @@ class WeaviateVector(BaseVector): # Parse gRPC configuration if config.grpc_endpoint: - # Urls without scheme won't be parsed correctly in some python verions, + # Urls without scheme won't be parsed correctly in some python versions, # see https://bugs.python.org/issue27657 grpc_endpoint_with_scheme = ( config.grpc_endpoint if "://" in config.grpc_endpoint else f"grpc://{config.grpc_endpoint}" diff --git a/web/utils/get-icon.spec.ts b/web/utils/get-icon.spec.ts index bd9c23d8e5..98eb2288fd 100644 --- a/web/utils/get-icon.spec.ts +++ b/web/utils/get-icon.spec.ts @@ -45,5 +45,118 @@ describe('get-icon', () => { const result = getIconFromMarketPlace(pluginId) expect(result).toBe(`${MARKETPLACE_API_PREFIX}/plugins/${pluginId}/icon`) }) + + /** + * Security tests: Path traversal attempts + * These tests document current behavior and potential security concerns + * Note: Current implementation does not sanitize path traversal sequences + */ + test('handles path traversal attempts', () => { + const pluginId = '../../../etc/passwd' + const result = getIconFromMarketPlace(pluginId) + // Current implementation includes path traversal sequences in URL + // This is a potential security concern that should be addressed + expect(result).toContain('../') + expect(result).toContain(pluginId) + }) + + test('handles multiple path traversal attempts', () => { + const pluginId = '../../../../etc/passwd' + const result = getIconFromMarketPlace(pluginId) + // Current implementation includes path traversal sequences in URL + expect(result).toContain('../') + expect(result).toContain(pluginId) + }) + + test('passes through URL-encoded path traversal sequences', () => { + const pluginId = '..%2F..%2Fetc%2Fpasswd' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + }) + + /** + * Security tests: Null and undefined handling + * These tests document current behavior with invalid input types + * Note: Current implementation converts null/undefined to strings instead of throwing + */ + test('handles null plugin ID', () => { + // Current implementation converts null to string "null" + const result = getIconFromMarketPlace(null as any) + expect(result).toContain('null') + // This is a potential issue - should validate input type + }) + + test('handles undefined plugin ID', () => { + // Current implementation converts undefined to string "undefined" + const result = getIconFromMarketPlace(undefined as any) + expect(result).toContain('undefined') + // This is a potential issue - should validate input type + }) + + /** + * Security tests: URL-sensitive characters + * These tests verify that URL-sensitive characters are handled appropriately + */ + test('does not encode URL-sensitive characters', () => { + const pluginId = 'plugin/with?special=chars#hash' + const result = getIconFromMarketPlace(pluginId) + // Note: Current implementation doesn't encode, but test documents the behavior + expect(result).toContain(pluginId) + expect(result).toContain('?') + expect(result).toContain('#') + expect(result).toContain('=') + }) + + test('handles URL characters like & and %', () => { + const pluginId = 'plugin&with%encoding' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + }) + + /** + * Edge case tests: Extreme inputs + * These tests verify behavior with unusual but valid inputs + */ + test('handles very long plugin ID', () => { + const pluginId = 'a'.repeat(10000) + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + expect(result.length).toBeGreaterThan(10000) + }) + + test('handles Unicode characters', () => { + const pluginId = '插件-🚀-测试-日本語' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + }) + + test('handles control characters', () => { + const pluginId = 'plugin\nwith\ttabs\r\nand\0null' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + }) + + /** + * Security tests: XSS attempts + * These tests verify that XSS attempts are handled appropriately + */ + test('handles XSS attempts with script tags', () => { + const pluginId = '' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + // Note: Current implementation doesn't sanitize, but test documents the behavior + }) + + test('handles XSS attempts with event handlers', () => { + const pluginId = 'plugin"onerror="alert(1)"' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + }) + + test('handles XSS attempts with encoded script tags', () => { + const pluginId = '%3Cscript%3Ealert%28%22xss%22%29%3C%2Fscript%3E' + const result = getIconFromMarketPlace(pluginId) + expect(result).toContain(pluginId) + }) }) }) diff --git a/web/utils/time.spec.ts b/web/utils/time.spec.ts index 2468799da1..fc57390fad 100644 --- a/web/utils/time.spec.ts +++ b/web/utils/time.spec.ts @@ -87,7 +87,8 @@ describe('time', () => { test('works with timestamps', () => { const date = 1705276800000 // 2024-01-15 00:00:00 UTC const result = formatTime({ date, dateFormat: 'YYYY-MM-DD' }) - expect(result).toContain('2024-01-1') // Account for timezone differences + // Account for timezone differences: UTC-5 to UTC+8 can result in 2024-01-14 or 2024-01-15 + expect(result).toMatch(/^2024-01-(14|15)$/) }) test('handles ISO 8601 format', () => {