Files
DECNET/pyproject.toml
anti 39dafaf384 feat(ssh-stealth): hide capture artifacts via XOR+gzip entrypoint blob
The /opt/emit_capture.py, /opt/syslog_bridge.py, and
/usr/libexec/udev/journal-relay files were plaintext and world-readable
to any attacker root-shelled into the SSH honeypot — revealing the full
capture logic on a single cat.

Pack all three into /entrypoint.sh as XOR+gzip+base64 blobs at build
time (_build_stealth.py), then decode in-memory at container start and
exec the capture loop from a bash -c string. No .py files under /opt,
no journal-relay file under /usr/libexec/udev, no argv_zap name
anywhere. The LD_PRELOAD shim is installed as
/usr/lib/x86_64-linux-gnu/libudev-shared.so.1 — sits next to the real
libudev.so.1 and blends into the multiarch layout.

A 1-byte random XOR key is chosen at image build so a bare
'base64 -d | gunzip' probe on the visible entrypoint returns binary
noise instead of readable Python.

Docker-dependent tests live under tests/docker/ behind a new 'docker'
pytest marker (excluded from the default run, same pattern as fuzz /
live / bench).
2026-04-18 05:34:50 -04:00

109 lines
2.7 KiB
TOML

[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "decnet"
version = "0.2.0"
description = "Deception network: deploy honeypot deckies that appear as real LAN hosts"
requires-python = ">=3.11"
dependencies = [
"typer[all]>=0.12",
"pydantic>=2.0",
"docker>=7.0",
"pyyaml>=6.0",
"jinja2>=3.1",
"fastapi>=0.110.0",
"uvicorn>=0.29.0",
"aiosqlite>=0.20.0",
"asyncmy>=0.2.9",
"PyJWT>=2.8.0",
"bcrypt>=4.1.0",
"psutil>=5.9.0",
"python-dotenv>=1.0.0",
"sqlmodel>=0.0.16",
"scapy>=2.6.1",
"orjson>=3.10",
"cryptography>=46.0.7"
]
[project.optional-dependencies]
tracing = [
"opentelemetry-api>=1.20.0",
"opentelemetry-sdk>=1.20.0",
"opentelemetry-exporter-otlp>=1.20.0",
"opentelemetry-instrumentation-fastapi>=0.41b0",
]
profile = [
"py-spy>=0.4.1",
"pyinstrument>=4.7",
"pytest-benchmark>=4.0",
"memray>=1.14 ; sys_platform == 'linux'",
"snakeviz>=2.2",
]
dev = [
"decnet[tracing,profile]",
"pytest>=9.0.3",
"ruff>=0.15.10",
"bandit>=1.9.4",
"pip>=26.0",
"pip-audit>=2.10.0",
"httpx>=0.28.1",
"hypothesis>=6.151.14",
"pytest-cov>=7.1.0",
"pytest-asyncio>=1.3.0",
"freezegun>=1.5.5",
"schemathesis>=4.15.1",
"pytest-xdist>=3.8.0",
"flask>=3.1.3",
"twisted>=25.5.0",
"requests>=2.33.1",
"redis>=7.4.0",
"pymysql>=1.1.2",
"psycopg2-binary>=2.9.11",
"paho-mqtt>=2.1.0",
"pymongo>=4.16.0",
"locust>=2.29",
"gevent>=24.0",
]
[project.scripts]
decnet = "decnet.cli:app"
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_debug = "true"
addopts = "-m 'not fuzz and not live and not stress and not bench and not docker' -v -q -x -n logical --dist loadscope"
markers = [
"fuzz: hypothesis-based fuzz tests (slow, run with -m fuzz or -m '' for all)",
"live: live subprocess service tests (run with -m live)",
"live_docker: live Docker container tests (requires DECNET_LIVE_DOCKER=1)",
"stress: locust-based stress tests (run with -m stress)",
"bench: pytest-benchmark micro-benchmarks (run with -m bench)",
"docker: tests that build and run docker images (run with -m docker)",
]
filterwarnings = [
"ignore::pytest.PytestUnhandledThreadExceptionWarning",
"ignore::DeprecationWarning",
"ignore::RuntimeWarning",
]
[tool.coverage.run]
source = ["decnet"]
omit = ["*/tests/*", "templates/*"]
parallel = true
[tool.coverage.report]
show_missing = true
skip_covered = false
# Run with: pytest --cov --cov-report=term-missing
[tool.setuptools.packages.find]
where = ["."]
include = ["decnet*"]
[tool.bandit]
exclude_dirs = [
"templates/syslog_bridge.py",
]