-
Notifications
You must be signed in to change notification settings - Fork 0
fix(ci): pin GitHub-hosted Ubuntu runner image #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aa54807
2770b57
33ebae0
2d41c40
9a159dd
b663f9d
d8d82cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # Doctoring — fail-closed management authentication | ||
|
|
||
| This note grounds the issue #78 implementation: non-loopback listeners refuse to become ready without a write-capable administrator principal, authentication and authorization failures remain distinct, and presented administrator secrets are compared without early-exit content comparison. IEEE PDFs are not redistributed; freely accessible standards are cited by stable locators. | ||
|
|
||
| ## Adopted standards and literature | ||
|
|
||
| Saltzer, J. H., & Schroeder, M. D. (1975). The protection of information in computer systems. *Proceedings of the IEEE, 63*(9), 1278–1308. https://doi.org/10.1109/PROC.1975.9939 | ||
|
|
||
| - **Design impact:** Fail-safe defaults require missing access authority to deny rather than silently enable management writes. Wardnet therefore refuses readiness when a non-loopback listener lacks a write-capable administrator credential. | ||
|
|
||
| OWASP Foundation. (2025). *OWASP Application Security Verification Standard 5.0.0*. https://owasp.org/www-project-application-security-verification-standard/ | ||
|
|
||
| - **Design impact:** Administrative functions require authentication and authorization. Wardnet returns `401` for an unauthenticated management request and `403` when an authenticated readonly principal attempts a mutation, without disclosing the expected secret or role. | ||
|
|
||
| National Institute of Standards and Technology. (2022). *Secure Software Development Framework (SSDF) version 1.1* (NIST SP 800-218). https://doi.org/10.6028/NIST.SP.800-218 | ||
|
|
||
| - **Design impact:** Authentication data is loaded through the credential bootstrap boundary rather than embedded in distributable assets. Health output exposes only non-secret configuration state such as authentication mode and credential source. | ||
|
|
||
| MITRE. (n.d.). *CWE-306: Missing authentication for critical function*. https://cwe.mitre.org/data/definitions/306.html | ||
|
|
||
| - **Design impact:** Management APIs that mutate routes, threat indicators, DNSBL entries, license state, or feeds are critical functions. The runtime gate rejects the unsafe combination of a reachable non-loopback listener and missing write-capable authentication. | ||
|
|
||
| ## Redistributable research artifact | ||
|
|
||
| `docs/papers/nist-sp-800-218-ssdf.pdf` is the NIST SP 800-218 Version 1.1 PDF published by the National Institute of Standards and Technology. Authoritative source: https://doi.org/10.6028/NIST.SP.800-218 (NIST publication record and official PDF). NIST states that SP 800-series publications are not subject to copyright in the United States and that attribution is appreciated; NIST's Technical Series policy also grants a worldwide royalty-free right to reprint covered NIST works. The repository therefore retains the exact PDF as research evidence with this attribution: “Republished courtesy of the National Institute of Standards and Technology.” The publication remains authoritative at NIST; the repository copy is evidence only and does not supersede the official source. | ||
|
|
||
| NIST SP 800-218 Rev. 1 / SSDF 1.2 is still an Initial Public Draft as of this doctoring update, so the implemented control continues to cite final SP 800-218 Version 1.1 rather than presenting the draft as a final standard. | ||
|
|
||
| ## Implementation binding | ||
|
|
||
| | Decision | Implementation boundary | | ||
| | --- | --- | | ||
| | Fail closed on public bind | `require_write_auth_for_bind` before listener readiness | | ||
| | Loopback development remains usable | loopback-only listener detection and `/healthz.auth_mode=development` | | ||
| | Authentication vs authorization | management write rejection distinguishes `401` and `403` | | ||
| | Constant-time credential handling | administrator-token comparison uses a bounded constant-work comparison path | | ||
| | Blank credential path | an empty or whitespace credentials-path bootstrap value is treated as unset | | ||
| | Smoke-test credential | `scripts/smoke.sh` creates a per-process administrator token instead of shipping a repository credential | | ||
| | Ambiguous token registry | strict administrator-token parsing rejects duplicate, blank, or unknown-role entries | | ||
|
|
||
| PII is not blanket-masked from security evidence when doing so would make incident response unusable. Purpose-bound authorization, least privilege, auditability, retention controls, and encryption are the preferred controls for operationally necessary security data. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,11 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | |
| TMP_DIR="$(mktemp -d)" | ||
| STATE_FILE="$TMP_DIR/state.json" | ||
| LOG_FILE="$TMP_DIR/server.log" | ||
| ADMIN_TOKEN_VALUE="dev-secret" | ||
| ADMIN_TOKEN_VALUE="$(python3 - <<'PY' | ||
| import secrets | ||
| print(secrets.token_hex(16)) | ||
| PY | ||
| )" | ||
| PORT="$(python3 - <<'PY' | ||
| import socket | ||
| s = socket.socket() | ||
|
|
@@ -27,10 +31,14 @@ cleanup() { | |
| trap cleanup EXIT | ||
|
|
||
| start_server() { | ||
| # Compile before the health wait so rustc time is not counted as a hang. | ||
| cargo build --quiet --manifest-path "$ROOT_DIR/Cargo.toml" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Sensitive Data Exposure (CWE-367): Time-of-check Time-of-use (TOCTOU) Race Condition Reachability: External · Exploitability: Difficult 게이트웨이 readiness 행을 확인한 후 관리자 토큰을 전송하십시오.
🤖 Prompt for AI Agents |
||
| ( | ||
| cd "$ROOT_DIR" | ||
| BIND_ADDR="127.0.0.1:$PORT" \ | ||
| ADMIN_TOKEN="$ADMIN_TOKEN_VALUE" \ | ||
| ADMIN_TOKENS= \ | ||
| WAF_IDS_CREDENTIALS_PATH= \ | ||
| WAF_IDS_STATE_PATH="$STATE_FILE" \ | ||
| DNSBL_ORIGIN="dnsbl.test" \ | ||
| EVENT_LIMIT="5" \ | ||
|
|
@@ -77,6 +85,8 @@ assert_json_field "$health" 'data["status"] == "ok"' | |
| assert_json_field "$health" 'data["persistence"] == "file"' | ||
| assert_json_field "$health" 'data["dnsbl_origin"] == "dnsbl.test"' | ||
| assert_json_field "$health" 'data["event_limit"] == 5' | ||
| assert_json_field "$health" 'data["admin_auth_configured"] is True' | ||
| assert_json_field "$health" 'data["auth_mode"] == "production"' | ||
|
|
||
| curl -fsS "$BASE_URL/admin" | grep -q "ContextualWisdomLab WAF/IDS/AI SOC Gateway" | ||
|
|
||
|
|
@@ -187,7 +197,7 @@ assert_json_field "$support_bundle" 'data["kpis"]["fresh_threat_feed_count"] == | |
| assert_json_field "$support_bundle" 'data["audit_log_count"] >= 3' | ||
| assert_json_field "$support_bundle" 'data["threat_feed_freshness"][0]["stale"] is False' | ||
|
|
||
| audit_logs="$(curl -fsS "$BASE_URL/api/audit-logs")" | ||
| audit_logs="$(curl -fsS -H "x-admin-token: $ADMIN_TOKEN_VALUE" "$BASE_URL/api/audit-logs")" | ||
| assert_json_field "$audit_logs" 'any(log["action"] == "upsert_route" and log["resource_id"] == "block" for log in data)' | ||
| assert_json_field "$audit_logs" 'any(log["action"] == "update_commercial_license" and log["resource_id"] == "cwlab-enterprise" for log in data)' | ||
| assert_json_field "$audit_logs" 'any(log["action"] == "import_threat_feed" and log["resource_id"] == "misp-seoul" for log in data)' | ||
|
|
@@ -212,7 +222,7 @@ license="$(curl -fsS "$BASE_URL/api/commercial/license")" | |
| assert_json_field "$license" 'data["license_status"] == "active"' | ||
| feeds="$(curl -fsS "$BASE_URL/api/threat-feeds")" | ||
| assert_json_field "$feeds" 'len(data) == 1' | ||
| audit_logs="$(curl -fsS "$BASE_URL/api/audit-logs")" | ||
| audit_logs="$(curl -fsS -H "x-admin-token: $ADMIN_TOKEN_VALUE" "$BASE_URL/api/audit-logs")" | ||
| assert_json_field "$audit_logs" 'len(data) >= 3' | ||
|
|
||
| echo "smoke ok: $BASE_URL with state $STATE_FILE" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
최신 NIST SP 800-63B 인용으로 교체하십시오.
이 인용은 2020년판 SP 800-63B를 가리킵니다. NIST는 2025년 7월에 최종판 SP 800-63B-4를 발행했고, 기존 SP 800-63B는 2025년 8월 1일에 철회되었습니다. 현재 인증 근거로 제시하는 문서이므로 참고 문헌을 SP 800-63B-4로 갱신하십시오. (csrc.nist.gov)
🤖 Prompt for AI Agents