integrations / integrations/terraform-provider-github

data "github_release_asset": download_file_contents uses browser_download_url, fails with fine-grained PATs on private repos

Open
#3,324 1 comment 7 reactions 0 assignees View on GitHub
Status: Triage
Dominant language
Go
Stars
1.2k
Forks
1k
Avg merge
1d 14h
Merged PRs (30d)
8

Description

### Description

The `data "github_release_asset"` data source with `download_file_contents = true` downloads files via `browser_download_url` (the web endpoint at `github.com/…`). Fine-grained personal access tokens (PATs) cannot authenticate against this web endpoint for **private** repositories, resulting in a 404.

The correct approach for authenticated asset downloads is to use the **API endpoint** (`api.github.com/repos/OWNER/REPO/releases/assets/ASSET_ID`) with `Accept: application/octet-stream`, which properly handles both classic and fine-grained PATs.

### Terraform Version

```
1.14.8
```

### Affected Resource(s)

- `data "github_release_asset"` (with `download_file_contents = true`)

### Expected Behavior

When configured with a fine-grained PAT that has `Contents: read` permission on a private repository, `data "github_release_asset"` with `download_file_contents = true` should successfully download the asset.

### Actual Behavior

The data source returns a 404 error because it fetches the asset using `browser_download_url` (`https://github.com/OWNER/REPO/releases/download/TAG/FILENAME`), which does not accept fine-grained PAT authentication for private repositories.

### Root Cause

In [`data_source_github_release_asset.go`](https://github.com/integrations/terraform-provider-github/blob/main/github/data_source_github_release_asset.go), the download path uses `asset.GetBrowserDownloadURL()`:

```go
downloadUrl := asset.GetBrowserDownloadURL()
```

This URL points to the web endpoint (`github.com/…`), not the REST API endpoint (`api.github.com/…`). Fine-grained tokens are not valid for the web endpoint on private repos.

### Suggested Fix

Use the REST API endpoint for the download instead. The API URL is available via `asset.GetURL()` and the download can be performed by sending an authenticated GET request with `Accept: application/octet-stream`.

### Workaround

We currently use `data "external"` with a shell script that calls curl against the API endpoint:

```bash
curl -fsSL \
-H "Authorization: token $TOKEN" \
-H "Accept: application/octet-stream" \
-o "$DEST" \
"$API_URL"
```

where `$API_URL` is `asset.url` from `data "github_release"` (the API endpoint), rather than `browser_download_url`.

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.