Skip to content

Conversation

@Iamrodos
Copy link
Contributor

@Iamrodos Iamrodos commented Jan 13, 2026

Closes #477

First commit.

Fine-grained personal access tokens cannot download attachments from private repositories due to a GitHub limitation. Add a workaround for image attachments using GitHub's Markdown API to convert URLs to JWT-signed URLs.

  • Tested with fine-grained token on private repo: /assets/ URLs download via workaround, /files/ URLs fail as expected
  • Include a startup warning when using --attachments with fine-grained tokens.
  • Files that can't be downloaded with a fine-grained PAT are noted in the attachments manifest and not attempted.
  • Document limitation in README

Second commit.

Refactor test fixtures to use shared create_args helper (uses real parse_args() so new CLI args are automatically available to all tests). This makes the tests more robust to CLI changes. Changing the CLI should no longer require modifying existing tests.

…alez#477)

Fine-grained personal access tokens cannot download attachments from
private repositories directly due to a GitHub platform limitation.

This adds a workaround for image attachments (/assets/ URLs) using
GitHub's Markdown API to convert URLs to JWT-signed URLs that can be
downloaded without authentication.

Changes:
- Add get_jwt_signed_url_via_markdown_api() function
- Detect fine-grained token + private repo + /assets/ URL upfront
- Use JWT workaround for those cases, mark success with jwt_workaround flag
- Skip download with skipped_at when workaround fails
- Add startup warning when using --attachments with fine-grained tokens
- Document limitation in README (file attachments still fail)
- Add 6 unit tests for JWT workaround logic
Uses the real parse_args() function to get CLI defaults, so when
new arguments are added they're automatically available to all tests.

Changes:
- Add tests/conftest.py with create_args fixture
- Update 8 test files to use shared fixture
- Remove duplicate _create_mock_args methods
- Remove redundant @pytest.fixture mock_args definitions

This eliminates the need to update multiple test files when
adding new CLI arguments.
@josegonzalez josegonzalez merged commit 65bacc2 into josegonzalez:master Jan 13, 2026
10 checks passed
@lukasbestle
Copy link
Contributor

@Iamrodos Thanks for the fix. Sorry I only saw it after it was merged, GitHub didn't send me a notification for the PR.

I just tested it and ran into two issues:

  • I use github-backup with --keychain-name and --keychain-account instead of with --token-fine. Just checking for the presence of the --token-fine argument will create a false negative. There is also the case of a token coming from the macOS keychain but that token being a fine token. I think we instead need some kind of global flag that controls whether the token is fine or classic. This flag could then be set by get_auth(). The keychain code would auto-detect based on the token prefix.
  • For some reason, I still get 404 responses for some URLs of the format https://github.com/org/repo/assets/.../.... I'll try to debug this further and open a separate issue.

@Iamrodos
Copy link
Contributor Author

Well that does complicate things a bit. I like your ideas on detecting the token type, I will do some research in the codebase.

Yes, if you can find more details about 404s that you are not expecting that would be great.

Rather than a new issue, should #477 be reopened? I am not familiar with the convention in such circumstances. That would be my preference.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Some attachments in private repos are not downloaded (HTTPError: Not Found), but can be accessed in a browser session

3 participants