A tool for creating customizable sandboxed Linux environments for educational testing and evaluation.
qo enables instructors to create secure and reproducible testing environments where students can complete coding challenges in isolated Linux sandboxes. The tool provides complete control over available commands and binaries while automatically generating detailed evaluation reports.
- Secure Sandboxing: Creates isolated Linux environments using namespaces for safe student testing
- Time-Locked Challenges: Encrypts challenge archives with unlock times to prevent early access
- Customizable Environments: Control exactly which binaries and commands are available to students
- Reproducible: Ensures consistent testing environments across different machines
- Linux operating system (required for sandboxing features).
- Go installed on your system.
Run this command to install qo.
curl -fsSL https://raw.githubusercontent.com/Open-Source-Community/qo2/main/setup.sh | bash- Prepare your challenge folder with levels and check scripts
- Build and encrypt the challenge archive:
For example:
qo build -f <challenge folder> -p <password> -k <starterkey> -u <unlock date and time>
qo build -f ./my-challenges -p mypassword -k starterkey -u "2025-12-01 14:30"
- Start the test session with the encrypted archive:
For example:
sudo qo start -i <student id> -a <challenge archive> -p <password> -k <starter key> -d <duration>
Note: Setting duration is not implemented yet. The option is accepted but has no effect.sudo qo start -i 2021170034 -a test.enc -p mypassword -k starterkey -d 90m
Prepares and encrypts challenge folders for secure distribution to students.
Workflow:
- Validates challenge folder structure and scripts
- Compresses folder into archive format
- Encrypts with time-lock and starter key
- Outputs ready-to-distribute encrypted file
Required Flags:
-f, --folder— Path to challenge folder-p, --password— Archive encryption password-k, --key— Starter key for students-u, --unlock-time— Unlock time (YYYY-MM-DD HH:MMformat)
Optional Flags:
-o, --output— Output path (default:eval-archive.enc)
Example:
qo build -f ./challenges -p securepass -k abc123 -u "2025-07-10 09:30" -o midterm-exam.encLaunches secure testing environment for students to complete challenges.
Workflow:
- Prompts for Student ID (used in reports and logs)
- Verifies starter key and enforces unlock time
- Creates isolated sandbox environment
- Extracts challenges and starts interactive shell
- Monitors all commands and activities
- Generates evaluation report upon completion
Required Flags:
-i, --id— Student ID-a, --archive— Path to encrypted challenge archive-p, --password— Archive decryption password-k, --key— Starter key provided by instructor-d, --duration— Test duration (e.g.,90m,2h,1h30m) (accepted but not implemented yet)
Optional Flags:
-o, --output— Results directory (default:eval-results) (not implemented yet)
Example:
sudo qo start -i 2021170034 -a midterm-exam.enc -p securepass -k abc123 -d 2h Your challenge folder should follow this structure:
challenges/
├── level1/
│ ├── README.md
│ ├── check.sh
│ ├── .base_flag
│ ├── hint.txt
│ └── files/
├── level2/
│ ├── README.md
│ ├── check.sh
│ ├── .base_flag
│ ├── hint.txt
│ └── files/
└── README.md
Each level should contain:
- README.md: Challenge instructions for students
- check.sh: Automated validation script (read-only by the tool, kept out of the sandbox)
- hint.txt / hint1.txt, hint2.txt, ...: Progressive hints, delivered read-only to the student's sandbox
- .base_flag: Per-level secret used to derive each student's unique flag (kept out of the sandbox)
- files/: Any supporting files needed
Students solve the task described in the level's README.md inside their own
sandbox shell. When ready, they run ./check.sh (delivered as a thin stub). The
stub relays the request over a session-scoped Unix socket to the privileged
parent, which runs the real script inside a chrooted child and returns the full
diagnostic output — exactly like the historical tool. On success the parent
replaces the hardcoded key="..." with a per-student flag derived via HMAC over
(base_flag, student_id), so every student gets their own flag.
Students never touch /tmp. On first login they set up their challenge folders
from the root-only pristine staging area:
qo-setup # copies every level into ~/challenges/
qo-setup level1 # or just one level
cd ~/challenges/level1
cat README.md
./check.sh # verified from homeA level whose files were corrupted can be restored at any time:
qo-reset level1 # wipe ~/challenges/level1 and re-copy pristine filesBoth commands relay over the same socket as qo-check; the parent copies only
non-secret data and never exposes the real check.sh or the base flag.
First, extract the rootfs.
# in qo/pkg/sandbox/
sudo tar -xzvf rootfs.tar.gzThen, check if the binary you would like to add is available in busybox.
# in qo/pkg/sandbox/bin/
./busybox --list | grep [command]You will encounter one of two cases:
Create a symbolic link to busybox with the name of the binary.
ln -s busybox [command]In this case, you can copy the binary (along with its dependencies) from your system to the environment. To do so, use the provided script:
# In qo/scripts/
./inject.sh /usr/bin/gcc /path/to/your/rootfs
./inject.sh /bin/nano /path/to/your/rootfsIm both cases, make sure to recompress the rootfs and recompile after modification.
# in qo/pkg/sandbox/
sudo tar -czvf rootfs.tar.gz rootfs
cd ../..
# In qo/
go installYou can customize the sandbox environment by modifying:
- Available commands and utilities
- File system permissions
- Available users and groups, etc
- Command Monitoring: Log all student commands and activities during testing sessions
- Automated Reporting: Generate comprehensive PDF reports of student performance
- Set Challenge Duaration: Automatically end the session after a specified duration