Skip to main content

MY GIT picoCTF 2026 Solution

Git takes the commit author from client config, so set your name and email to root, push flag.txt, and the flag lands.

Published: March 20, 2026Updated: September 20, 2026

Description

I have built my own Git server with my own rules! You want the flag - make sure to push the flag. Only flag.txt pushed by root (name: root, email: root@picoctf) will be updated with the flag.

Launch the challenge instance and clone the repository using the provided command.
Note the password shown on the challenge page.

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Clone the repository
    Observation
    The instance page gives an HTTP Git URL and a password, so there is a remote repository to clone before anything else.
    Clone the repository using the command provided on the challenge page. Note the password.
    bash
    git clone http://<HOST>:<PORT_FROM_INSTANCE>/repo.git
    bash
    cd repo
    What didn't work first

    Tried: Browsing to the repo URL in a browser to look for files or the flag directly

    The server speaks the Git smart-HTTP protocol, not a file browser, so a browser gets an empty index page. The flag only appears after the right commit is pushed.

    Tried: Cloning with SSH instead of the provided HTTP URL

    The challenge instance does not expose an SSH port - only the HTTP port shown on the challenge page is open. An SSH clone attempt will time out or be refused. Use the exact URL format provided.

    Learn more

    This challenge has a server-side Git hook that runs when you push commits. The hook checks the committer name and email - it only updates flag.txt if the push comes from a commit with name root and email root@picoctf. Git allows you to set any name and email locally, so you can impersonate this identity.

  2. Step 2Configure git identity as root
    Observation
    The description says only a flag.txt pushed by a committer named root, at root@picoctf, triggers the flag. Set the local git identity to match before committing.
    Set your local git user name to 'root' and email to 'root@picoctf'. These values appear in commit metadata and the server hook checks them.
    bash
    git config user.name root
    bash
    git config user.email root@picoctf
    What didn't work first

    Tried: Setting the global git config (git config --global user.name root) instead of the local repo config

    The global form writes to your user gitconfig and affects every repository you own. It works here, as long as you set it before committing, but it is easy to forget afterwards. Setting it locally inside the clone is safer.

    Tried: Setting the GIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL environment variables instead of the committer fields

    Git separates the author, who wrote the change, from the committer, who recorded it, and the hook checks the committer. Set only the author variables and the committer still comes from your real config, so the push is rejected.

    Learn more

    Git commit metadata (author name and email) is entirely client-controlled. There is no authentication binding a git identity to an actual user. This is why signed commits (GPG or SSH signing) exist - to provide cryptographic proof that a commit came from a specific key, not just a self-reported name.

    The challenge illustrates a real security risk: if a server grants permissions based on the committer name/email in the commit object, any client can impersonate any identity by simply changing their local git config.

  3. Step 3Create flag.txt, commit, and push
    Observation
    The hook watches for a flag.txt pushed under that identity, so creating the file and pushing it brings the real flag back in the push output.
    Create a flag.txt file, stage it, commit with the root identity, and push. The server hook will detect the commit came from 'root' and update flag.txt with the flag.
    bash
    touch flag.txt
    bash
    git add flag.txt
    bash
    git commit -m 'add flag'
    bash
    git push
    bash
    # Enter the password from the challenge page when prompted

    Expected output

    picoCTF{1mp3rs0n4t4_g17_345y_...}
    What didn't work first

    Tried: Committing flag.txt with actual flag content (e.g. the placeholder picoCTF{...}) hoping the hook will accept it

    The hook never looks inside flag.txt. It checks the committer identity, then overwrites the file with the real flag on its side. Whatever you put in the file changes nothing; the flag comes back in the push response.

    Tried: Forgetting to enter the password and pressing Enter at the prompt, then trying to read flag.txt from the local clone

    An empty password fails authentication and the push is rejected before the hook runs at all. And even on success, the flag arrives in the push output rather than in your working tree; a pull brings the file down.

    Learn more

    The server-side Git hook (typically a post-receive or update hook) runs after you push. It inspects the committer identity in the pushed commits. Since we configured our local git to use name "root" and email "root@picoctf", the hook recognizes this as the privileged identity and replaces flag.txt with the actual flag content, which the hook then echoes back in the push output.

Interactive tools
  • Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
  • Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.

Flag

Reveal flag

picoCTF{1mp3rs0n4t4_g17_345y_...}

Configure git user.name=root and user.email=root@picoctf, create flag.txt, commit, and push. The server hook grants the flag to commits from 'root'.

Key takeaway

Commit metadata is self-reported by the client with no cryptographic binding to anyone: any developer sets the name and email to whatever they like before committing. Access control built on those fields falls to plain impersonation, exactly as a server trusting a username in an HTTP header would. Authenticate at the transport layer with SSH keys or tokens, and sign commits when you need proof of authorship that holds up.

How to prevent this

Git commit identity is completely client-controlled. Never grant permissions based on committer name or email.

  • Use signed commits (GPG or SSH signing) if you need to verify who made a commit. The signature is cryptographically tied to a private key the committer controls, unlike the name/email which anyone can set to anything.
  • Authenticate at the transport layer (SSH keys, HTTPS tokens) rather than inside commit metadata. The connection identity is harder to fake than the metadata inside the commit object.

Related reading

Useful tools for General Skills

Where to go next