From fb3958ba441d3f523382456f7e6925da3c412e87 Mon Sep 17 00:00:00 2001 From: Salman Chishti Date: Thu, 13 Mar 2025 04:47:49 -0700 Subject: [PATCH] update ts docs --- __tests__/util.test.ts | 18 +++++---------- src/internal/shared/util.ts | 45 ++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 12cec07..7cf071d 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -8,34 +8,28 @@ describe('maskSigUrl', () => { jest.clearAllMocks() }) - it('returns the original URL if no sig parameter is present', () => { + it('does nothing if no sig parameter is present', () => { const url = 'https://example.com' - const maskedUrl = maskSigUrl(url) - expect(maskedUrl).toBe(url) + maskSigUrl(url) expect(setSecret).not.toHaveBeenCalled() }) it('masks the sig parameter in the middle of the URL and sets it as a secret', () => { const url = 'https://example.com/?param1=value1&sig=12345¶m2=value2' - const maskedUrl = maskSigUrl(url) - expect(maskedUrl).toBe( - 'https://example.com/?param1=value1&sig=***¶m2=value2' - ) + maskSigUrl(url) expect(setSecret).toHaveBeenCalledWith('12345') expect(setSecret).toHaveBeenCalledWith(encodeURIComponent('12345')) }) - it('returns the original URL if it is empty', () => { + it('does nothing if the URL is empty', () => { const url = '' - const maskedUrl = maskSigUrl(url) - expect(maskedUrl).toBe('') + maskSigUrl(url) expect(setSecret).not.toHaveBeenCalled() }) it('handles URLs with fragments', () => { const url = 'https://example.com?sig=12345#fragment' - const maskedUrl = maskSigUrl(url) - expect(maskedUrl).toBe('https://example.com/?sig=***#fragment') + maskSigUrl(url) expect(setSecret).toHaveBeenCalledWith('12345') expect(setSecret).toHaveBeenCalledWith(encodeURIComponent('12345')) }) diff --git a/src/internal/shared/util.ts b/src/internal/shared/util.ts index b69bb18..bbce73f 100644 --- a/src/internal/shared/util.ts +++ b/src/internal/shared/util.ts @@ -2,13 +2,23 @@ import {debug, setSecret} from '@actions/core' /** * Masks the `sig` parameter in a URL and sets it as a secret. - * @param url The URL containing the `sig` parameter. - * @returns A masked URL where the sig parameter value is replaced with '***' if found, - * or the original URL if no sig parameter is present. + * + * @param url - The URL containing the signature parameter to mask + * @remarks + * This function attempts to parse the provided URL and identify the 'sig' query parameter. + * If found, it registers both the raw and URL-encoded signature values as secrets using + * the Actions `setSecret` API, which prevents them from being displayed in logs. + * + * The function handles errors gracefully if URL parsing fails, logging them as debug messages. + * + * @example + * ```typescript + * // Mask a signature in an Azure SAS token URL + * maskSigUrl('https://example.blob.core.windows.net/container/file.txt?sig=abc123&se=2023-01-01'); + * ``` */ -export function maskSigUrl(url: string): string { - if (!url) return url - +export function maskSigUrl(url: string): void { + if (!url) return try { const parsedUrl = new URL(url) const signature = parsedUrl.searchParams.get('sig') @@ -17,7 +27,6 @@ export function maskSigUrl(url: string): string { setSecret(signature) setSecret(encodeURIComponent(signature)) parsedUrl.searchParams.set('sig', '***') - return parsedUrl.toString() } } catch (error) { debug( @@ -26,18 +35,34 @@ export function maskSigUrl(url: string): string { }` ) } - return url } /** - * Masks any URLs containing signature parameters in the provided object + * Masks sensitive information in URLs containing signature parameters. + * Currently supports masking 'sig' parameters in the 'signed_upload_url' + * and 'signed_download_url' properties of the provided object. + * + * @param body - The object should contain a signature + * @remarks + * This function extracts URLs from the object properties and calls maskSigUrl + * on each one to redact sensitive signature information. The function doesn't + * modify the original object; it only marks the signatures as secrets for + * logging purposes. + * + * @example + * ```typescript + * const responseBody = { + * signed_upload_url: 'https://blob.core.windows.net/?sig=abc123', + * signed_download_url: 'https://blob.core/windows.net/?sig=def456' + * }; + * maskSecretUrls(responseBody); + * ``` */ export function maskSecretUrls(body: Record | null): void { if (typeof body !== 'object' || body === null) { debug('body is not an object or is null') return } - if ( 'signed_upload_url' in body && typeof body.signed_upload_url === 'string'