google / google/arb-editor

Path traversal / arbitrary local file read via @@x-template (and l10n.yaml) template path

Open
#91 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
64
Forks
11
Avg merge
2d 3h
Merged PRs (30d)
18

Description

### Summary

`Parser.resolveTemplatePath()` passes a workspace-controlled path straight to `fs.readFileSync` without any containment check, so a crafted `.arb` file (or `l10n.yaml`) can make the extension read **any file the editing user can open**, outside the project.

- **Version:** 0.2.2 (HEAD `a6fa5a3`)
- **Source:** the `@@x-template` field of an `.arb` file, or `arb-dir` / `template-arb-file` in `l10n.yaml`
- **Sink:** `src/messageParser.ts:243` — `fs.readFileSync(templatePath, "utf8")`
- **Resolve:** `src/messageParser.ts:207-218` — no `..` rejection, no workspace containment, absolute paths returned as-is

### Steps to reproduce

1. In any Flutter/ARB project, set the template field of an `.arb` file:
```json
{ "@@locale": "es", "@@x-template": "../../../../../../../../../../etc/passwd" }
```
(`path.join` clamps surplus `..` at the filesystem root, so this lands on `/etc/passwd` regardless of where the repo is cloned; an absolute path works too.)
2. Open the project in VS Code with the ARB Editor extension installed and open the `.arb` file.
3. The extension's parser runs and calls `fs.readFileSync("/etc/passwd")` — a file entirely outside the workspace.

### Impact

- **Arbitrary local file read.** Any file readable by the user can be opened by the extension as a side effect of editing a repository.
- **Disclosure channel.** For JSON-with-string-values targets, the top-level keys are echoed into the Problems panel as `Missing messages from template: ` (`src/diagnose.ts`), surfacing file contents (key names) to the editing user — useful for exfiltration via a repo the attacker later inspects, or simply for tricking a victim.
- **Extension-host DoS (sub-case).** The read is synchronous and follows symlinks; pointing the template at `/dev/zero`, a FIFO, or a multi-GB file blocks the extension host.

The same unchecked path also reaches the sink through the `l10n.yaml` (`arb-dir` + `template-arb-file`) branch.

### Suggested fix

Resolve the candidate path and reject anything that escapes the workspace folder (fall back to the document directory when there is no workspace folder). Legitimate in-project templates are unaffected. PR attached.

This was reported through Google's VRP and closed as out of scope for that program; filing here so the project can fix it directly.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.