8000 Task queue emulator incorrectly decodes base64 payload with atob(), should be Buffer.from(..., "base64") · Issue #8836 · firebase/firebase-tools · GitHub
[go: up one dir, main page]

Skip to content

Task queue emulator incorrectly decodes base64 payload with atob(), should be Buffer.from(..., "base64") #8836

@CodingDoug

Description

@CodingDoug

[REQUIRED] Environment info

firebase-tools: 14.9.0

Platform: macOS

[REQUIRED] Test case

The emulator doesn't decode strings with non-ascii utf8 characters correctly, for example, emoji.

Enqueue a task using firebase-admin in one (http) function:

const taskData = {"key":"some value with a utf-8 character, such as emoji"}
const queue = getFunctions().taskQueue("someTask")
await queue.enqueue(taskData)

Receive it:

export default async function someTask(req: TaskRequest) {
    // does not print the original character
    console.log(req.data.key)
}

[REQUIRED] Steps to reproduce

Run the emulator, invoke the http function that enqueues task, watch the task print the unexpected value.

[REQUIRED] Expected behavior

It should print exactly the utf-8 string that was enqueued.

[REQUIRED] Actual behavior

It prints a "junk" decoding.

The problem is that the emulator uses the JavaScript atob() function to decode the base64 payload created by the Admin SDK. Here is what the Admin SDK does (correctly):

https://github.com/firebase/firebase-admin-node/blob/master/src/functions/functions-api-client-internal.ts#L244C15-L244C71

body: Buffer.from(JSON.stringify({ data })).toString('base64'),

Here is what the emulator does (incorrectly):

https://github.com/firebase/firebase-tools/blob/master/src/emulator/tasksEmulator.ts#L271

req.body.task.httpRequest.body = JSON.parse(atob(req.body.task.httpRequest.body));

atob() uses the JavaScript native utf-16 internal encoding for strings, however, this incorrectly decodes anything with a codepoint above 256. What the emulator should do instead is use Buffer.from(data, "base64").toString("utf-8").

Here is a bit of node repl that illustrates the expected translation, including JSON parsing:

> b64 = Buffer.from(JSON.stringify({"A":"👍"})).toString('base64')
'eyJBIjoi8J+RjSJ9'
> JSON.parse(Buffer.from(b64, "base64").toString("utf-8"))
{ A: '👍' }

Note that the production Cloud Functions works fine - it's just the emulator that doesn't decode task payloads correctly.

< 537A div class="CommentDivider-module__CommentDividerContainer--fCCZA">

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0