{"id":50528247,"url":"https://github.com/earentir/sslcheck","last_synced_at":"2026-06-03T10:02:09.310Z","repository":{"id":356926729,"uuid":"1184744009","full_name":"earentir/sslcheck","owner":"earentir","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-10T12:47:56.000Z","size":92,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-10T14:33:21.301Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/earentir.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-17T22:25:44.000Z","updated_at":"2026-05-10T12:47:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/earentir/sslcheck","commit_stats":null,"previous_names":["earentir/sslcheck"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/earentir/sslcheck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fsslcheck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fsslcheck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fsslcheck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fsslcheck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/earentir","download_url":"https://codeload.github.com/earentir/sslcheck/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fsslcheck/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33858578,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-03T10:02:08.343Z","updated_at":"2026-06-03T10:02:09.305Z","avatar_url":"https://github.com/earentir.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sslcheck\n\nPure-Go HTTPS / TLS validation scanner.\n\n## Run\n\n```bash\ngo mod tidy\ngo run . https://example.com\ngo run . --json https://example.com\ngo run . --schema\n```\n\n## Building\n\n```bash\ngo build -o sslcheck .\n```\n\nTo embed a version at build time:\n\n```bash\ngo build -ldflags \"-X main.appVersion=1.0.0\" -o sslcheck .\n```\n\nDefault is the `appVersion` var at the top of `main.go`.\n\nIntegration / fixture tests (no external network): see [docs/VERIFICATION.md](docs/VERIFICATION.md).\n\n## Usage\n\n```\nsslcheck [flags] [URL ...]\n```\n\nSupply one or more targets per run: full `https://` URLs, `http://` (normalized to HTTPS for the scan), or a bare hostname like `earentir.dev` (HTTPS is assumed). Use `--file` to read lines from a file (`#` comments). Use `--schema` for the JSON schema only.\n\n### Logging (`--log-file`, `--log-level`)\n\nStructured logs go to **stderr** and optionally to a file. On startup, one line is always printed to stderr, e.g. `sslcheck logging: level=info console=stderr file=/path/to/sslcheck.log`.\n\n| Flags | Behavior |\n|-------|----------|\n| *(none)* | Console only, **warn** and above. No log file. |\n| `--log-file PATH` | Append to `PATH` at **info** (file + console). Omit `--log-level` → both use **info**. |\n| `--log-level debug\\|info\\|warn\\|error` | Console at that level; append to **`sslcheck.log` next to the binary** (same level). If that path is not writable, falls back to `./sslcheck.log`. |\n| Both | Console and file at `--log-level`; file is `--log-file`. |\n\n`--json` / report output stays on **stdout**; logs stay on **stderr** so pipelines stay clean.\n\nSubcommands:\n\n| Command | Description |\n|---------|-------------|\n| `sslcheck api` | HTTP **API only** (JSON). Use behind nginx; no TLS in-process. |\n| `sslcheck web` | Same API **plus** a small browser UI at `/`. |\n\n### HTTP API (`sslcheck api`)\n\nListen address: `--listen` (default `:8080`).\n\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | `/api/v1/health` | `{\"status\":\"ok\",\"scanner_version\":\"…\",\"scanner_source\":\"https://github.com/earentir/sslcheck\"}` |\n| GET | `/api/v1/schema` | JSON schema for reports |\n| GET | `/api/v1/checks` | List all supported finding codes (summary) |\n| GET | `/api/v1/checks/{code}` | Full metadata for one finding code (e.g. `CERT-011`) |\n| GET | `/api/v1/scan?url=https://...` | Run scan (optional: `profile`, `timeout_seconds`, `no_http`, `no_active_ocsp`, `first_ip_only`, `proxy_url`) |\n| POST | `/api/v1/scan` | Body: `{\"url\":\"earentir.dev\"}` or full URL — same rules as CLI |\n\nErrors: `400` with `{\"error\":\"...\"}`.\n\n### Web UI (`sslcheck web`)\n\nServes the API under `/api/v1/*` and a single-page UI at `/` (redirects to `index.html`). The page POSTs to `/api/v1/scan` on the same origin.\n\n### nginx (TLS termination in front)\n\nBoth commands speak plain HTTP. Example:\n\n```nginx\nlocation / {\n    proxy_pass http://127.0.0.1:8080;\n    proxy_read_timeout 130s;\n    proxy_connect_timeout 10s;\n}\n```\n\n### Flags\n\n| Flag | Short | Description |\n|------|--------|-------------|\n| `--json` | | Emit report as JSON |\n| `--schema` | | Emit JSON schema and exit |\n| `--csv` | | Emit findings as CSV |\n| `--timeout` | | Per-operation timeout (default 12s) |\n| `--profile` | | Policy profile: `modern` or `strict` (default modern) |\n| `--no-http` | | Skip HTTP redirect and application probes |\n| `--no-active-ocsp` | | Skip active OCSP responder checks |\n| `--no-color` | | Disable colored output |\n| `--output` | `-o` | Write report to file |\n| `--quiet` | `-q` | Only print overall result, grade, and findings count |\n| `--verbose` | `-v` | Include full redirect chain and extra detail |\n| `--file` | | Read URLs from file (one per line, # comments) |\n| `--ip` | | Only probe the first resolved IP |\n| `--proxy` | | Connect via HTTP CONNECT proxy (host:port or URL) |\n| `--version` | | Print version and project URL (Cobra default; `-v` is `--verbose`) |\n\nColored output is enabled when stdout is a terminal and `NO_COLOR` is not set. Use `--no-color` to force plain output.\n\n### Exit codes\n\n- **0** — Success (schema printed or check completed)\n- **1** — Error (e.g. invalid URL, run failure, schema generation failed)\n- **2** — Usage / validation error (e.g. unknown profile, missing URL)\n\n## Current capabilities\n\n- URL normalization\n- DNS resolution, CAA lookup, IPv4 / IPv6 findings\n- TCP reachability\n- TLS protocol support probing\n- Weak cipher probing (e.g. 3DES, RSA CBC)\n- TLS fallback SCSV check (RFC 7507)\n- Certificate inspection and trust checks; full chain (leaf → intermediates → root) at the top of the report with days to expiry per cert\n- Missing intermediates resolved via AIA (HTTP) when possible, labeled as **fetched via AIA** vs **sent by server** vs **trust anchor**\n- OCSP stapling decode and active OCSP checks\n- ALPN probing, session resumption, no-SNI / wrong-SNI probing\n- Key exchange group probing, TLS 1.2 cipher preference\n- HTTP redirect and redirect chain analysis\n- HSTS, cookie security, and header policy checks (including HPKP deprecated notice)\n- Mixed-content detection and active HTTPS subresource host TLS checks\n- Cross-edge consistency findings\n- JSON and CSV output, JSON schema\n- Optional letter grade (A+–F) and colored text output\n\n## Scope and comparison\n\nsslcheck focuses on configuration and compliance checks that can be done with standard TLS and HTTP. It does **not** implement custom vulnerability probes such as Heartbleed, POODLE, DROWN, BEAST, or CRIME; for those, consider [testssl.sh](https://github.com/drwetter/testssl.sh) or the [Qualys SSL Labs](https://www.ssllabs.com/ssltest/) server test. sslcheck is suitable for local or CI use, single or batch URLs, and scripted reporting (JSON/CSV).\n\n## Notes\n\n- `HSTS max-age=0` is treated as a warning, not a failure.\n- Active HTTPS subresource hosts are validated separately so the tool can catch cases where the main page is trusted but scripts/iframes from another HTTPS origin have certificate errors.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fearentir%2Fsslcheck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fearentir%2Fsslcheck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fearentir%2Fsslcheck/lists"}