fix: sanitize URL sinks and trim sensitive log fields (#40546)

Co-authored-by: Claude Code <noreply@anthropic.com>
This commit is contained in:
Evan Rusackas
2026-06-02 11:52:02 -07:00
committed by GitHub
co-authored by Claude Code
parent b97d3ef520
commit 00dd31494d
13 changed files with 65 additions and 39 deletions
@@ -29,10 +29,13 @@ import * as chartAction from 'src/components/Chart/chartAction';
import * as saveModalActions from 'src/explore/actions/saveModalActions';
import * as downloadAsImage from 'src/utils/downloadAsImage';
import * as exploreUtils from 'src/explore/exploreUtils';
import { FeatureFlag, VizType } from '@superset-ui/core';
import {
FeatureFlag,
VizType,
getChartMetadataRegistry,
} from '@superset-ui/core';
import { useUnsavedChangesPrompt } from 'src/hooks/useUnsavedChangesPrompt';
import ExploreHeader, { ExploreChartHeaderProps } from '.';
import { getChartMetadataRegistry } from '@superset-ui/core';
import fs from 'fs';
import path from 'path';
@@ -910,23 +913,28 @@ describe('Additional actions tests', () => {
let spyDownloadAsImage: jest.SpyInstance;
let spyExportChart: jest.SpyInstance;
let originalURL: typeof URL;
let anchorClickSpy: jest.SpyInstance;
let createObjectURLSpy: jest.SpyInstance;
let revokeObjectURLSpy: jest.SpyInstance;
beforeAll(() => {
originalURL = global.URL;
// Replace global.URL with a version that has the blob helpers
const mockedURL = {
...originalURL,
createObjectURL: jest.fn(() => 'blob:mock-url'),
revokeObjectURL: jest.fn(),
} as unknown as typeof URL;
Object.defineProperty(global, 'URL', {
writable: true,
value: mockedURL,
});
// jsdom does not define URL.createObjectURL / URL.revokeObjectURL, so we
// stub them before spying so that jest.spyOn finds a real property to wrap.
if (!URL.createObjectURL) {
URL.createObjectURL = () => '';
}
if (!URL.revokeObjectURL) {
URL.revokeObjectURL = () => {};
}
// Spy on static URL methods rather than replacing the constructor so that
// code paths calling `new URL(...)` (e.g. @braintree/sanitize-url) keep
// working while tests can assert on blob URL creation/revocation.
createObjectURLSpy = jest
.spyOn(URL, 'createObjectURL')
.mockReturnValue('blob:mock-url');
revokeObjectURLSpy = jest
.spyOn(URL, 'revokeObjectURL')
.mockImplementation(() => {});
// Avoid jsdom navigation side-effects on <a>.click()
anchorClickSpy = jest
@@ -935,11 +943,8 @@ describe('Additional actions tests', () => {
});
afterAll(() => {
// restore URL
Object.defineProperty(global, 'URL', {
writable: true,
value: originalURL,
});
createObjectURLSpy.mockRestore();
revokeObjectURLSpy.mockRestore();
anchorClickSpy.mockRestore();
});
@@ -1073,7 +1078,7 @@ describe('Additional actions tests', () => {
userEvent.click(await screen.findByText('Export to .CSV'));
expect(spyExportChart.mock.calls.length).toBe(1);
const args = spyExportChart.mock.calls[0][0];
const [[args]] = spyExportChart.mock.calls;
expect(args.resultType).toBe('results');
expect(args.resultFormat).toBe('csv');
@@ -1124,7 +1129,7 @@ describe('Additional actions tests', () => {
userEvent.click(await screen.findByText(/Export to (Excel|\.XLSX)/i));
expect(spyExportChart.mock.calls.length).toBe(1);
const args = spyExportChart.mock.calls[0][0];
const [[args]] = spyExportChart.mock.calls;
expect(args.resultType).toBe('results');
expect(args.resultFormat).toBe('xlsx');
getSpy.mockRestore();
@@ -1162,7 +1167,7 @@ describe('Additional actions tests', () => {
expect(spyExportChart.mock.calls.length).toBe(1);
});
const args = spyExportChart.mock.calls[0][0];
const [[args]] = spyExportChart.mock.calls;
expect(args.resultType).toBe('results');
expect(args.resultFormat).toBe('json');