Plugin SDKTesting your module

Testing a custom module

Pencheff modules are plain Python so pytest works as-is. Ship your tests alongside the module in ~/.pencheff/custom_modules/tests/ or include them in the pencheff repo if you plan to upstream.

Unit test template

# ~/.pencheff/custom_modules/tests/test_robots_check.py
import pytest
from unittest.mock import AsyncMock, MagicMock
 
from pencheff.config import TestDepth
from pencheff.core.session import PentestSession, TargetInfo, DiscoveredState
from pencheff.core.credentials import CredentialStore
from pencheff.core.findings import FindingsDB
 
# Import the module from your custom_modules directory
import sys, pathlib
sys.path.insert(0, str(pathlib.Path.home() / ".pencheff" / "custom_modules"))
from robots_check import RobotsCheck
 
 
@pytest.mark.asyncio
async def test_flags_admin_disallow():
    session = PentestSession(
        id="test", target=TargetInfo(base_url="https://example.com"),
        credentials=CredentialStore(), depth=TestDepth.QUICK,
        findings=FindingsDB(), discovered=DiscoveredState(),
    )
 
    mock_http = MagicMock()
    mock_http.request = AsyncMock(return_value=MagicMock(
        status=200,
        text="User-agent: *\nDisallow: /admin\n",
    ))
 
    findings = await RobotsCheck().run(session, mock_http)
    assert len(findings) == 1
    assert "/admin" in findings[0].description
 
 
@pytest.mark.asyncio
async def test_no_findings_when_robots_missing():
    session = PentestSession(
        id="test", target=TargetInfo(base_url="https://example.com"),
        credentials=CredentialStore(), depth=TestDepth.QUICK,
        findings=FindingsDB(), discovered=DiscoveredState(),
    )
    mock_http = MagicMock()
    mock_http.request = AsyncMock(return_value=MagicMock(status=404))
 
    findings = await RobotsCheck().run(session, mock_http)
    assert findings == []

Run:

pip install pytest pytest-asyncio
pytest ~/.pencheff/custom_modules/tests/

Integration test with a live target

Spin up a local vulnerable container (e.g. Juice Shop) and run your module end-to-end:

docker run --rm -p 3000:3000 bkimminich/juice-shop
pencheff run-policy - <<'YAML'
apiVersion: pencheff/v1
kind: ScanPolicy
metadata: { name: module-ete }
spec:
  targets: [{ url: http://localhost:3000 }]
  modules:
    - { name: custom_robots_check }
YAML