Skip to main content
The ports command validates that a container image only exposes authorized network ports. This helps enforce network security policies and prevent unintended service exposure.

Usage

check-image ports <image> [--allowed-ports <ports>]

Description

The ports command extracts the list of exposed ports from the image configuration (from the EXPOSE instruction in Dockerfile) and validates them against an allowed list. Ports can be provided as a comma-separated list or loaded from a file. This check helps:
  • Enforce network security policies
  • Prevent unintended port exposure
  • Identify unauthorized services
  • Control network attack surface
  • Validate Dockerfile EXPOSE instructions

Flags

--allowed-ports
string
Comma-separated list of allowed ports (e.g., 80,443) or @<file> to load from JSON/YAML file. Use @- to read from stdin.Short form: -p
--output
string
default:"text"
Output format: text or jsonShort form: -o
--color
string
default:"auto"
Color output mode: auto, always, never
--log-level
string
default:"info"
Set log level: trace, debug, info, warn, error, fatal, panic

Allowed Ports File Format

When using @<file>, the file must contain an allowed-ports array:
allowed-ports:
  - 80
  - 443
  - 8080
  - 8443

Examples

Inline port list

check-image ports nginx:latest --allowed-ports 80,443

Load from JSON file

check-image ports nginx:latest --allowed-ports @allowed-ports.json

Load from YAML file

check-image ports nginx:latest --allowed-ports @allowed-ports.yaml

Ports from stdin

echo '{"allowed-ports": [80, 443]}' | \
  check-image ports nginx:latest --allowed-ports @-

Check OCI archive

check-image ports oci-archive:/path/to/image.tar:latest --allowed-ports 8080,8443

No allowed ports specified

# Will fail if image exposes any ports
check-image ports nginx:latest

JSON output

check-image ports nginx:latest --allowed-ports 80,443 -o json

Output

Text Format

When validation passes:
✓ All exposed ports are in the allowed list

Details:
  Exposed Ports: [80, 443]
  Allowed Ports: [80, 443, 8080]
When no ports are exposed:
✓ No ports are exposed in this image

Details:
  Exposed Ports: []
  Allowed Ports: [80, 443]
When validation fails (unauthorized ports):
✗ Unauthorized ports detected

Details:
  Exposed Ports: [80, 443, 3000, 5432]
  Allowed Ports: [80, 443]
  Unauthorized Ports: [3000, 5432]
When validation fails (no allowed ports provided):
✗ No allowed ports were provided

Details:
  Exposed Ports: [80, 443]
  Allowed Ports: []

JSON Format

{
  "check": "ports",
  "image": "nginx:latest",
  "passed": true,
  "message": "All exposed ports are in the allowed list",
  "details": {
    "exposed-ports": [80, 443],
    "allowed-ports": [80, 443, 8080],
    "unauthorized-ports": null
  }
}
Failed validation:
{
  "check": "ports",
  "image": "myapp:latest",
  "passed": false,
  "message": "",
  "details": {
    "exposed-ports": [80, 443, 3000],
    "allowed-ports": [80, 443],
    "unauthorized-ports": [3000]
  }
}

Exit Codes

CodeMeaningExample
0All exposed ports are allowed or no ports exposedImage exposes 80,443 and allowed list is 80,443,8080
1Unauthorized ports detectedImage exposes 3000 but allowed list is only 80,443
2Execution errorInvalid port format, file not found

Configuration

When using the all command, configure ports validation in your config file:
checks:
  ports:
    allowed-ports: [80, 443, 8080]
You can also reference a file:
checks:
  ports:
    allowed-ports: config/allowed-ports.yaml

Implementation Details

  • Reads exposed ports from image config’s ExposedPorts field
  • Parses port format <port>/<protocol> (e.g., 8080/tcp, 53/udp)
  • Only validates the port number, protocol is ignored
  • Port comparison is exact (no ranges or wildcards)
  • Empty allowed list with exposed ports = validation failure
  • No exposed ports = always passes (regardless of allowed list)

Common Issues

No allowed ports provided

✗ No allowed ports were provided
Solution: Specify --allowed-ports with at least one port.

Invalid port format

Error: invalid port 'abc': strconv.Atoi: parsing "abc": invalid syntax
Solution: Ensure all ports are numeric values.

EXPOSE vs runtime ports

The ports command validates EXPOSE declarations in the Dockerfile, not runtime port mappings (-p in docker run):
# This is what the ports command checks
EXPOSE 80
EXPOSE 443
Runtime port mappings are not visible in the image config:
# This does NOT affect the ports check
docker run -p 8080:80 nginx:latest

Best Practices

Define allowed ports based on your application’s needs
Include common web ports (80, 443) for web applications
Be restrictive with database ports (3306, 5432, etc.)
Document why each port is allowed
Use separate policies for different application types
Remember that the ports check validates EXPOSE declarations, not runtime port mappings

Port Protocols

The image config stores ports with protocols (e.g., 80/tcp, 53/udp), but the validation only considers the port number:
Image EXPOSEExtracted Port
EXPOSE 8080
EXPOSE 80/tcp80
EXPOSE 53/udp53
EXPOSE 8080/tcp8080
If you need protocol-specific validation, you’ll need to implement that separately.
  • all - Run all checks including ports validation
  • registry - Validate registry trust
  • platform - Validate image platform

Build docs developers (and LLMs) love