Server Hardening Audit - sshd, nginx, Docker, Kubernetes avatar

Server Hardening Audit - sshd, nginx, Docker, Kubernetes

Pricing

from $28.00 / 1,000 config auditeds

Go to Apify Store
Server Hardening Audit - sshd, nginx, Docker, Kubernetes

Server Hardening Audit - sshd, nginx, Docker, Kubernetes

Audit server and container configs against hardening baselines. 9 formats, 74 checks. Catches insecure implicit defaults other linters miss. No network access - analyses only the text you supply.

Pricing

from $28.00 / 1,000 config auditeds

Rating

0.0

(0)

Developer

John J. K. Omolo

John J. K. Omolo

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Server Hardening Audit — sshd, nginx, Docker, ufw

Paste a config file. Get back every hardening failure, ranked by severity, with the exact line to change.

Built for the moment an AI coding agent has just written an sshd_config, a Dockerfile or a docker-compose.yml and nobody has checked whether it is safe to deploy. One call in, a graded finding list out.

No network access. No scanning. This Actor reads only the text you pass it. It never connects to a host, never probes a port and never touches a machine you do not control. That is a deliberate design choice, not a missing feature.

Why this is not another linter

Most config checkers grade what is written in the file. That means an empty sshd_config scores 100% — while the daemon it describes is quietly accepting password logins from the entire internet.

This Actor evaluates implicit defaults. When a directive is absent, it is checked against the value the daemon actually uses, and the finding is tagged source: implicit-default so you can tell the two apart.

Three examples of what that catches:

FindingWhy other tools miss it
ClientAliveInterval absentDefaults to 0 — the session never times out
PermitRootLogin absentDefaults to prohibit-password — key-based root login is still open
add_header inside a location blocknginx does not merge headers across scopes. One add_header in a nested block silently discards every security header set at server or http level. Config looks right, headers ship missing.

Supported formats

Auto-detected from the content — you do not need to say which is which.

  • sshd_config — 20 checks. Correctly models sshd's first-value-wins precedence and flags Match blocks that re-enable password auth or root login.
  • nginx.conf — 10 checks. TLS versions, cipher suites (understands OpenSSL ! exclusion syntax), security headers, header-inheritance footgun.
  • Dockerfile — 7 checks. Root execution, floating tags, secrets baked into layers, curl | sh, remote ADD.
  • docker-compose.yml — 9 checks. privileged, Docker socket mounts, host namespaces, capabilities, datastore ports published to 0.0.0.0.
  • ufw status verbose — 4 checks. Default policy, exposed datastore ports, unlimited SSH.

Input

Single file:

{
"configText": "PermitRootLogin yes\nPasswordAuthentication yes\n"
}

Batch — one run, one call, billed per config:

{
"configs": [
{ "name": "web-01 sshd", "content": "..." },
{ "name": "web-01 nginx", "content": "..." },
{ "name": "api compose", "content": "..." }
],
"minSeverity": "medium"
}

Output

One dataset item per config:

{
"name": "web-01 sshd",
"config_type": "sshd",
"score": 43,
"grade": "D",
"counts": { "critical": 1, "high": 2, "medium": 3, "low": 1, "info": 0 },
"findings": [
{
"rule_id": "SSH-001",
"title": "Root login over SSH",
"severity": "critical",
"status": "fail",
"source": "explicit",
"line": 2,
"observed": "yes",
"rationale": "Direct root login removes per-user accountability...",
"fix": "PermitRootLogin no",
"ref": "CIS Distribution Independent Linux 5.2"
}
]
}

A SUMMARY record in the key-value store aggregates the run: average score, total counts, and the top ten critical and high findings across every config as priority_actions.

Scoring: starts at 100, minus 25 per critical, 12 per high, 5 per medium, 2 per low. Info findings cost nothing. A → 90+, B → 75+, C → 60+, D → 40+, F below.

Redaction

Detected credentials are never echoed back. A hardcoded password is reported as POSTGRES_PASSWORD=<redacted, 18 chars> — enough to locate it, not enough to leak it into your logs, your dataset or your agent's context window.

Calling it from an agent

Available through the Apify MCP server, so Claude, Cursor and any MCP-speaking client can call it as a tool. Ask it to audit a config and it will route here.

Pricing

Billed per config audited, not per run. Batch as many files as you like into a single call — the batch costs the same as running them separately, but finishes in one round trip.

Limits and honest caveats

  • 512 KB per config.
  • nginx parsing handles include directives as opaque — files you do not paste are not analysed.
  • This grades configuration. It says nothing about unpatched packages, running processes or kernel version.
  • A clean score means the config passes these checks. It is not a certification, and it is not a substitute for a penetration test.
  • SSH-017 reports a non-default SSH port as informational only. Moving the port reduces log noise from untargeted scanners; it is not a security control and is scored as zero.

Local use

pip install -r requirements.txt
python -m src.main path/to/sshd_config path/to/docker-compose.yml

Prints the same JSON structure to stdout, no Apify account needed.