Skip to content

Base64 encoding of vault path produces "/" character, breaking server URL #71

Description

@Huangzeref

Body

### Description

When the vault path contains certain byte sequences (commonly found in CJK characters like Chinese, Japanese, Korean), `Buffer.from(path).toString("base64")` can produce a `/` character in the output. Since `/` is a URL path separator, the generated URL is truncated at that point, causing the server to receive an incomplete base64 string. The decoded path is then garbage and the plugin fails to connect.

### Root Cause

`main.js:938`:
```js
const encodedPath = Buffer.from(this.projectDirectory).toString("base64");
return `http://${this.settings.hostname}:${this.settings.port}/${encodedPath}`;

Standard Base64 (RFC 4648) uses 64 characters: A-Za-z0-9+/=. The / is the 63rd character (value 63 = 111111 in binary). When 3 bytes of the UTF-8 encoded path are grouped into four 6-bit values, any group that equals 63 will produce a /.

This is not limited to a few specific characters. The condition is common: when any CJK character's UTF-8 last byte ends in 1111 (which occurs for ~1312 CJK characters, including many common ones), and the next character's first byte starts with 11 (true for all CJK characters), the cross-byte 6-bit value becomes 111111 = 63 = /.

Example

  • Vault path: E:\some\path\生活笔记库vps
  • Base64: RTpcaHVhbmdteFxvYnNpZGlhblznlJ/mtLvnrJTorrDlupN2cHM=
  • The znlJ**/m**tLv portion contains / from the byte boundary between (0x9F) and (0xE6)
  • Resulting URL (truncated): http://127.0.0.1:14096/RTpcaHVhbmdteFxvYnNpZGlhblznlJ
  • Server sees: RTpcaHVhbmdteFxvYnNpZGlhblznlJ → decoded: garbage path → health check fails

Expected Behavior

The URL should contain the complete base64-encoded path, regardless of which characters appear in the vault name.

Suggested Fix

Option 1 (minimal): URL-encode the base64 string before embedding in the URL:

getUrl() {
    const encodedPath = Buffer.from(this.projectDirectory).toString("base64");
    return `http://${this.settings.hostname}:${this.settings.port}/${encodeURIComponent(encodedPath)}`;
}

Option 2 (more robust): Use Base64url encoding (RFC 4648 §5), which replaces + with - and / with _:

getUrl() {
    const encodedPath = Buffer.from(this.projectDirectory)
        .toString("base64")
        .replace(/\+/g, "-")
        .replace(/\//g, "_")
        .replace(/=+$/, "");
    return `http://${this.settings.hostname}:${this.settings.port}/${encodedPath}`;
}

Note: If the opencode server expects standard Base64, Option 1 is safer. If the server side also switches to base64url in the future, Option 2 is cleaner.

Environment

  • Plugin version: 0.2.1
  • OS: Windows
  • Vault name contains CJK characters

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions