Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,15 @@ jobs:
BROWSER_PATH="${{ steps.build_dir.outputs.build_dir }}/lib/playwright/driver/package/.local-browsers"
echo "Checking browser installation at: $BROWSER_PATH"
ls -la "$BROWSER_PATH" || echo "Browser directory not found"
find "$BROWSER_PATH" -type f -name "chrome*" -o -name "chromium*" | head -5 || echo "No browser binaries found"
echo ""
echo "Looking for chromium_headless_shell directories:"
find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium_headless_shell-*" || echo "No chromium_headless_shell directories found"
echo ""
echo "Looking for browser executables:"
find "$BROWSER_PATH" -type f \( -name "chrome-headless-shell" -o -name "chrome-headless-shell*" -o -name "chrome*" -o -name "chromium*" \) | head -10 || echo "No browser binaries found"
echo ""
echo "Checking directory structure:"
find "$BROWSER_PATH" -type d -name "*chrome*" -o -name "*chromium*" | head -10 || echo "No browser directories found"

- name: Create package directory structure
id: package
Expand Down
42 changes: 36 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,43 @@ The framework focuses on **intelligent security analysis** through:

### Prerequisites
- Docker (required)
- Python 3.11+
- Playwright: `playwright install`
- curl (for installation script)

### Installation

**Recommended: Install from release (Linux x86_64 / macOS ARM64)**

```bash
# Install via pipx (recommended)
pipx install deadend_cli
# Install latest release
curl -fsSL https://raw.githubusercontent.com/xoxruns/deadend-cli/main/install.sh | bash

# Or build from source
# Or install a specific version
curl -fsSL https://raw.githubusercontent.com/xoxruns/deadend-cli/main/install.sh | bash -s -- --version v1.0.0

# Custom installation directory (default: ~/.cache/server)
curl -fsSL https://raw.githubusercontent.com/xoxruns/deadend-cli/main/install.sh | bash -s -- --install-dir /path/to/install
```

The installer will:
- Download pre-built binaries for your platform
- Install the RPC server to `~/.cache/server` (or custom directory)
- Install the CLI binary to `~/.local/bin` (or `/usr/local/bin` on macOS)
- Set up Playwright browsers automatically

**Alternative: Build from source**

```bash
git clone https://github.com/xoxruns/deadend-cli.git
cd deadend-cli
uv sync && uv build
```

**Legacy: Install via pipx**

```bash
pipx install deadend_cli
```

### First Run
```bash
# Initialize configuration
Expand All @@ -81,6 +104,12 @@ deadend chat \
--prompt "find SQL injection vulnerabilities"
```

**Note:** If `deadend` is not found, ensure `~/.local/bin` is in your PATH:
```bash
export PATH="$HOME/.local/bin:$PATH"
# Add to ~/.bashrc or ~/.zshrc to make it permanent
```

---

## Usage Examples
Expand Down Expand Up @@ -189,8 +218,9 @@ deadend chat --target URL --mode yolo
- **Instructor**: Structured LLM outputs
- **pgvector**: Vector database for context
- **Pyodide/WebAssembly**: Python sandbox
- **Playwright**: HTTP request generation
- **Playwright**: HTTP request generation (bundled with browser binaries)
- **Docker**: Shell command isolation
- **PyOxidizer**: Standalone binary packaging

---

Expand Down
4 changes: 4 additions & 0 deletions deadend_cli/installer/deadend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Include both lib and numpy/libs directories for OpenBLAS and other shared libraries
export LD_LIBRARY_PATH="${SCRIPT_DIR}/lib:${SCRIPT_DIR}/lib/numpy/libs${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"

# Set PLAYWRIGHT_BROWSERS_PATH so Playwright knows where to find browsers
# This must point to the .local-browsers directory
export PLAYWRIGHT_BROWSERS_PATH="${SCRIPT_DIR}/lib/playwright/driver/package/.local-browsers"

# Ensure Playwright driver has execute permissions
if [ -f "${SCRIPT_DIR}/lib/playwright/driver/node" ]; then
chmod +x "${SCRIPT_DIR}/lib/playwright/driver/node" 2>/dev/null
Expand Down
9 changes: 9 additions & 0 deletions deadend_cli/installer/fix_permissions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ fi
# Fix all shell scripts in playwright
find "$INSTALL_DIR/lib/playwright" -type f \( -name "*.sh" -o -name "playwright*" \) -exec chmod +x {} \; 2>/dev/null

# Fix browser executables in .local-browsers
BROWSER_PATH="$INSTALL_DIR/lib/playwright/driver/package/.local-browsers"
if [ -d "$BROWSER_PATH" ]; then
echo "Fixing permissions for Playwright browsers..."
find "$BROWSER_PATH" -type f \( -name "chrome-headless-shell" -o -name "chrome-headless-shell*" -o -name "chrome*" -o -name "chromium*" \) -exec chmod +x {} \; 2>/dev/null || true
# Also fix permissions in subdirectories
find "$BROWSER_PATH" -type d -name "*chrome*" -exec find {} -type f -exec chmod +x {} \; \; 2>/dev/null || true
fi

# Fix any other executables that might need it
find "$INSTALL_DIR/lib" -type f \( -name "node" -o -name "*.so" \) -exec chmod +x {} \; 2>/dev/null

Expand Down
124 changes: 88 additions & 36 deletions deadend_cli/installer/install_playwright_browsers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,49 +32,101 @@ if [ "$IS_MACOS" = false ]; then
fi
python3 -m pip install playwright $PIP_FLAGS

# First, install browsers to default location to get the version
python3 -m playwright install chromium
# Set PLAYWRIGHT_BROWSERS_PATH to install directly to target location
export PLAYWRIGHT_BROWSERS_PATH="$BROWSER_PATH"

# Find the installed chromium version
PLAYWRIGHT_CACHE="${HOME}/.cache/ms-playwright"
CHROMIUM_DIR=$(find "$PLAYWRIGHT_CACHE" -maxdepth 1 -type d -name "chromium-*" 2>/dev/null | head -n 1)
# Install chromium-headless-shell (the headless browser Playwright uses)
echo "Installing chromium-headless-shell to $BROWSER_PATH..."
python3 -m playwright install chromium-headless-shell

if [ -z "$CHROMIUM_DIR" ]; then
# Try alternative location (macOS)
PLAYWRIGHT_CACHE="${HOME}/Library/Caches/ms-playwright"
CHROMIUM_DIR=$(find "$PLAYWRIGHT_CACHE" -maxdepth 1 -type d -name "chromium-*" 2>/dev/null | head -n 1)
fi
# Target version - must be exactly 1208
TARGET_VERSION="1208"
TARGET_DIR_NAME="chromium_headless_shell-$TARGET_VERSION"
TARGET_DIR="$BROWSER_PATH/$TARGET_DIR_NAME"

if [ -n "$CHROMIUM_DIR" ]; then
CHROMIUM_VERSION=$(basename "$CHROMIUM_DIR" | sed 's/chromium-//')
echo "Found Chromium version: $CHROMIUM_VERSION"

# Copy to the target location with the expected name format
TARGET_DIR="$BROWSER_PATH/chromium_headless_shell-$CHROMIUM_VERSION"
mkdir -p "$TARGET_DIR"
cp -r "$CHROMIUM_DIR"/* "$TARGET_DIR/"
# Verify installation
if [ -d "$BROWSER_PATH" ]; then
echo "Browser installation successful"
echo "Browser directory contents:"
ls -la "$BROWSER_PATH"

echo "Copied Chromium $CHROMIUM_VERSION to $TARGET_DIR"
echo "Browser files:"
ls -la "$TARGET_DIR" | head -10
else
echo "Warning: Could not find installed Chromium browser"
echo "Attempting to install directly to target location..."
# Check for chromium-headless-shell directory (Playwright creates it with hyphens)
# Also check for chromium_headless_shell (with underscores) in case it was renamed
HEADLESS_SHELL_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d \( -name "chromium-headless-shell-*" -o -name "chromium_headless_shell-*" \) | head -n 1)

# Set PLAYWRIGHT_BROWSERS_PATH and try installing again
export PLAYWRIGHT_BROWSERS_PATH="$BROWSER_PATH"
python3 -m playwright install chromium
# Also check for chromium directory as fallback
if [ -z "$HEADLESS_SHELL_DIR" ]; then
CHROMIUM_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium-*" | head -n 1)
if [ -n "$CHROMIUM_DIR" ]; then
echo "Found chromium directory, will use it to create $TARGET_DIR_NAME"
HEADLESS_SHELL_DIR="$CHROMIUM_DIR"
fi
fi

# Check if it worked
if [ -d "$BROWSER_PATH" ]; then
echo "Browser installation to target location successful"
ls -la "$BROWSER_PATH"
# Rename if needed
if [ -n "$HEADLESS_SHELL_DIR" ]; then
HEADLESS_SHELL_NAME=$(basename "$HEADLESS_SHELL_DIR")
echo "Found browser directory: $HEADLESS_SHELL_NAME"

# Rename or copy to the exact version name (chromium_headless_shell-1208)
if [ "$HEADLESS_SHELL_NAME" != "$TARGET_DIR_NAME" ]; then
echo "Renaming $HEADLESS_SHELL_NAME to $TARGET_DIR_NAME (version 1208)"
if [ -d "$TARGET_DIR" ]; then
echo "Target directory already exists, removing it first..."
rm -rf "$TARGET_DIR"
fi
mv "$HEADLESS_SHELL_DIR" "$TARGET_DIR"
echo "✓ Successfully renamed to $TARGET_DIR_NAME"
else
echo "✓ Directory already has correct name: $TARGET_DIR_NAME"
fi

# Verify the target directory exists
if [ -d "$TARGET_DIR" ]; then
echo "Browser executable check:"
find "$TARGET_DIR" -type f -name "chrome-headless-shell" -o -name "chrome-headless-shell*" | head -5 || echo "Checking for browser executables..."
find "$TARGET_DIR" -type d -name "*chrome*" | head -5 || echo "Checking for browser directories..."

# Fix permissions on browser executables
echo "Fixing permissions on browser executables..."
find "$TARGET_DIR" -type f \( -name "chrome-headless-shell" -o -name "chrome-headless-shell*" -o -name "chrome*" -o -name "chromium*" \) -exec chmod +x {} \; 2>/dev/null || true
find "$TARGET_DIR" -type d -name "*chrome*" -exec find {} -type f -exec chmod +x {} \; \; 2>/dev/null || true
else
echo "Error: Target directory $TARGET_DIR_NAME was not created"
exit 1
fi
else
echo "Warning: No chromium_headless_shell or chromium directory found"
echo "Trying to find any chromium-related directories..."
find "$BROWSER_PATH" -maxdepth 1 -type d | head -10

# Try installing regular chromium as fallback
echo "Attempting to install regular chromium as fallback..."
python3 -m playwright install chromium

# Check if chromium was installed
CHROMIUM_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium-*" | head -n 1)
if [ -n "$CHROMIUM_DIR" ] && [[ "$CHROMIUM_DIR" != *"chromium_headless_shell"* ]]; then
CHROMIUM_VERSION=$(basename "$CHROMIUM_DIR" | sed 's/chromium-//')
mv "$CHROMIUM_DIR" "$BROWSER_PATH/chromium_headless_shell-$CHROMIUM_VERSION"
echo "Renamed to chromium_headless_shell-$CHROMIUM_VERSION"
if [ -n "$CHROMIUM_DIR" ]; then
echo "Found chromium directory, creating $TARGET_DIR_NAME from it"
if [ -d "$TARGET_DIR" ]; then
rm -rf "$TARGET_DIR"
fi
cp -r "$CHROMIUM_DIR" "$TARGET_DIR"
echo "✓ Created $TARGET_DIR_NAME from chromium installation"
# Fix permissions
find "$TARGET_DIR" -type f \( -name "chrome*" -o -name "chromium*" \) -exec chmod +x {} \; 2>/dev/null || true
else
echo "Error: Could not find chromium installation after fallback attempt"
exit 1
fi
fi

# Final verification that the target directory exists with the correct name
if [ ! -d "$TARGET_DIR" ]; then
echo "Error: Final verification failed - $TARGET_DIR_NAME does not exist"
exit 1
fi
echo "✓ Final verification: $TARGET_DIR_NAME exists and is ready"
else
echo "Error: Browser installation failed - directory not created"
exit 1
fi
Loading