Summary
POST /project/<id>/export_github creates a public GitHub repository on the user's account with no visibility prompt or consent. The repo payload hard-codes "private": False, so a learner who clicks "Export to GitHub" exposes their starter project publicly (code, repo name, description) even if they only wanted a private copy.
Evidence
src/routes/main_routes.py:438-447:
username = user_resp.json().get('login')
# 2. Create the repository
repo_payload = {
"name": repo_name,
"description": f"Starter code for DevPath project: {project['title']}",
"private": False, # <-- hard-coded public
"auto_init": False
}
create_resp = requests.post("https://api.github.com/user/repos", json=repo_payload, headers=headers)
The route only checks that the user is logged in (session.get('github_token'), lines 383-388). There is no UI option to choose public vs private and no checkbox in project.html's export flow.
Note also the 422 branch (lines 449-450): if the repository name already exists, the route silently proceeds to push the file into that existing repo, so a repeat click can push into a repo the user did not intend (and may not own a matching one for).
Impact
- Unwanted public exposure of starter code and per-user repo names on GitHub.
- Pushing into an existing repo on name collision is surprising and could modify an unrelated repository.
Suggested Fix
- Ask for visibility (public/private) in the export UI and pass it through (or default to private and let the user opt in to public).
- On 422, detect that the repo already exists and either update the intended repo explicitly or return a clear error instead of blind-pushing.
Summary
POST /project/<id>/export_githubcreates a public GitHub repository on the user's account with no visibility prompt or consent. The repo payload hard-codes"private": False, so a learner who clicks "Export to GitHub" exposes their starter project publicly (code, repo name, description) even if they only wanted a private copy.Evidence
src/routes/main_routes.py:438-447:The route only checks that the user is logged in (
session.get('github_token'), lines 383-388). There is no UI option to choose public vs private and no checkbox inproject.html's export flow.Note also the 422 branch (lines 449-450): if the repository name already exists, the route silently proceeds to push the file into that existing repo, so a repeat click can push into a repo the user did not intend (and may not own a matching one for).
Impact
Suggested Fix