pentest-lyan-web-security-testing
Autonomous web penetration testing skill with threat modeling, JavaScript analysis, and multi-role verification
How do I install this agent skill?
npx skills add https://github.com/reason-machines/security-skills --skill pentest-lyan-web-security-testingIs this agent skill safe to install?
- Gen Agent Trust Hubfail
The skill instructs the agent to store user credentials in plaintext in a local file, which is a major security risk. It also downloads code from an unverified GitHub repository and processes external website content, making it susceptible to indirect prompt injection.
- Socketwarn
1 alert: gptSecurity
- Snykwarn
Risk: MEDIUM · 1 issue
What does this agent skill do?
Pentest-Lyan Web Security Testing
Skill by ara.so — Security Skills collection.
Pentest-Lyan is an autonomous web penetration testing framework that performs self-directed threat modeling across 12 dimensions, complete JavaScript analysis, and cross-role verification. It validates business impact (not just HTTP 200 responses), maintains state across sessions, and generates both technical Markdown and delivery-ready Word reports.
What It Does
- Autonomous Threat Modeling: Identifies threats based on 12 thinking dimensions rather than fixed vulnerability checklists
- Deep JavaScript Analysis: Reads and understands business logic, signing mechanisms, and frontend parameters before testing APIs
- Business Impact Validation: Verifies database-layer changes, data access, and state transitions actually occur
- Multi-Role Testing: Builds permission matrices and performs cross-role privilege escalation checks
- Stateful Testing: Supports resume (
--resume), multi-project isolation, and session pooling - Dual Report Formats: Markdown for technical details, Word for delivery; separates critical findings from configuration issues
Installation
Prerequisites
- Python 3.8+ with the project dependencies
- Playwright MCP Server (recommended for browser automation and session pooling)
Setup Steps
# Clone the repository
git clone https://github.com/HeaSec/Pentest-Lyan.git
cd Pentest-Lyan
# Install Python dependencies (if requirements.txt exists)
pip install -r requirements.txt
# Install as a Claude Code skill
# Copy the entire pentest-lyan/ directory to your Claude Code skills path
# Default locations:
# - macOS/Linux: ~/.config/claude-code/skills/
# - Windows: %APPDATA%\claude-code\skills\
cp -r . ~/.config/claude-code/skills/pentest-lyan/
Playwright MCP Setup (Optional but Recommended)
# Install Playwright MCP for browser automation
npm install -g @playwright/mcp-server
# Or add to your MCP configuration
# The skill will use curl if Playwright is unavailable
Project Structure
pentest-lyan/
├── SKILL.md # Main orchestrator (3 phases, 9 exit conditions)
├── gates.md # HARD GATE definitions (G1-G7)
├── schema.md # Data schema index
├── references/ # Process documentation (read by agent as needed)
│ ├── discovery-guide.md
│ ├── attack-guide.md
│ ├── threat-modeling.md
│ ├── validation-guide.md
│ ├── cross-role-testing.md
│ ├── audit-guide.md
│ ├── report-template.md
│ ├── docx-template.md
│ └── post-delivery.md
├── schema/ # Field specification schemas (*.schema.json)
├── scripts/ # Utility scripts
│ └── render_docx.py
└── templates/ # Word document templates
Basic Usage
Starting a New Security Test
# Basic invocation
/pentest-lyan https://target.example.com
# Provide credentials (required for proper testing)
/pentest-lyan https://target.example.com
账号:
- admin/Admin@123 (role_level: high_privilege)
- user1/User@123 (role_level: standard)
- user2/User@123 (role_level: standard)
Important: No need to declare authorization scope/timeframe — issuing the command implies authorization.
Multi-Project Management
# List all projects
/pentest-lyan --list
# Resume an existing project
/pentest-lyan --resume <project-id>
# Start with custom project ID
/pentest-lyan https://target.example.com --project custom-id
Default project-id is extracted from the hostname's first segment.
Testing Phases
Pentest-Lyan executes in three sequential phases:
Phase 1: Discovery
- Deep JavaScript analysis (business logic, signing, parameters)
- Complete API endpoint discovery
- Session pool creation
- Permission matrix generation
Phase 2: Attack
- Feature-level testing pipeline
- Dynamic sub-module discovery
- Cross-role privilege verification
- Business impact validation
Phase 3: Audit
- Schema validation
- Completeness auditing
- System-level checks
- Report generation (Markdown + Word)
Account Requirements (G1 Gate)
The G1 gate checks account availability but does not block testing:
- ≥2 accounts: Normal flow, full cross-role testing
- 0-1 accounts: Degraded mode, limited privilege testing; if registration page found, report prompts user to register additional accounts
role_level must be explicitly declared by the user (not inferred from username):
high_privilege: Admin, superuser, managerstandard: Regular userlimited: Guest, read-only
Working with State Files
Pentest-Lyan maintains state in pentest-data/<project-id>/:
pentest-data/
└── <project-id>/
├── state.json # Main state (phase, coverage, findings)
├── index.json # Project metadata
├── pages/ # Discovered pages/APIs
├── sessions/ # Session data (contains credentials)
├── modules/ # Feature module state
└── coverage/ # Coverage tracking
State File Example
{
"project_id": "example-com",
"phase": "discovery",
"target": "https://example.com",
"accounts": [
{
"username": "admin",
"password": "REDACTED",
"role_level": "high_privilege"
}
],
"discovered_endpoints": [],
"findings": [],
"coverage": {}
}
Security Warning: pentest-data/ contains plaintext credentials. Add to .gitignore:
# Add to .gitignore
echo "pentest-data/" >> .gitignore
echo "pentest-report/" >> .gitignore
Threat Modeling Dimensions
Pentest-Lyan uses 12 autonomous threat dimensions:
- Authentication: Session, token, multi-factor bypasses
- Authorization: Horizontal/vertical privilege escalation, IDOR
- Input Validation: Injection, XSS, path traversal
- Business Logic: Workflow bypasses, race conditions
- Data Exposure: Sensitive data leaks, information disclosure
- Session Management: Fixation, hijacking, timeout issues
- Cryptography: Weak algorithms, improper key management
- Configuration: Default credentials, unnecessary services
- API Security: Rate limiting, parameter tampering
- File Handling: Upload bypasses, arbitrary file operations
- Error Handling: Stack traces, verbose errors
- Third-Party: Dependency vulnerabilities, external service abuse
Code Examples
Extending Validation Logic (Python)
# Example: Custom validator for business impact
# File: custom_validators.py
import requests
import json
def validate_discount_manipulation(session, endpoint, payload):
"""
Verify that discount manipulation actually affects the database.
Returns True if vulnerability is confirmed.
"""
# Apply discount
resp = session.post(
endpoint,
json=payload,
headers={"Content-Type": "application/json"}
)
if resp.status_code != 200:
return False
# Retrieve order to confirm database change
order_id = resp.json().get("order_id")
verify_resp = session.get(f"/api/orders/{order_id}")
if verify_resp.status_code == 200:
order_data = verify_resp.json()
expected_price = payload.get("discounted_price")
actual_price = order_data.get("total_price")
# Confirm business impact
return actual_price == expected_price
return False
# Use in validation-guide.md workflow
Reading JavaScript for Signing Logic
# Example: Extracting signing mechanism from JS
# The agent performs this during discovery phase
import re
import requests
def extract_signing_function(js_url):
"""
Download and parse JavaScript to find signing functions.
"""
resp = requests.get(js_url)
js_content = resp.text
# Look for common signing patterns
signing_patterns = [
r'function\s+sign\([^)]*\)\s*{([^}]+)}',
r'const\s+sign\s*=\s*\([^)]*\)\s*=>\s*{([^}]+)}',
r'\.sign\s*=\s*function\([^)]*\)\s*{([^}]+)}'
]
for pattern in signing_patterns:
matches = re.findall(pattern, js_content)
if matches:
return {
"signing_function": matches[0],
"algorithm": detect_algorithm(matches[0])
}
return None
def detect_algorithm(func_body):
"""Detect crypto algorithm from function body."""
if 'md5' in func_body.lower():
return 'md5'
elif 'sha256' in func_body.lower():
return 'sha256'
elif 'hmac' in func_body.lower():
return 'hmac'
return 'unknown'
Permission Matrix Generation
# Example: Building permission matrix for cross-role testing
# File: permission_matrix.py
def build_permission_matrix(endpoints, sessions):
"""
Test each endpoint with each role to build permission matrix.
Returns matrix of {endpoint: {role: accessible}}.
"""
matrix = {}
for endpoint in endpoints:
matrix[endpoint["path"]] = {}
for session_info in sessions:
role = session_info["role_level"]
session = session_info["session"]
# Test access
resp = session.get(
endpoint["url"],
allow_redirects=False
)
# Determine if accessible
accessible = resp.status_code in [200, 201, 204]
matrix[endpoint["path"]][role] = {
"accessible": accessible,
"status_code": resp.status_code
}
return matrix
# Example matrix output:
# {
# "/api/admin/users": {
# "high_privilege": {"accessible": True, "status_code": 200},
# "standard": {"accessible": False, "status_code": 403}
# },
# "/api/profile": {
# "high_privilege": {"accessible": True, "status_code": 200},
# "standard": {"accessible": True, "status_code": 200}
# }
# }
Cross-Role Privilege Testing
# Example: Test privilege escalation using permission matrix
# File: cross_role_test.py
def test_privilege_escalation(matrix, sessions):
"""
Use permission matrix to find privilege escalation vulnerabilities.
"""
findings = []
for endpoint, roles in matrix.items():
# Find endpoints accessible to high_privilege but not standard
if (roles.get("high_privilege", {}).get("accessible") and
not roles.get("standard", {}).get("accessible")):
# Test with standard user using high_privilege user's ID
standard_session = get_session_by_role(sessions, "standard")
high_priv_user_id = get_user_id_by_role(sessions, "high_privilege")
# Attempt access with victim ID (not hardcoded)
test_url = endpoint.replace("{user_id}", str(high_priv_user_id))
resp = standard_session.get(test_url)
if resp.status_code in [200, 201]:
findings.append({
"type": "privilege_escalation",
"endpoint": endpoint,
"description": f"Standard user can access high_privilege endpoint",
"evidence": {
"url": test_url,
"status": resp.status_code,
"attacker_role": "standard",
"victim_role": "high_privilege"
}
})
return findings
Report Generation
Markdown Report
Generated automatically at end of audit phase:
# Reports are written to:
pentest-report/<project-id>_<timestamp>.md
Structure:
- Executive Summary
- Findings (Critical → High → Medium → Low)
- Coverage Analysis (answers: input surface, behavior surface, depth)
- Appendix (configuration issues, not_vulnerable with unruled_out)
Word Report
# scripts/render_docx.py
import sys
from docx import Document
from docx.shared import Inches, Pt, RGBColor
def render_docx(markdown_path, output_path, template_path=None):
"""
Convert Markdown report to Word document.
Args:
markdown_path: Path to .md report
output_path: Path for output .docx
template_path: Optional custom template
"""
doc = Document(template_path) if template_path else Document()
with open(markdown_path, 'r', encoding='utf-8') as f:
content = f.read()
# Parse markdown and apply styles
sections = parse_markdown(content)
for section in sections:
if section['type'] == 'heading1':
doc.add_heading(section['text'], level=1)
elif section['type'] == 'finding':
add_finding_block(doc, section['data'])
elif section['type'] == 'code':
add_code_block(doc, section['text'])
doc.save(output_path)
# Usage:
# python scripts/render_docx.py pentest-report/example-com_2026.md output.docx
Configuration
Environment Variables
# Optional: Custom data directory
export PENTEST_DATA_DIR="/secure/location/pentest-data"
# Optional: Report output directory
export PENTEST_REPORT_DIR="/reports"
# Optional: Playwright MCP endpoint
export PLAYWRIGHT_MCP_URL="http://localhost:3000"
# Optional: Rate limiting (requests per second)
export PENTEST_RATE_LIMIT="5"
# Optional: Timeout for requests (seconds)
export PENTEST_TIMEOUT="30"
Custom Gate Configuration
Edit gates.md to adjust gate thresholds:
# G1: Account Gate
Threshold: ≥2 accounts (degraded mode if fewer)
# G2: JavaScript Coverage Gate
Threshold: ≥80% of main bundles analyzed
# G3: Endpoint Discovery Gate
Threshold: ≥5 unique endpoints or complete sitemap
Common Patterns
Pattern 1: Testing with Multiple Accounts
# The framework automatically manages session pools
# You provide credentials at invocation:
/pentest-lyan https://api.example.com
Accounts:
- admin@example.com/SecurePass123! (role_level: high_privilege)
- user@example.com/UserPass456! (role_level: standard)
- guest@example.com/GuestPass789! (role_level: limited)
Pattern 2: Resuming After Interruption
# List projects to find ID
/pentest-lyan --list
# Output:
# example-com | Phase: attack | Findings: 3 | Status: in_progress
# Resume
/pentest-lyan --resume example-com
Pattern 3: Custom Threat Module
Create a custom module in references/custom-threats/:
# custom-payment-logic.md
## Threat: Payment Amount Manipulation
**Coverage Questions:**
- Input surface: price, quantity, discount_code, currency
- Behavior surface: calculate_total, apply_discount, process_payment
- Depth: Database transaction verification, audit log check
**Test Steps:**
1. Capture legitimate payment request
2. Modify `amount` parameter to $0.01
3. Replay request
4. Verify database: SELECT amount FROM orders WHERE order_id = ?
5. Check audit logs for amount mismatch
**Validation:**
- Status 200 alone is NOT sufficient
- Must confirm database shows manipulated amount
- Must confirm payment gateway charged manipulated amount
Troubleshooting
Issue: "No endpoints discovered"
Cause: JavaScript not fully analyzed or SPA routing not detected.
Solution:
# Check if JS bundles were downloaded
ls pentest-data/<project-id>/pages/
# Verify Playwright MCP is running
curl http://localhost:3000/health
# Force re-discovery
rm pentest-data/<project-id>/state.json
/pentest-lyan --resume <project-id>
Issue: "G1 gate: insufficient accounts"
Cause: Fewer than 2 accounts provided.
Solution: This is a soft gate — testing continues in degraded mode.
- Provide additional accounts and re-run
- Or continue and register accounts manually if prompted in report
Issue: "Validation failed: status 200 but no business impact"
Cause: Response is 200 but database/state unchanged.
Solution: This is correct behavior (not a bug).
- Pentest-Lyan requires verification of actual state change
- Check validation-guide.md for proper validation steps
- Customize validators if needed (see Code Examples above)
Issue: Session expires during testing
Cause: Long-running tests exceed session timeout.
Solution:
# Pentest-Lyan auto-refreshes sessions
# If custom session handling needed, extend:
# File: custom_session_refresh.py
def refresh_session(session_info):
"""Re-authenticate if session expired."""
login_resp = requests.post(
f"{session_info['base_url']}/api/login",
json={
"username": session_info["username"],
"password": session_info["password"]
}
)
return login_resp.cookies.get("session_token")
Issue: Report missing findings
Cause: Findings not properly recorded in state.json.
Solution:
# Validate state file structure
python -c "
import json
with open('pentest-data/<project-id>/state.json') as f:
state = json.load(f)
print(f'Findings: {len(state.get(\"findings\", []))}')
"
# Check findings schema
cat schema/findings.schema.json
Issue: Word report rendering fails
Cause: Missing python-docx or template corruption.
Solution:
# Install dependencies
pip install python-docx
# Re-render with default template
python scripts/render_docx.py \
pentest-report/<project-id>.md \
output.docx
# Or specify custom template
python scripts/render_docx.py \
pentest-report/<project-id>.md \
output.docx \
--template templates/custom-template.docx
Security Best Practices
-
Credential Management:
- Never commit
pentest-data/to version control - Use environment variables for sensitive config
- Follow post-delivery cleanup (see
references/post-delivery.md)
- Never commit
-
Authorization:
- Only test systems you have explicit permission to test
- Issuing
/pentest-lyan <target>implies authorization
-
Data Handling:
- Encrypt
pentest-data/andpentest-report/after testing - Clear sessions after delivery:
rm -rf pentest-data/<project-id>/sessions/
- Encrypt
-
Rate Limiting:
- Set
PENTEST_RATE_LIMITto avoid overwhelming targets - Default: 5 req/s (configurable)
- Set
Advanced Usage
Custom Validation Pipeline
# File: advanced_validation.py
from typing import Dict, Any, List
def extended_validation_pipeline(finding: Dict[str, Any]) -> bool:
"""
Extended validation requiring multiple confirmation steps.
"""
validators = [
validate_http_response,
validate_database_state,
validate_audit_log,
validate_side_effects
]
results = []
for validator in validators:
result = validator(finding)
results.append(result)
# Log validation step
log_validation_step(
finding_id=finding['id'],
validator=validator.__name__,
result=result
)
# All validators must pass
return all(results)
def validate_database_state(finding: Dict[str, Any]) -> bool:
"""Verify database reflects the exploit."""
# Implementation specific to finding type
pass
def validate_audit_log(finding: Dict[str, Any]) -> bool:
"""Check if suspicious activity was logged."""
# Absence of logging may itself be a finding
pass
def validate_side_effects(finding: Dict[str, Any]) -> bool:
"""Verify no unintended side effects occurred."""
pass
Integration with CI/CD
# .github/workflows/security-test.yml
name: Automated Security Testing
on:
schedule:
- cron: '0 2 * * 0' # Weekly on Sunday 2 AM
jobs:
pentest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Pentest-Lyan
run: |
git clone https://github.com/HeaSec/Pentest-Lyan.git
cd Pentest-Lyan
pip install -r requirements.txt
- name: Run Security Test
env:
TEST_ADMIN_USER: ${{ secrets.TEST_ADMIN_USER }}
TEST_ADMIN_PASS: ${{ secrets.TEST_ADMIN_PASS }}
TEST_USER_USER: ${{ secrets.TEST_USER_USER }}
TEST_USER_PASS: ${{ secrets.TEST_USER_PASS }}
run: |
/pentest-lyan https://staging.example.com \
--account "$TEST_ADMIN_USER/$TEST_ADMIN_PASS (role_level: high_privilege)" \
--account "$TEST_USER_USER/$TEST_USER_PASS (role_level: standard)"
- name: Upload Report
uses: actions/upload-artifact@v3
with:
name: security-report
path: pentest-report/*.md
Additional Resources
- Threat Modeling Reference — 12 dimension framework
- Cross-Role Testing Guide — Permission matrix usage
- Validation Guide — Business impact verification
- Schema Guide — State file structure
- Report Templates — Markdown report structure
- Post-Delivery Checklist — Cleanup procedures
License: MIT
Repository: https://github.com/HeaSec/Pentest-Lyan
Issues: https://github.com/HeaSec/Pentest-Lyan/issues
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/reason-machines/security-skills/pentest-lyan-web-security-testing">View pentest-lyan-web-security-testing on skillZs</a>