Skip to content

fix(gmail): re-pad base64url attachment data for standard decoder compatibility#834

Open
nuthalapativarun wants to merge 1 commit into
googleworkspace:mainfrom
nuthalapativarun:fix/774-base64url-attachment-padding
Open

fix(gmail): re-pad base64url attachment data for standard decoder compatibility#834
nuthalapativarun wants to merge 1 commit into
googleworkspace:mainfrom
nuthalapativarun:fix/774-base64url-attachment-padding

Conversation

@nuthalapativarun
Copy link
Copy Markdown

Description

Google's API returns unpadded base64url data for gmail.users.messages.attachments.get. Standard decoders in Python, Node.js, and other languages require = padding and fail when len % 4 != 0.

This fix detects the gmail.users.messages.attachments.get method and appends the correct number of = padding characters to the data field before returning the response. Scoped to this one method to avoid unintended side effects.

Closes #774

Checklist:

  • My code follows the AGENTS.md guidelines (no generated google-* crates).
  • I have run cargo fmt --all to format the code perfectly.
  • I have run cargo clippy -- -D warnings and resolved all warnings.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have provided a Changeset file (e.g. via pnpx changeset) to document my changes.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 2, 2026

🦋 Changeset detected

Latest commit: 5a9a1dd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where the Gmail API returns unpadded base64url strings for attachments, causing failures in standard decoders that expect specific padding. By introducing a targeted padding function in the executor, the system now ensures that attachment data is correctly formatted before further processing, improving reliability across different environments.

Highlights

  • Base64url Padding Fix: Implemented a mechanism to detect and add missing '=' padding to base64url encoded attachment data returned by the Gmail API, ensuring compatibility with standard decoders.
  • Scoped Execution: The padding logic is specifically scoped to the 'gmail.users.messages.attachments.get' method to prevent unintended side effects on other API responses.
  • Comprehensive Testing: Added multiple unit tests to verify correct padding behavior for various input lengths, handling of already-padded data, and resilience against invalid JSON.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a fix to re-pad base64url-encoded attachment data in Gmail API responses, ensuring compatibility with standard decoders. The feedback points out that parsing and re-serializing the entire JSON response is highly inefficient for large attachments (up to 25MB) and suggests an in-place string scanning approach to avoid significant CPU overhead and memory allocations.

Comment on lines +1204 to +1218
fn pad_attachment_data(body: String) -> String {
let mut val: Value = match serde_json::from_str(&body) {
Ok(v) => v,
Err(_) => return body,
};

if let Some(obj) = val.as_object_mut() {
if let Some(Value::String(data)) = obj.get_mut("data") {
let padding = (4 - data.len() % 4) % 4;
data.push_str(&"=".repeat(padding));
}
}

serde_json::to_string(&val).unwrap_or_else(|_| body)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Parsing and re-serializing the entire JSON response body just to append a few padding characters to the data field is highly inefficient, especially for large Gmail attachments (which can be up to 25MB). This approach causes significant CPU overhead and multiple large memory allocations.

Instead, we can perform a highly efficient, in-place string scan to locate the "data" key and append the padding characters directly to the String without parsing or re-serializing the JSON.

fn pad_attachment_data(mut body: String) -> String {
    let mut start_idx = 0;
    while let Some(key_idx) = body[start_idx..].find("\"data\"").map(|idx| start_idx + idx) {
        let rest = &body[key_idx + 6..];
        if let Some(colon_relative_idx) = rest.find(|c: char| !c.is_whitespace()) {
            if rest.as_bytes()[colon_relative_idx] == b':' {
                let after_colon = &rest[colon_relative_idx + 1..];
                if let Some(quote_relative_idx) = after_colon.find(|c: char| !c.is_whitespace()) {
                    if after_colon.as_bytes()[quote_relative_idx] == b'"' {
                        let value_start = key_idx + 6 + colon_relative_idx + 1 + quote_relative_idx + 1;
                        let after_quote = &body[value_start..];
                        if let Some(quote_end) = after_quote.find('"') {
                            let value_end = value_start + quote_end;
                            let data_str = &body[value_start..value_end];
                            if data_str.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') {
                                let padding = (4 - data_str.len() % 4) % 4;
                                if padding > 0 {
                                    body.insert_str(value_end, &"=".repeat(padding));
                                }
                                return body;
                            }
                        }
                    }
                }
            }
        }
        start_idx = key_idx + 6;
    }
    body
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gmail attachments get: unpadded base64url data breaks standard decoders

2 participants