If you discover a security vulnerability in dnp3-interop, please report it responsibly.
Do not open a public GitHub issue for security vulnerabilities.
Instead, please email security@otfabric.io, or open a private advisory on GitHub (the Security tab → Advisories → Report a vulnerability), with a description, steps to reproduce and the affected image tag or digest.
Vulnerabilities in the bundled implementations themselves (opendnp3, dnp3py, DSC Systems go-dnp3) belong upstream; report them there, and tell us so that the pin can be moved.
| Version | Supported |
|---|---|
| v0.10.x (latest, v0.10.0) | Yes |
| < v0.10 | No; pull the latest images (and build the dnp3c image locally) |
The images run DNP3 outstations, unauthenticated and unencrypted by default, that accept polls, controls, restarts and time writes from anyone who can reach them, and clients that send commands to whatever address they are given. That is their purpose.
- Never attach a server to a plant, control or other production network
- Never point a client at a real outstation:
operate,restart,time-syncand the other operations act on what they are sent to compose.yamland therun-*Makefile targets publish ports on127.0.0.1only. Keep it that way; the self-tests use private Docker networks and publish nothing- TLS and secure authentication (contract 1.1) are optional. The self-tests make throw-away certificates per run (
scripts/test-pki.sh); keys passed with--tls-keyor--sa-update-keyare test material and protect nothing. The images contain no certificates or keys
- Processes run as a non-root user (uid 10001)
- Base images are pinned by digest; upstream sources by commit or exact version (versions.yaml)
- The runtime images contain the adapter, its runtime libraries and the fixtures; build tools stay in the build stages
- The images are rebuilt, not patched: a base image or upstream fix arrives with a new release
- Upstream sources are fetched during the image build at pinned versions: opendnp3 from GitHub (verified against the pinned commit hash), dnp3py from PyPI (hash-pinned
requirements.txt) and DSC Systems go-dnp3 through the Go module proxy (checksums ingo.sum). - Base images are pinned by digest. CI and the release workflow pull them from
mirror.gcr.io/library, a mirror of Docker Hub's official images, because anonymous Docker Hub pulls are rate limited; the digest makes the source irrelevant to the content (BASE_REGISTRY, defaultdocker.io/library). The build tooling images (BuildKit, QEMU handlers, shellcheck) come from the same mirror by tag (TOOLS_REGISTRY) - Consumers should pin the published images by digest, taken from the
manifest.jsonof a release. - Every release is scanned with Trivy (pinned by digest) after publishing, and every published image gets a CycloneDX SBOM per architecture;
vulnerabilities.mdandsboms.tar.gzare attached to the release. Findings are recorded, not gated on: the images are test fixtures, never deployed. Findings with a fix available are taken up in the next release by moving the base image digest or the package; the rest disappear when upstream ships a fix. Trivy sees the Debian packages, the Python packages of the dnp3py image and the Go modules of the dscsystems binary, not what is statically compiled into the C++ binary (their versions are inversions.yamland the release'smanifest.json)