| name | pentesting-checklist-interactive |
| description | Interactive security assessment checklist covering 23 platforms with 1000+ checks for penetration testing, bug bounty, and security audits |
| triggers | ["use the pentesting checklist tool","open security assessment checklist","start a pentest with the checklist","track penetration testing progress","export security assessment findings","search pentesting checks","filter security checklist by severity","manage pentest assessment notes"] |
PentestingChecklist Interactive Skill
Skill by ara.so — Security Skills collection.
Overview
PentestingChecklist is a comprehensive, client-side security assessment checklist covering 23 platforms with over 1,000 security checks. It runs entirely in the browser with no backend, storing all progress and notes in localStorage. The tool provides hierarchical organization (Platform → Category → Technology → Check), global search, progress tracking, severity filtering, and export capabilities for penetration testers, bug bounty hunters, and security engineers.
Key platforms covered: Web Application, API, Mobile, Cloud (AWS/Azure/GCP), Active Directory, Kubernetes, LLM Security, MCP Security, Blockchain, IoT, CI/CD, and 12 more.
Live instance: checklist.m14r41.in
Installation & Setup
Running Locally
git clone https://github.com/m14r41/PentestingChecklist.git
cd PentestingChecklist
npm install
npm run dev
npm run build
npm run preview
Project Structure
PentestingChecklist/
├── src/
│ ├── components/ # React components
│ ├── data/ # Checklist data files
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions
│ └── App.tsx # Main application
├── public/ # Static assets
└── package.json
Core Concepts
Data Structure
The checklist uses a 4-level hierarchy:
interface Platform {
id: string;
name: string;
description: string;
categories: Category[];
}
interface Category {
id: string;
name: string;
technologies: Technology[];
}
interface Technology {
id: string;
name: string;
checks: Check[];
}
interface Check {
id: string;
title: string;
description: string;
severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
tags: string[];
tools?: string[];
references?: string[];
}
State Management
All assessment data is stored in localStorage:
interface AssessmentState {
checkStatus: Record<string, 'open' | 'closed' | 'na'>;
checkNotes: Record<string, string>;
progress: {
overall: number;
perPlatform: Record<string, number>;
perCategory: Record<string, number>;
};
}
Key Features & Usage
1. Navigation & Hierarchy
Expand/Collapse All:
const expandAll = () => {
setExpandedCategories(new Set(categories.map(c => c.id)));
setExpandedTechnologies(new Set(technologies.map(t => t.id)));
};
const collapseAll = () => {
setExpandedCategories(new Set());
setExpandedTechnologies(new Set());
};
Platform-specific views:
/checklist - All platforms view
/web - Web Application platform
/api - API Security platform
/mobile - Mobile Security platform
/cloud - Cloud Security platform
/active-directory - Active Directory platform
/kubernetes - Kubernetes Security platform
/llm - LLM Security platform
/mcp - MCP Security platform
- (and 14 more platform-specific routes)
2. Global Search (⌘K / Ctrl+K)
Search across all content types:
const searchChecklist = (query: string) => {
const results = [];
platforms.forEach(platform => {
platform.categories.forEach(category => {
category.technologies.forEach(technology => {
technology.checks.forEach(check => {
const searchable = [
check.title,
check.description,
...check.tags,
...(check.tools || []),
...(check.references || [])
].join(' ').toLowerCase();
if (searchable.includes(query.toLowerCase())) {
results.push({
platform: platform.name,
category: category.name,
technology: technology.name,
check: check
});
}
});
});
});
});
return results;
};
3. Status Tracking
Mark checks with different statuses:
type CheckStatus = 'open' | 'closed' | 'na';
const setCheckStatus = (checkId: string, status: CheckStatus) => {
const currentState = getAssessmentState();
currentState.checkStatus[checkId] = status;
saveAssessmentState(currentState);
};
const getOpenFindings = () => {
const state = getAssessmentState();
return Object.entries(state.checkStatus)
.filter(([_, status]) => status === 'open')
.map(([checkId, _]) => findCheckById(checkId));
};
4. Notes Management
Add contextual notes to checks:
const updateCheckNote = (checkId: string, note: string) => {
const state = getAssessmentState();
if (note.trim()) {
state.checkNotes[checkId] = note;
} else {
delete state.checkNotes[checkId];
}
saveAssessmentState(state);
};
const getCheckNote = (checkId: string): string => {
const state = getAssessmentState();
return state.checkNotes[checkId] || '';
};
5. Severity Filtering
Filter checks by severity level:
type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
const filterBySeverity = (
checks: Check[],
severities: Set<Severity>
): Check[] => {
if (severities.size === 0) return checks;
return checks.filter(check => severities.has(check.severity));
};
const activeSeverities = new Set<Severity>(['critical', 'high']);
const filteredChecks = filterBySeverity(allChecks, activeSeverities);
6. Progress Calculation
Track completion percentage:
const calculatePlatformProgress = (platformId: string): number => {
const platform = findPlatformById(platformId);
const totalChecks = countChecksInPlatform(platform);
const completedChecks = countCompletedChecks(platform);
return totalChecks > 0 ? (completedChecks / totalChecks) * 100 : 0;
};
const calculateOverallProgress = (): number => {
const totalChecks = platforms.reduce(
(sum, p) => sum + countChecksInPlatform(p),
0
);
const completedChecks = platforms.reduce(
(sum, p) => sum + countCompletedChecks(p),
0
);
return totalChecks > 0 ? (completedChecks / totalChecks) * 100 : 0;
};
Export & Import
Export Formats
Markdown Export:
const exportToMarkdown = (): string => {
const state = getAssessmentState();
let markdown = `# Security Assessment Report\n\n`;
markdown += `Generated: ${new Date().toISOString()}\n\n`;
platforms.forEach(platform => {
markdown += `## ${platform.name}\n\n`;
platform.categories.forEach(category => {
category.technologies.forEach(technology => {
technology.checks.forEach(check => {
const status = state.checkStatus[check.id];
const note = state.checkNotes[check.id];
if (status === 'open') {
markdown += `### [${check.severity.toUpperCase()}] ${check.title}\n`;
markdown += `**Status:** ${status}\n\n`;
markdown += `${check.description}\n\n`;
if (note) markdown += `**Notes:** ${note}\n\n`;
}
});
});
});
});
return markdown;
};
CSV Export:
const exportToCSV = (): string => {
const state = getAssessmentState();
const rows = [
['Platform', 'Category', 'Technology', 'Check', 'Severity', 'Status', 'Notes']
];
platforms.forEach(platform => {
platform.categories.forEach(category => {
category.technologies.forEach(technology => {
technology.checks.forEach(check => {
rows.push([
platform.name,
category.name,
technology.name,
check.title,
check.severity,
state.checkStatus[check.id] || 'unchecked',
state.checkNotes[check.id] || ''
]);
});
});
});
});
return rows.map(row => row.map(cell => `"${cell}"`).join(',')).join('\n');
};
JSON Export:
interface ExportData {
version: string;
exportDate: string;
state: AssessmentState;
metadata: {
totalChecks: number;
completedChecks: number;
progress: number;
};
}
const exportToJSON = (): string => {
const state = getAssessmentState();
const exportData: ExportData = {
version: '1.0',
exportDate: new Date().toISOString(),
state: state,
metadata: {
totalChecks: countAllChecks(),
completedChecks: countCompletedChecks(),
progress: calculateOverallProgress()
}
};
return JSON.stringify(exportData, null, 2);
};
Import from JSON
const importFromJSON = (jsonString: string): boolean => {
try {
const data: ExportData = JSON.parse(jsonString);
if (data.version !== '1.0') {
console.warn('Version mismatch, attempting import anyway');
}
saveAssessmentState(data.state);
return true;
} catch (error) {
console.error('Import failed:', error);
return false;
}
};
LocalStorage Management
Save and Load State
const STORAGE_KEY = 'pentesting-checklist-state';
const saveAssessmentState = (state: AssessmentState): void => {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
} catch (error) {
console.error('Failed to save state:', error);
}
};
const getAssessmentState = (): AssessmentState => {
try {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
return JSON.parse(stored);
}
} catch (error) {
console.error('Failed to load state:', error);
}
return {
checkStatus: {},
checkNotes: {},
progress: {
overall: 0,
perPlatform: {},
perCategory: {}
}
};
};
const clearAssessmentState = (): void => {
localStorage.removeItem(STORAGE_KEY);
};
Common Patterns
Starting a New Assessment
const startNewAssessment = (platformId: string) => {
const clearPrevious = confirm('Clear previous assessment data?');
if (clearPrevious) {
clearAssessmentState();
}
navigate(`/${platformId}`);
expandAll();
};
Filtering Open Findings
const getCriticalOpenFindings = () => {
const state = getAssessmentState();
return platforms.flatMap(platform =>
platform.categories.flatMap(category =>
category.technologies.flatMap(technology =>
technology.checks.filter(check =>
state.checkStatus[check.id] === 'open' &&
(check.severity === 'critical' || check.severity === 'high')
)
)
)
);
};
Bulk Status Update
const markCategoryAsNA = (categoryId: string) => {
const category = findCategoryById(categoryId);
const state = getAssessmentState();
category.technologies.forEach(technology => {
technology.checks.forEach(check => {
state.checkStatus[check.id] = 'na';
});
});
saveAssessmentState(state);
};
Platform-Specific Quick Filters
const filterHelpers = {
getAuthChecks: () =>
searchByTags(['authentication', 'auth', 'login', 'session']),
getInjectionChecks: () =>
searchByTags(['injection', 'sqli', 'xss', 'command-injection']),
getConfigChecks: () =>
searchByTags(['configuration', 'hardening', 'misconfiguration']),
getOWASPChecks: () =>
searchByTags(['owasp', 'owasp-top-10'])
};
const searchByTags = (tags: string[]): Check[] => {
return platforms.flatMap(platform =>
platform.categories.flatMap(category =>
category.technologies.flatMap(technology =>
technology.checks.filter(check =>
check.tags.some(tag =>
tags.some(searchTag =>
tag.toLowerCase().includes(searchTag.toLowerCase())
)
)
)
)
)
);
};
Troubleshooting
localStorage Issues
const isLocalStorageAvailable = (): boolean => {
try {
const test = '__storage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch {
return false;
}
};
const safeLocalStorageSave = (key: string, data: any): boolean => {
try {
localStorage.setItem(key, JSON.stringify(data));
return true;
} catch (error) {
if (error.name === 'QuotaExceededError') {
console.error('localStorage quota exceeded. Consider exporting and clearing old data.');
}
return false;
}
};
State Recovery
const backupState = (): string => {
return localStorage.getItem(STORAGE_KEY) || '{}';
};
const restoreState = (backup: string): void => {
localStorage.setItem(STORAGE_KEY, backup);
window.location.reload();
};
Performance Optimization
const debouncedUpdateNote = debounce((checkId: string, note: string) => {
updateCheckNote(checkId, note);
}, 500);
function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
Best Practices
- Regular Exports: Export assessment data regularly (daily for long assessments)
- Browser Consistency: Use the same browser throughout an assessment to maintain state
- Backup Before Clear: Always export before clearing localStorage
- Progressive Review: Start with critical/high severity items, then work down
- Detailed Notes: Include request/response snippets, payloads, and reproduction steps
- Platform Focus: Complete one platform before moving to another for better context
- Status Discipline: Use 'N/A' for out-of-scope items to accurately track progress
Integration Examples
CI/CD Integration (Automated Checks)
import checklistData from './src/data/checklist.json';
const getAutomatableChecks = () => {
return checklistData.platforms.flatMap(platform =>
platform.categories.flatMap(category =>
category.technologies.flatMap(technology =>
technology.checks.filter(check =>
check.tags.includes('automatable') &&
check.tools && check.tools.length > 0
)
)
)
);
};
Custom Report Generation
const generateExecutiveSummary = (): string => {
const state = getAssessmentState();
const findings = {
critical: 0,
high: 0,
medium: 0,
low: 0,
info: 0
};
Object.entries(state.checkStatus).forEach(([checkId, status]) => {
if (status === 'open') {
const check = findCheckById(checkId);
if (check) findings[check.severity]++;
}
});
return `
# Executive Summary
**Total Open Findings:** ${Object.values(findings).reduce((a, b) => a + b, 0)}
- Critical: ${findings.critical}
- High: ${findings.high}
- Medium: ${findings.medium}
- Low: ${findings.low}
- Informational: ${findings.info}
**Overall Progress:** ${calculateOverallProgress().toFixed(1)}%
`.trim();
};
This skill provides comprehensive coverage of the PentestingChecklist tool for AI agents to assist developers and security professionals in conducting thorough security assessments.