fix(common): correctly resolve secret environment variables in basic auth header (#5879)

Co-authored-by: James George <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
Eve 2026-02-16 07:51:11 -05:00 committed by GitHub
parent 2ad2f46e6a
commit 98aa0368fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 16 deletions

View file

@ -131,7 +131,10 @@ import {
getEffectiveRESTRequest,
resolvesEnvsInBody,
} from "~/helpers/utils/EffectiveURL"
import { AggregateEnvironment, getAggregateEnvs } from "~/newstore/environments"
import {
AggregateEnvironment,
getAggregateEnvsWithCurrentValue,
} from "~/newstore/environments"
import { useService } from "dioc/vue"
import cloneDeep from "lodash-es/cloneDeep"
@ -237,7 +240,7 @@ const getFinalURL = (input: string): string => {
* Combines all environment variables into a single environment object
*/
const buildFinalEnvironment = (): Environment => {
const aggregateEnvs = getAggregateEnvs()
const aggregateEnvs = getAggregateEnvsWithCurrentValue()
const inheritedVariables =
currentActiveTabDocument.value.inheritedProperties?.variables || []

View file

@ -49,5 +49,25 @@ describe("Basic Auth", () => {
expect(headers[0].value).toBe(`Basic ${btoa(":")}`)
})
test("resolves secret environment variables before base64 encoding even when `showKeyIfSecret` is `true`", async () => {
const auth: HoppRESTAuth & { authType: "basic" } = {
authActive: true,
authType: "basic",
username: "<<USERNAME>>",
password: "<<PASSWORD>>",
}
// `showKeyIfSecret = true` should NOT affect base64 encoding
// Previously, this would encode "testuser:<<PASSWORD>>" instead of "testuser:testpass"
// See: https://github.com/hoppscotch/hoppscotch/issues/5863
const headers = await generateBasicAuthHeaders(
auth,
mockEnvVars,
true // showKeyIfSecret
)
expect(headers[0].value).toBe(`Basic ${btoa("testuser:testpass")}`)
})
})
})

View file

@ -5,29 +5,35 @@ import {
HoppRESTHeader,
} from "@hoppscotch/data"
/**
* UTF-8 safe base64 encoding. Standard btoa() throws on non-ASCII chars,
* so we encode through TextEncoder first.
*/
function utf8Btoa(str: string): string {
const bytes = new TextEncoder().encode(str)
let binary = ""
for (const byte of bytes) {
binary += String.fromCharCode(byte)
}
return btoa(binary)
}
export async function generateBasicAuthHeaders(
auth: HoppRESTAuth & { authType: "basic" },
envVars: Environment["variables"],
showKeyIfSecret = false
// `showKeyIfSecret` is intentionally not forwarded to `parseTemplateString()` here.
// The base64 encoding must always use actual values, otherwise the
// Authorization header is unusable (see #5863).
_showKeyIfSecret = false
): Promise<HoppRESTHeader[]> {
const username = parseTemplateString(
auth.username,
envVars,
false,
showKeyIfSecret
)
const password = parseTemplateString(
auth.password,
envVars,
false,
showKeyIfSecret
)
const username = parseTemplateString(auth.username, envVars, false, false)
const password = parseTemplateString(auth.password, envVars, false, false)
return [
{
active: true,
key: "Authorization",
value: `Basic ${btoa(`${username}:${password}`)}`,
value: `Basic ${utf8Btoa(`${username}:${password}`)}`,
description: "",
},
]