gitmd2pdf

Git Security — converting private repositories

Converting a private repository through gitmd2pdf requires credentials, because our server has to fetch it from your git host the same way your laptop would. This page walks through the recommended workflow, the alternatives, and what gitmd2pdf does with the credentials you supply.

Short answer: put your username in the repository URL, then enter your Personal Access Token (or whatever your host calls it — see the provider table) in the dedicated field that appears below. Use a short-lived, scoped, read-only token — not your account password. Revoke the token after a one-off conversion.

TL;DR by provider

Host What to create Where to find it Scope
GitHub Personal Access Token (PAT) — fine-grained recommended Settings → Developer settings → Personal access tokens Contents: Read on the target repo only
GitLab Project Access Token or Deploy Token Settings → Access Tokens / Repository → Deploy tokens read_repository
Bitbucket Repository Access Token or App Password Repository settings → Access tokens / Personal settings → App passwords Repository: Read only
Azure DevOps Personal Access Token (PAT) User Settings → Personal access tokens Code: Read on the project
Self-hosted Whatever your server's equivalent is Your admin / docs Read-only on the single repo

In every case: scope the token to one repository, not your whole account, set an expiry of weeks rather than "no expiry", and revoke the token immediately if the conversion was a one-off. PATs are designed to be cheap to create + revoke — that's the whole point of using them rather than your password.

How to convert a private repository

Step 1 — Create a Personal Access Token

In your git host's settings panel (links above), create a token with read-only access to the repository you want to convert. Keep the token visible — you'll paste it in step 3.

Step 2 — Paste the repository URL with your username

In the Dashboard's Repository tab, paste a URL of the form:

https://YOUR-USERNAME@github.com/your-org/your-repo.git
https://YOUR-USERNAME@gitlab.com/your-namespace/your-project.git
https://YOUR-USERNAME@bitbucket.org/your-workspace/your-repo.git

Substitute your actual git-host login for YOUR-USERNAME. Do NOT include the token here — leave the part after @ as just the host + path.

When you paste a URL of this shape, the form recognises that the host needs authentication and reveals a Personal Access Token field below the URL.

Step 3 — Enter the token in the dedicated field

Type (or paste) your PAT into the Personal Access Token field. Click Convert to PDF.

That's it. The token is forwarded to the converter through a subprocess environment variable (never command-line argv, never written to disk), and the working directory is deleted as soon as the PDF is generated.

Why is the username in the URL and not a separate form field?

HTTPS git authentication needs two values: a username and a credential. They both ride in the URL like https://USER:CRED@host/.... The dashboard splits them so the token gets entered in a separate password-type input (so browsers don't autocomplete it, sync it across devices, or leak it via referrer headers), but keeps the username in the URL itself for one important reason: single source of truth. An earlier version of the form had a separate username input — pre-filled from the URL, but editable. The result was confusing UX: two places to enter a username, with the field silently overriding the URL prefix on the wire. Removed in change-248. The URL prefix is now the canonical username source.

If your token type needs a magic-string username (oauth2, x-token-auth, etc. — see the table below), edit the URL prefix to use that string. For example: https://myers@gitlab.com/org/repo.git becomes https://oauth2@gitlab.com/org/repo.git for a GitLab Project Access Token.

What username should I put in the URL?

For most token types the username is just your account login — but several token types require a literal magic-string username instead. If your token type isn't your standard account login, edit the USER portion of the URL before submitting.

Token type Username to put in the URL prefix
GitHub Personal Access Token (classic + fine-grained) Your GitHub login (or any non-empty string — GitHub ignores it for PAT auth)
GitHub App installation token x-access-token
GitHub Actions GITHUB_TOKEN (inside a workflow) x-access-token
GitLab Personal Access Token Your GitLab login (or oauth2)
GitLab Project Access Token oauth2
GitLab Deploy Token The deploy-token's name (the name, not its scope)
GitLab CI_JOB_TOKEN (inside a pipeline) gitlab-ci-token
Bitbucket Repository Access Token x-token-auth
Bitbucket App Password Your Bitbucket login
Azure DevOps PAT Empty or any non-empty string
Self-hosted (Gitea, Forgejo, Codeberg, etc.) Whatever your host's docs say — usually your login

If your conversion fails with a 403 Forbidden or fatal: Authentication failed error and you're confident the token is valid, the URL-prefix username is the most likely culprit — try the magic-string equivalent for your token type before regenerating the token.

Alternative: put the token directly in the URL

If you'd rather embed the token in the URL — for example, you have automation that already builds URLs of this shape — that also works. The format is:

https://YOUR-USERNAME:YOUR-TOKEN@github.com/your-org/your-repo.git
https://oauth2:YOUR-TOKEN@gitlab.com/your-namespace/your-project.git
https://x-token-auth:YOUR-TOKEN@bitbucket.org/your-workspace/your-repo.git

Paste the whole URL into the Repository tab and convert. Everything after https:// up to the @ is the credential portion — gitmd2pdf never stores it, and the redaction step (described below) strips it from the PDF and from any log output.

Why the username-in-URL + PAT-in-field flow is preferred: the URL itself can leak through browser history, bookmark sync, referrer headers, and shared error reports. Anything you put in the URL field is at risk through those channels. The dedicated PAT field has none of those leak vectors — it's a password-type input that browsers don't autofill or sync.

Can I use my account password instead of a PAT?

Technically yes — most git hosts still accept your account password where they accept a token (use it as the :password half of the URL or in the PAT field). Don't. Reasons:

If you're going to type a credential into a form, type a PAT.

What gitmd2pdf does on your behalf

What you should avoid

Putting credentials in places that leak:

If a PAT is exposed by any channel, revoke it immediately at your provider and issue a new one. That's the whole point of using short-lived scoped tokens — revocation is cheap.

API users — send the token in the request body

If you're calling the Premium API rather than using the Dashboard, send the token in the repoCredentials body field instead of embedding it in the URL:

curl -X POST https://yourapp.com/api/v1/convert \
  -H "Authorization: Bearer YOUR_API_BEARER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "repo",
    "repoUrl": "https://github.com/your-org/your-repo.git",
    "repoCredentials": {
      "username": "your-github-login",
      "token": "ghp_..."
    }
  }'

Both username and token are required when repoCredentials is present (HTTPS git auth needs both halves). The token is forwarded to the converter via subprocess env (NOT process argv), so it never appears in ps output, access logs, or MongoDB.

Coming Soon: stored credentials

A future Premium feature will let you save scoped tokens server-side — encrypted at rest with a KMS-managed key, audit-logged, and referenced by ID in the convert request — so you don't have to paste the token on every conversion. Today's flow (single-use per request, no storage) is the safe default until that lands.

SSH URLs

The web UI accepts only http:// and https:// URLs today. The Premium API v1 additionally accepts git@host:path and ssh://… URLs for customers on Premium integrations. SSH auth against a private repo requires keys that are pre-provisioned on the converter host — if you need that pattern for an enterprise or self-hosted deployment, contact us and we'll walk through the options.

When in doubt

Related: How do I convert a private GitHub or GitLab repository? in the FAQ covers the same workflow at a lower level of detail.