Port Table
Published ports with their bind address. `0.0.0.0:5432` and `127.0.0.1:5432` are the difference between a database on the internet and a database on the machine — printing only the number hides that.
src/components/ui/port-table.tsxAbout
From the component's own source, where it was written.
Published ports, with what is actually listening.
The bind address is shown, not just the port. 0.0.0.0:5432 and 127.0.0.1:5432 are the difference between a database on the internet and a database on the machine, and a table that prints only the number hides the one that matters.
Ports bound to all interfaces without TLS are flagged. That combination is the actual finding; either alone is often fine.
Well-known ports get their conventional service name, because 5432 means nothing to someone who does not already know it is Postgres.
One grid owns the columns and every row inherits them through subgrid. Giving each row its own grid looks identical in a mock-up and drifts in practice: 1fr and auto resolve against whatever that row happens to contain, so a row carrying an "exposed" badge squeezes its neighbours while an empty one does not, and no two rows line up.
Install
npx astralyx-ui add port-table
Usage
import { PortTable } from '@/components/ui/port-table'
<PortTable ports={ports} />Composer
Change the props and the source below follows.
- 443→8080
0.0.0.0nginxhttps - 8080
0.0.0.0node apihttp-altexposed - 5432
127.0.0.1postgrespostgres - 6379
0.0.0.0redis-serverredisexposed - 9090
127.0.0.1prometheusprometheus - 53/udp
127.0.0.53systemd-resolveddns
Bound to every interface without TLS — reachable from outside the host in the clear.
<PortTable ports={ports} />Examples
What is listening
<PortTable ports={ports} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
PortTable
Published ports, with what is actually listening.
Extends ComponentProps<'div'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| ports | PortBinding[] | required | { id, port, targetPort?, protocol?, address?, process?, tls?, service? }. |
| emptyLabel | ReactNode | 'No published ports' | — |
| portHeader | ReactNode | 'Port' | — |
| addressHeader | ReactNode | 'Bind' | — |
| processHeader | ReactNode | 'Process' | — |
| exposedLabel | ReactNode | 'exposed' | — |
| tlsLabel | string | 'TLS' | Accessible name for the TLS marker. |
| exposedNote | ReactNode | 'Bound to every interface without TLS — reachable from outside the host in the clear.' | — |
Functions
| Function | Signature | Description |
|---|---|---|
| wellKnownPorts | Record<number, string> | — |
Types
PortBinding
| Field | Type | Description |
|---|---|---|
| id | string | — |
| port | number | Port on the host. |
| targetPort? | number | Port inside the container or process. |
| protocol? | 'tcp' | 'udp' | — |
| address? | string | Bound to every interface is highlighted; loopback is not. |
| process? | ReactNode | — |
| tls? | boolean | — |
| service? | string | 5432 means nothing to someone who does not already know it is Postgres. |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| exposure | public + no TLS | That combination is the actual finding. Either alone is often fine. |