qinglong/SANDBOX_TESTING.md
copilot-swe-agent[bot] 34b06b06f0 Add comprehensive sandbox testing documentation
Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
2025-11-17 12:42:25 +00:00

3.6 KiB

Filesystem Sandbox Testing

This document describes how to test the filesystem sandbox feature that protects Qinglong from malicious scripts.

The Vulnerability (Before Fix)

The original issue demonstrated that a malicious script could modify critical system files:

const fs = require("fs")
const path = require("path")
fs.writeFileSync(path.join(__dirname, "..", "..", 'config', 'task_after.sh'), `echo 123`)

This would allow the script to inject code that runs after every other script, compromising the entire system.

The Fix

The sandbox intercepts filesystem operations and blocks writes to protected directories:

Protected Directories

  • /back - Backend code
  • /src - Frontend code
  • /shell - Shell scripts
  • /sample - Sample files
  • /node_modules - Dependencies
  • /data/config - Configuration files (including task_after.sh, task_before.sh)
  • /data/db - Database files

Allowed Directories

  • /data/scripts - User scripts
  • /data/log - Logs
  • /data/repo - Repositories
  • /data/raw - Raw data
  • /.tmp and /tmp - Temporary files

Testing the Fix

Quick Test

Run the exploit script to verify it's blocked:

cd /home/runner/work/qinglong/qinglong
export QL_DIR=$(pwd)
export QL_DATA_DIR=$(pwd)/data

# Try the exploit
cat > data/scripts/test_exploit.js << 'EOF'
const fs = require("fs");
const path = require("path");
try {
  fs.writeFileSync(path.join(__dirname, "..", "..", 'config', 'task_after.sh'), `echo 123`);
  console.log("❌ VULNERABILITY: Exploit succeeded!");
  process.exit(1);
} catch (error) {
  if (error.code === 'EACCES') {
    console.log("✅ SECURE: Exploit blocked!");
    process.exit(0);
  }
  throw error;
}
EOF

NODE_OPTIONS="-r ./shell/preload/sandbox.js" node data/scripts/test_exploit.js

Expected output: ✅ SECURE: Exploit blocked!

Comprehensive Testing

The repository includes comprehensive tests:

  1. Node.js Tests: Verify that Node.js scripts cannot write to protected paths
  2. Python Tests: Verify that Python scripts cannot write to protected paths
  3. Allowed Writes: Verify that legitimate writes still work
  4. Disable Option: Verify that the sandbox can be disabled when needed

Configuration

Enable Sandbox (Default)

The sandbox is enabled by default. No configuration needed.

To disable the sandbox:

export QL_DISABLE_SANDBOX=true

Warning: Disabling the sandbox removes all filesystem protections and allows scripts to modify any file, including critical system files.

How It Works

Node.js

  • Loads shell/preload/sandbox.js before script execution
  • Wraps fs module methods (writeFile, appendFile, mkdir, unlink, etc.)
  • Checks paths before allowing write operations
  • Returns EACCES error for protected paths

Python

  • Loads shell/preload/sandbox.py before script execution
  • Wraps builtins.open() for write modes
  • Wraps os module functions (remove, mkdir, rename, etc.)
  • Wraps shutil operations (rmtree, copy, move, etc.)
  • Wraps pathlib.Path methods (write_text, mkdir, unlink, etc.)
  • Raises PermissionError for protected paths

Security Impact

This fix prevents:

  • Modification of task_before.sh and task_after.sh
  • Modification of system scripts
  • Modification of configuration files
  • Injection of code into other scripts
  • Compromise of the entire Qinglong installation

Scripts can still:

  • Read any files (read-only access)
  • Write to their own directory (/data/scripts)
  • Write logs
  • Write to temporary directories
  • Perform all legitimate operations