These rules apply to all code changes:
- Never add Puppeteer flags that disable security features (sandbox, web security, CORS). If you believe a flag is needed, document the justification and get explicit approval.
- All browser navigation must use
safeNavigate()-- never callpage.goto()directly. This validates the URL hostname againstPCPP_DOMAIN_PATTERN. - All tag inputs must use
validateTag()-- pattern:/^[A-Za-z0-9]{6}$/. Never inline checks. - All category inputs must use
validateCategory()-- validates againstCATEGORY_SLUGSkeys. - Never log full error objects -- use
sanitizeErrorForLog(error)for stderr,sanitizeErrorForClient(error)for MCP responses. - Never expose filesystem paths in error messages -- use generic messages with setup instructions.
- Cookie files must be validated -- the Zod cookie schema in cookie loading validates structure and rejects non-PCPP domains.
- Mock exports must be sanitized -- always wrap HTML with
sanitizeMockHtml()before writing to disk. - CSRF tokens must never be logged or included in error messages -- extract via
extractCsrfToken(), use in/qapi/POST headers only. - All build-list identifier inputs must use
validateIdentifier()-- validates max 200 chars and character allowlist/^[A-Za-z0-9 :.\-_()]+$/.
This server runs as a local MCP server on the developer's machine. It:
- Launches headless Chrome instances with anti-detection spoofing
- Navigates to pcpartpicker.com URLs constructed from user-provided parameters (tags, categories, search terms)
- Reads and parses full page HTML, including JavaScript-rendered content
- Executes AJAX POSTs to
/qapi/endpoints with CSRF tokens for build mutations - Writes mock HTML files to disk when export mode is enabled
- Persists session cookies to disk (build server)
- Logs operational details to stderr (captured by MCP host)
Primary attack surface: The browser. If Chrome navigates to a compromised page with disabled sandboxing, escape to the host is possible. CSRF token leakage could enable unauthorized build list mutations from external scripts.
Secondary surfaces: Cookie file handling (path injection, domain spoofing), error message leakage (internal paths/stack traces), mock export mode (PII written to disk).
PCPP-specific risks: robots.txt blocks AI user agents -- our browser automation bypasses this but may trigger additional scrutiny. Cloudflare WAF may challenge or block automated requests. The _scr() fingerprint validation may detect automation and reject /qapi/ calls.
Phase 7 security audit completed on 2026-03-07.
Audit coverage:
- Navigation audit: passed (
page.goto()only insidesafeNavigate()). - Tag/category validation audit: passed (
validateTag()/validateCategory()guards present on user inputs). - Error audit: passed (server handlers route logging and client responses through sanitizers).
- Browser cleanup audit: passed (
createBrowserAndPage()call sites close browser infinally). - Mock sanitization audit: passed (
maybeExportMockHtml()and capture script sanitize HTML before write). - CSRF audit: passed after fix (
src/pcpp.navigation.test.tsnow logs presence boolean, never token-derived text). - Cookie audit: passed (cookie-file loader rejects non-PCPP domains via Zod
refine). - Dependency audit: passed after remediation (
npm audit --audit-level=highreports 0 vulnerabilities).
| ID | Description | Severity | Status | |---|---|---|
| ID | Description | Severity | Status |
|---|---|---|
| PCPP-SEC-001 | express-rate-limit advisory GHSA-46wh-pxpv-q5gq (IPv4-mapped IPv6 bypass) was present in lockfile dependency tree. | High | Resolved on 2026-03-07 by npm audit fix (package-lock.json updated; audit now clean). |
| ID | Description | Severity | Status |
|---|---|---|
| QA-R1-001 | pcpp_get_guide missing outputSchema in listTools response (protocol compliance bug). | Medium | Resolved on 2026-03-07 by adding guideToolSchema and wiring it in src/servers/research.ts. |
| ID | Description | Severity | Status |
|---|---|---|
| PCPP-SEC-002 | Navigation smoke test logged CSRF token prefix to stderr (src/pcpp.navigation.test.ts). | Low | Resolved on 2026-03-07 by replacing token-prefix logging with CSRF token present: true/false. |
-
Sandbox enabled by default.
PCPP_MCP_DISABLE_SANDBOX=trueenv var for container deployments. A startup warning is logged when sandbox is disabled. -
Domain allowlist is a regex constant, not config.
PCPP_DOMAIN_PATTERNinsrc/constants.tsis hardcoded. A configurable list could be tampered with. -
safeNavigate()is a wrapper, not middleware. Eachpage.goto()call is replaced withsafeNavigate(page, url)which validates the URL hostname before navigating. More explicit and auditable than request interception. -
Cookie validation uses Zod. The same Zod library used for MCP tool schemas validates the cookie file structure, including domain validation against the PCPP allowlist.
-
Error sanitization is centralized. Two shared functions (
sanitizeErrorForLogandsanitizeErrorForClient) insrc/utils.tscentralize the logic.
Chrome sandbox requires kernel features (user namespaces, seccomp-bpf) that may not be available in Docker containers or CI environments running as root. In these environments:
PCPP_MCP_DISABLE_SANDBOX=true node build/servers/research.jsA [WARNING] message is logged to stderr when sandbox is disabled. This is the only supported way to disable sandbox -- never add --no-sandbox to the Puppeteer launch args directly.