Description
My team has been working very hard on new features for our flag printing program! I wonder how they'll work together?
Download the provided challenge.zip archive.
Extract it locally and move into the drop-in repository where the Git history lives.
wget https://artifacts.picoctf.net/c_titan/71/challenge.zip && \
unzip challenge.zip && \
cd drop-in/Solution
- Step 1List every branchgit branch -a reveals the feature/part-* branches that contain pieces of the flag. They're local copies already, so you can check them out directly.
git branch -aLearn more
Git branches are lightweight pointers to commits, enabling parallel lines of development. The
-aflag (all) shows both local branches and remote-tracking branches (remotes/origin/...). In a distributed workflow, each developer typically works on a feature branch, preventing conflicts with others' work until an intentional merge.The branch naming convention
feature/part-1follows the GitFlow branching model, where feature branches are prefixed withfeature/. Other common conventions includefeat/, issue numbers (issue-123), or author initials. Consistent naming makes it easy to understand a branch's purpose at a glance.In security research, inspecting all branches of a repository can reveal sensitive information that was accidentally committed to a feature branch and never merged. Credentials, API keys, and partial implementations are sometimes found in abandoned branches that developers forgot existed. Tools like
truffleHogandgit-secretsautomate this kind of branch-wide secret scanning. - Step 2Inspect each feature branchCheckout each branch and read flag.py. Every branch prints a different slice of the flag, intentionally split to encourage review of multiple branches.
git checkout feature/part-1 && cat flag.pyRepeat for feature/part-2 and feature/part-3 to gather the middle and final segments.Learn more
git checkout <branch>switches your working directory to a different branch, updating all tracked files to match that branch's latest commit. It's one of the most frequently used Git commands, and in modern Git (2.23+) the more explicitgit switch <branch>command is preferred for branch switching whilegit checkoutis reserved for file restoration.Splitting a secret across multiple branches demonstrates a real security concern: sensitive data spread across feature branches may be harder to detect than a single committed secret. Automated secrets scanners need to check every branch, not just the default branch, to provide complete coverage.
This pattern also illustrates collaborative Git workflows: in practice, multiple developers submit pull requests (PRs) from feature branches. Code reviewers must examine each branch individually before approving a merge. Understanding how to navigate branches quickly is essential for both development productivity and security auditing.
- Step 3Optional: merge for a single viewIf you prefer one unified output, merge the feature branches into main (in any order) and resolve the minor conflicts. The combined flag prints once the merges complete.
git checkout main && \ git merge feature/part-1 feature/part-2 feature/part-3Learn more
git mergeintegrates changes from one or more branches into the current branch. When multiple branches modify the same file in the same location, Git creates a merge conflict - it marks the conflicting sections and requires a human to choose how to resolve them. This is a fundamental part of collaborative development.Git uses a three-way merge algorithm: it finds the common ancestor commit of both branches and compares each branch's changes against that ancestor. Changes that don't overlap are merged automatically; overlapping changes become conflicts. Understanding this algorithm helps predict when conflicts will occur and how to structure commits to minimize them.
In production workflows, merges are often done via pull requests on platforms like GitHub or GitLab, which add code review, CI/CD checks, and discussion threads before the merge happens. The
--no-ffflag forces a merge commit even when a fast-forward is possible, preserving branch history in the commit graph for auditing purposes.
Flag
picoCTF{t3@mw0rk_m@k3s_th3_dr3@m_w0rk_4c2...}
Concatenate the outputs from each feature/part-* branch (or resolve the merged file) to reveal the full flag above.