Skip to content

Commit 41305e9

Browse files
authored
docs(roadmap): track container port exposure + OS-image research item (#147)
Adds a new "Attack Surface Visibility — Port & Service Exposure" section to docs/developer/SDK-ROADMAP.md. Two items: 1) Container declared EXPOSE ports — actionable. Extends the existing container scanner (no new module). Reads Config.ExposedPorts from the docker inspect output the scanner already pulls, emits one Finding per port. Severity INFO for ordinary application ports, WARN for a built-in risky-defaults list (SSH 22, MySQL 3306, Redis 6379, etc. — every entry cites why in the scanner docstring). Config knobs: scanners.container.expose_warn_ports and expose_ignore_ports. Findings flow through existing reporter pipeline, severity filtering, audit trail, and the view-terminal / view-browser UIs without per-reporter custom code. Single-PR scope listed. 2) OS image port enumeration — research item. Same question for AMIs / VMDKs / ISOs / rootfs tarballs. Before any implementation, three questions to answer: - Is offline OS-image inspection in argus's scope at all? (libguestfs / boot-and-inspect / cloud-native paths each have distinct operational profiles vs. argus's container + source-code model.) - Are there existing tools that solve this well enough that argus should wrap rather than reimplement? (OpenSCAP + libguestfs, Lynis, CIS-CAT, AWS Inspector v2, commercial suites — comparison matrix needed.) - Or is this a "different product" feeling? (Audience overlaps with argus but operational model — golden-AMI / Packer pre-release gates with minutes-to-tens-of-minutes scan latency — differs from PR-CI / sub-minute scans.) Research deliverable is a short ADR (likely ADR-025+), not code. Strong prior noted: argus stays focused on source-code + container images; OS-image inspection probably belongs in purpose-built tools and we surface a documentation pointer. Co-authored-by: eFAILution <eFAILution@users.noreply.github.com>
1 parent 8e51955 commit 41305e9

1 file changed

Lines changed: 181 additions & 0 deletions

File tree

docs/developer/SDK-ROADMAP.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,187 @@ defending against and the gaps we knowingly carry.
897897

898898
---
899899

900+
## Attack Surface Visibility — Port & Service Exposure
901+
902+
Companion to the vulnerability scanning argus already does
903+
(Trivy / Grype find CVEs in installed packages, Bandit / Opengrep
904+
find SAST issues in source). This section tracks features that
905+
report *attack surface* — what network endpoints an image
906+
declares — separate from whether those endpoints have known CVEs.
907+
"Image exposes 6379/tcp" is a different question from "image has
908+
a vulnerable Redis package" and most security reviewers want both.
909+
910+
### Container image exposed ports — actionable
911+
912+
- [ ] **Surface declared EXPOSE ports as findings.** Extend the
913+
existing `argus/scanners/container.py` sub-scanner flow
914+
(alongside trivy / grype / syft). No new scanner module — the
915+
data is already free: `docker inspect <image>` returns
916+
`Config.ExposedPorts` and the container scanner already inspects
917+
every image it scans.
918+
919+
**Output shape:** one `Finding` per declared port:
920+
```
921+
INFO EXPOSE-8080 Port 8080/tcp declared exposed
922+
WARN EXPOSE-22 Port 22/tcp (SSH) declared exposed — review necessity
923+
WARN EXPOSE-3306 Port 3306/tcp (MySQL) declared exposed — review necessity
924+
```
925+
Severity defaults to `INFO` for ordinary application ports and
926+
`WARN` for ports on a built-in risky-defaults list (services that
927+
shouldn't normally be exposed from a container image without a
928+
deliberate reason). The list is config-overridable so teams can
929+
tune it for their context.
930+
931+
**Built-in risky-port defaults (warn):**
932+
- `21/tcp` (FTP), `22/tcp` (SSH), `23/tcp` (Telnet)
933+
- `25/tcp` (SMTP), `110/tcp` (POP3), `143/tcp` (IMAP)
934+
- `161/udp` (SNMP), `389/tcp` (LDAP), `445/tcp` (SMB)
935+
- `3306/tcp` (MySQL), `3389/tcp` (RDP)
936+
- `5432/tcp` (PostgreSQL), `6379/tcp` (Redis)
937+
- `9200/tcp` (Elasticsearch), `11211/tcp` (Memcached)
938+
- `27017/tcp` (MongoDB)
939+
Source: services that historically ship with weak defaults or
940+
that fronting via a container without auth/TLS in front of them
941+
is a recurring incident pattern. Each entry cites a "why" in the
942+
scanner module's docstring so future contributors don't tune the
943+
list blindly.
944+
945+
**Config knob** (in `argus.yml`):
946+
```yaml
947+
scanners:
948+
container:
949+
expose_warn_ports: # override the built-in WARN list
950+
- 22/tcp
951+
- 6379/tcp
952+
expose_ignore_ports: # don't emit a finding at all
953+
- 8080/tcp
954+
- 443/tcp
955+
```
956+
957+
**Why findings (not metadata):** flows through the existing
958+
reporter pipeline (terminal table, markdown, SARIF, JSON, GitHub
959+
annotations, GitLab Code Quality, JUnit), `--severity-threshold`
960+
works on them, audit-trail captures them, and the
961+
`argus view terminal` / `argus view browser` UIs render them
962+
alongside CVE findings without per-reporter custom code.
963+
964+
**Implementation tasks** (single PR, no new dependencies):
965+
- [ ] `argus/scanners/container.py`: new `_scan_exposed_ports`
966+
sub-method that reads `Config.ExposedPorts` from the existing
967+
`docker inspect` output. Emits one `Finding` per port with
968+
`id=f"EXPOSE-{port}"`, `scanner="container"`,
969+
`metadata={"port": ..., "protocol": ..., "common_service": ...}`.
970+
- [ ] Built-in `RISKY_PORTS: dict[tuple[int, str], str]` mapping
971+
`(port, protocol) -> service_name` with the WARN-list above;
972+
cited entries in the docstring.
973+
- [ ] Config schema additions: `expose_warn_ports` and
974+
`expose_ignore_ports` (both `list[str]`, parsed as `"port/proto"`).
975+
Validator errors on malformed entries.
976+
- [ ] Tests in `argus/tests/scanners/test_container.py`: fixture
977+
with a multi-port `Config.ExposedPorts` blob; assert one finding
978+
per port with correct severity, ignore-list suppresses, override
979+
warn-list changes the severity.
980+
- [ ] Docs: `docs/scanners.md` container section gets an
981+
"Exposed ports" subsection with config examples;
982+
`docs/config-reference.md` adds the two new keys.
983+
- [ ] `.ai/architecture.yaml`: container scanner description
984+
updated to mention the new sub-scanner capability.
985+
986+
**Out of scope for this PR:** *runtime* port enumeration (actually
987+
start the container, probe with `nmap` / `ss`). Static `EXPOSE`
988+
data is the bulk of the value at a fraction of the operational
989+
cost. A runtime variant can become a separate roadmap item if
990+
consumer demand surfaces.
991+
992+
### OS image port enumeration — research item
993+
994+
Same question as above but for OS-level images: AWS AMIs, Azure VHDs,
995+
GCP disk images, on-prem VMware OVA/VMDK, ISO files, raw disk dumps,
996+
rootfs tarballs. What network endpoints would this image bind on boot?
997+
998+
- [ ] **Research: in-scope, out-of-scope, or wrap-existing?**
999+
Before scoping any implementation, answer three questions:
1000+
1001+
**Is offline OS-image inspection in argus's scope at all?**
1002+
Argus today operates on (a) source-code directories and (b)
1003+
container image references. An OS image is a fundamentally
1004+
different artifact — it's a bootable disk, not a layered
1005+
filesystem manifest. Inspecting it offline typically requires
1006+
one of:
1007+
- **libguestfs / `virt-customize` / `virt-inspect`** — mount the
1008+
disk image, walk the filesystem, read systemd unit files
1009+
(`/etc/systemd/system/*.service`, `/lib/systemd/system/*.service`),
1010+
SysV init scripts, common service configs (sshd_config,
1011+
postgresql.conf, nginx.conf, etc.). Linux-only on the host;
1012+
needs root or libvirt group; libguestfs is a heavy install
1013+
(~hundreds of MB once a guest kernel is included).
1014+
- **Boot-and-inspect** — actually boot the image in a sandbox VM,
1015+
let services start, capture listening sockets via SSH or guest
1016+
agent, tear down. Heaviest path; needs hypervisor (KVM, QEMU,
1017+
or cloud-provider API). Argus's container-or-source-code model
1018+
doesn't extend here cleanly.
1019+
- **Cloud-provider native** — AWS Inspector (AMIs), Azure
1020+
Defender for Cloud, GCP Security Command Center. These run
1021+
server-side, no local install.
1022+
1023+
**Are there existing tools that solve this well enough that argus
1024+
should not reimplement?** Candidates to evaluate:
1025+
- **OpenSCAP + `oscap-vm` / `oscap-docker`** — SCAP content with
1026+
OVAL definitions can audit a running or mounted system; covers
1027+
listening-port checks via STIG/CIS profiles. Output is XCCDF
1028+
XML — would need an argus reporter shim.
1029+
- **Lynis** — system audit tool. Runs against a live root
1030+
filesystem; can chroot into a mounted image. Output is text;
1031+
parser would be needed.
1032+
- **CIS-CAT** — CIS benchmark scanner. Commercial license tier
1033+
needed for production use; OSS version exists but limited.
1034+
- **AWS Inspector v2** — first-class AMI scanning, no install
1035+
required if you're already on AWS. Doesn't help users on
1036+
other clouds or with on-prem images.
1037+
- **Anchore Enterprise** / **Aqua** / **Sysdig Secure** — all
1038+
have on-prem image scanning but are commercial/freemium.
1039+
- **`debootstrap` + chroot + `ss`** — DIY for Linux rootfs
1040+
tarballs only. Possible but argus-specific implementation.
1041+
1042+
**Or is this a "different product" feeling?** The audience for
1043+
OS-image hardening (DevSecOps building golden AMIs, on-prem VM
1044+
templates, FedRAMP-bound infrastructure teams) overlaps with
1045+
argus's audience but the operational model is different:
1046+
- Argus runs in PR CI / dev loops; OS image scans are
1047+
typically pre-release gates on infrastructure-as-code
1048+
pipelines (Packer builds, Terraform deploys).
1049+
- Argus expects sub-minute scan times; OS-image inspection via
1050+
libguestfs is minutes-to-tens-of-minutes per image.
1051+
- Argus's container-scanner model assumes Docker is available;
1052+
OS-image inspection assumes libguestfs / KVM / cloud API
1053+
access, which is a different host requirement.
1054+
1055+
**Specific research deliverables** (one investigation, output is
1056+
a short ADR — not code):
1057+
- [ ] Inventory of 3-5 actual user requests / use cases for OS
1058+
image inspection. Without concrete demand, this stays
1059+
deferred.
1060+
- [ ] Comparison matrix: argus-native (libguestfs) vs. wrap
1061+
OpenSCAP vs. defer to AWS Inspector vs. out-of-scope.
1062+
Dimensions: install footprint, host OS requirements, supported
1063+
image formats, scan latency, license cost, reporting fidelity.
1064+
- [ ] Scope decision in `.ai/decisions.yaml` (likely ADR-025 or
1065+
later): one of "argus native", "argus wraps OpenSCAP", "argus
1066+
out of scope; recommend X", "deferred until more demand".
1067+
- [ ] If "out of scope": note in `docs/scanners.md` pointing
1068+
users at the right tool for OS-image port enumeration so they
1069+
don't open issues asking for it later.
1070+
1071+
**My strong prior** (to be tested against the research):
1072+
argus stays focused on source-code + container images;
1073+
OS-image inspection is best served by purpose-built tools
1074+
(OpenSCAP for offline, cloud-native scanners for AMIs). The
1075+
argus answer for users would be a documentation pointer plus,
1076+
if compelling, a `docs/security.md` paragraph naming the tools
1077+
we recommend for each cloud + on-prem path.
1078+
1079+
---
1080+
9001081
## Dependency Maintenance — Full Coverage
9011082

9021083
| Dependency Type | Tool | Config Location | Status |

0 commit comments

Comments
 (0)