fix: add remediations on EXT-2 DoS and Auth Failures#916
Merged
Conversation
OWASP security hardening across the KMS server: - EXT2-2/A03-2: TTLV binary parser recursion depth limit (MAX=64) + tests - EXT2-3/A03-3: TTLV XML parser stack depth limit (MAX=64) - EXT2-1/A04-1: HTTP payload limit 10GB -> 64MB (PayloadConfig + JsonConfig) - EXT2-5/A04-2: Rate-limiting via actix-governor (KMS_RATE_LIMIT_PER_SECOND config) - A05-1/A01-1: Replace Cors::permissive() on KMIP default scope with Cors::default() - A07-1: JWT algorithm confusion fix: asymmetric-only allowlist + explicit validation.algorithms - A07-2: API token constant-time comparison via subtle::ConstantTimeEq - A09-1: DB URL password masking in Display impl (mask_db_url_password helper) - A09-2: TLS P12 password proper [****] redaction - Update audit script CORS check for enterprise-integration scopes cargo clippy-all: clean cargo test-non-fips: 0 failures audit.sh: 8 PASS, 8 WARN, 0 FAIL
- Fix all Mermaid rendering failures in runtime_security_audit.md and crypto_inventory.md: replace — HTML entities, remove emoji from node labels, fix special characters (>=, quotes, wildcards), move PQC pie chart out of HTML div so MkDocs renders it, fix parallelogram shape with newline. - Add api_token_id, rate_limit_per_second, and cors_allowed_origins to kms_template.toml [http] section (used by --print-default-config). - Extend ckms configure wizard to cover all HttpClientConfig fields: verified_cert, database_secret, cipher_suites, custom_headers, and full proxy configuration (url, exclusion list, basic/custom auth). - Add runtime_security.sh black-box TLS/KMIP security analysis script. - Regenerate crypto_inventory.md with fixed diagrams and clean scorecard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CHANGELOG — test/owasp
Bug Fixes
Logging / Startup
HttpConfig::Displayno longer hardcodeshttp://; the scheme-lesshostname:portis now the canonicalDisplayform. A newHttpConfig::scheme(&self, tls: &TlsConfig) -> &strhelper returns"https"or"http"based onTlsConfig::is_tls_enabled().ClapConfig::Debugnow logs the correcthttps://…orhttp://…URL.Security
KMIP Protocol / Parser
MAX_TTLV_DEPTH = 64) to TTLV binary parser to prevent stack-overflowDoSvia deeply-nested structures; includes unit tests.MAX_XML_STACK_DEPTH = 64) to TTLV XML deserializer to preventDoSvia deeply-nested XML.HTTP Server
PayloadConfigandJsonConfig) to prevent memory exhaustionDoS.actix-governor) controlled byKMS_RATE_LIMIT_PER_SECOND/rate_limit_per_secondconfig field; disabled by default, enabling operators to prevent brute-force andDoSattacks.Cors::permissive()on the main KMIP default scope withCors::default()restricted to explicitly configured origins (cors_allowed_origins); addallow_any_method(),allow_any_header(), andsupports_credentials()so browser WASM UI clients can pass CORS preflight checks and carry session cookies; enterprise-integration scopes (Google CSE, MS DKE, AWS XKS) intentionally retain permissive CORS as required by their integration contracts.Authentication
RS*,ES*,PS*) checked beforeValidation::new(header.alg), and explicitly pinvalidation.algorithmsto prevent confusion attacks.==API-token comparison with constant-timesubtle::ConstantTimeEqto eliminate timing side-channel vulnerability.Logging / Credential Masking
Displayimpl ofMainDBConfigusingmask_db_url_password()helper (URL-parser-based, with multi-host PostgreSQL fallback).replace('.', '*')) with a proper[****]redaction.Session / Cookies
SameSiteattribute fromNonetoStrictto prevent CSRF attacks via cross-site request forgery.warn!log whenui_session_saltis not configured, directing operators to set a strong random salt for production multi-node deployments.SSRF Prevention
reqwestHTTP client withredirect::Policy::none()in both the JWKS fetcher (jwks.rs) and the UI OAuth token exchange (ui_auth.rs) to prevent SSRF via crafted 3xx redirect chains.Key Zeroization
derive_pbkdf2andderive_hkdfreturn types fromKResult<Vec<u8>>toKResult<Zeroizing<Vec<u8>>>so derived key bytes are scrubbed from memory on drop.Resource Limits
MAX_LOCATE_ITEMS = 1000server-side cap inlocate.rs; the effective limit ismin(client_requested_max, 1000)so an unbounded result set can no longer be requested.TTLV Binary Deserializer — OOM Guards
MAX_TTLV_FIELD_BYTES = 64 MiBper-field length guard toTTLVBytesDeserializer:ByteString,TextString, andBigIntegertypes now reject claims of length > 64 MiB immediately — before any memory allocation — preventing a minimal HTTP request from triggering a gigabyte-scalevec![0_u8; N]allocation.ByteString,TextString, andBigIntegerlength headers are rejected with a descriptive error.Logging
debug!towarn!for all 401-unauthorized paths injwt_token_auth.rsso authentication failures are visible at normal log levels.CORS — E2E Test Support
cors_allowed_originsfield toHttpConfig(envKMS_CORS_ALLOWED_ORIGINS, comma-separated) so the UI E2E test KMS instance can allow the Vite dev server origin (http://127.0.0.1:5173) without enabling permissive CORS in production.Cors::default()in actix-cors 0.6.5 starts with emptyallowed_methodsandallowed_headers, causing all CORS preflight method checks to fail even when an explicit origin is listed. Moved.allow_any_method().allow_any_header()before the origin loop to ensure methods and headers are always configured when building the CORS policy.--cors-allowed-origins, causing identicalTypeError: Failed to fetchfailures in Chromium. Moved the Vite preview port selection before KMS startup and pass the origin to the KMS via--cors-allowed-origins.Audit
.github/scripts/audit/owasp.shCORS check to distinguish enterprise-integration scopes (WARN) from main KMIP scope (FAIL), and add JWT algorithm allowlist check that verifiesvalidation.algorithmsassignment.JWKS HTTPS Guard
validate_jwks_uris_are_https()startup guard instart_kms_server.rs; any JWKS URI that does not use thehttpsscheme causes the server to refuse to start. Guard is gated behind#[cfg(not(feature = "insecure"))]. Unit tests J1–J4 cover rejection, acceptance, empty list, and mixed-list scenarios.Dependency Policy
[[bans.features]]entry indeny.tomlbanningserde_json::unbounded_depth; this feature removes the built-in 128-level JSON recursion limit and is a direct DoS regression vector.Testing
Security regression tests
crate/server/src/config/command_line/db.rs: N1–N5 tests formask_db_url_password()covering Postgres single-host, MySQL, Postgres multi-host, no-password, and invalid URL edge cases.crate/server/src/middlewares/jwt/jwt_config.rs: A1–A6 tests for the JWT algorithm allowlist (HS256/HS384/HS512 rejected; RS256/ES256/PS256 accepted) using the production constantALLOWED_JWT_ALGORITHMS.crate/server/src/start_kms_server.rs: J1–J4 tests for the JWKS HTTPS startup guard.crate/clients/clap/src/tests/serialization/batch_abuse.rs: B1–B5 tests that submit KMIP batch requests with mismatchedBatchCountvalues and verify the server does not return 500.crate/clients/clap/src/tests/security/privilege_bypass.rs: PB1–PB4 tests verifying that privileged user scope does not bleed into read/export operations for other users.crate/clients/clap/src/tests/security/cors_config.rs: C1–C3 tests verifying no-wildcard CORS policy (no foreign origin reflected inAccess-Control-Allow-Origin).crate/server/src/middlewares/jwt/jwks.rs: SR1–SR2 SSRF regression tests verifying that a 307 redirect from a JWKS endpoint is not followed.HSM
test_hsm_*_allfor Proteccio, Utimaco, SoftHSM2, Crypt2pay, and SmartcardHSM: each sub-test was creating its ownBaseHsminstance, causing repeatedC_Initialize/C_Finalize/dlclose/dlopencycles within the same process. The_alltest functions now create a singleBaseHsmandArc<SlotManager>and call the shared helpers directly, ensuring only oneC_Initializeand oneC_Finalizecall per test run.KMIP Protocol Tests
crate/kmip/src/ttlv/tests/wire_edge_cases.rs).crate/kmip/src/ttlv/tests/xml_edge_cases.rs).TTLVBytesDeserializer:remaining -= item_lengthreplaced withchecked_subto prevent wrapping on malformed child-length fields.CLI Security Tests
serialization/wire_payloads.rs).serialization/batch_abuse.rs).InvalidRequesterror instead of allocating gigabytes of memory (oom/large_payloads.rs).security/access_control.rs).security/lifecycle.rs).security/uid_injection.rs).Server — Resource Limit Fix
create_symmetric_key_and_tags: reject any request withcryptographic_length < 8or> 8192bits withInvalidRequestto prevent 128 MB+ key-material allocation attacks.THREE_DESretains its existing exact-value validation (112 or 168 bits).Documentation
.github/scripts/audit/:owasp.sh(OWASP Top 10, 21 checks, JSON output, updatessecurity_audit.md),multi_framework.sh(NIST CSF 2.0/SSDF, CIS Controls v8, ISO/IEC 27034, OSSTMM — 21 checks: gitleaks, cargo audit, cargo deny, unsafe count, JWKS HTTPS guard, CORS wildcard, TTLV depth, JWT allowlist, SSRF guard, TLS config, Zeroize usage), and unified entry-pointaudit.sh.documentation/docs/certifications_and_compliance/multi_framework_security_audit.md— comprehensive multi-framework security audit report mapping all findings to NIST CSF 2.0, SSDF SP 800-218, CIS Controls v8, ISO/IEC 27034, and OSSTMM controls, with a remediation matrix cross-referencing all 8 closed findings.documentation/mkdocs.yml— add Multi-Framework Security Audit page underCertifications and compliance.SameSite::Strict, JWT log level (warn!), reqwest redirect disable, session key salt warning, andMAX_LOCATE_ITEMSconstant.update_audit_md()function that automatically updates the Remediation Priority Matrix inaudit.mdfromOpento✅ Fixed/⚠️ Mitigatedbased on check results.audit.mdRemediation Priority Matrix: all High and most Medium findings now marked✅ Fixedor⚠️ Mitigated.audit.mdtodocumentation/docs/certifications_and_compliance/security_audit.mdand add page todocumentation/mkdocs.ymlnavigation under Certifications & Compliance..github/scripts/audit/owasp.shdefault output path todocumentation/docs/certifications_and_compliance/audit-results/<timestamp>/; add.gitignoreto exclude per-run output files from git.Audit reports reorganization
security_audit.md→cryptographic_algorithms/audit/owasp_security_audit.mdandmulti_framework_security_audit.md→cryptographic_algorithms/audit/multi_framework_security_audit.md; moveaudit-results/timestamped directories into the same subfolder.documentation/mkdocs.ymlnavigation: addAuditsection underCryptographic algorithmscontaining both audit pages; remove the top-level audit page entries fromCertifications and compliance.crypto_inventory.md,risk_score.py(Related documentation section),.github/scripts/audit/owasp.sh(hardcodedAUDIT_MDandOUTPUT_DIRpaths).Build
OpenSSL
crate/crypto/build.rsdownload URL to GitHub releases and SHA-256 hash; updatenix/common.nixSRI hash; update all 3.6.0 version strings innix/kms-server.nix.default.nixopenssl36Argsblock retained the 3.6.0 URL/hash from before the upgrade; updated version,srcUrl,sha256SRI, andexpectedHashto 3.6.2; also updated allopenssl-3.6.0-linux/openssl-non-fips-3.6.0-linuxstaging path references incrate/server/Cargo.toml,crate/clients/ckms/Cargo.toml,.github/scripts/package/package_common.sh,.github/scripts/package/smoke_test_linux.sh, and.github/scripts/package/smoke_test_dmg.sh.Refactor
cosmian_kmip — LEB128 serialization
crate/kmip/src/bytes_ser_de.rs(local LEB128Serializer/Deserializerimplementation) in favor of the upstreamcosmian_crypto_core::bytes_set_demodule which is actively maintained and includes a buffer-bounds check before allocation inread_vec(); addcosmian_crypto_coredependency tocosmian_kmip; addFrom<CryptoCoreError>forKmipError.CBOM / Cryptographic sensor
cbom/cbom.cdx.json: replace 63 invalid"executionEnvironment": "software"values with"software-plain-ram"(valid CycloneDX 1.6 enum); validation viavalidate_cbom.pynow passes..github/scripts/crypto_sensor/scripts to be project-agnostic:scan_source.py: add--scan-dirsargument (default:crate) so the scanner can target any Rust source directory; remove hardcodedcrate/path andcrate/ not founderror.risk_score.py: add--project-nameargument (auto-detected fromCargo.tomlif omitted); replace hardcoded Cosmian KMS Mermaid dependency graph with a dynamically generated flowchart from scan data; addimport re.crypto_sensor.sh: add--scan-dirs,--project-name, and--docs-outputoptions; auto-detect project name from rootCargo.toml; remove hardcodedDOCS_PAGEassignment from risk-scoring step (now set once at top level); pass--scan-dirstoscan_source.pyand--project-nametorisk_score.py..github/scripts/crypto_sensor/into.github/scripts/audit/; the three scripts (crypto_sensor.sh,scan_source.py,risk_score.py) now live alongsideowasp.sh,multi_framework.sh, andaudit.sh.audit.sh(main entry point) to also invokecrypto_sensor.shas step 3; add--quick,--server-url, and--update-cbomrouting fromaudit.shtocrypto_sensor.sh.--quickflag tocrypto_sensor.sh: skips cargo audit (step 2), cdxgen (step 4), TLS scan (step 5), and CBOM update — runs only source scan + risk scoring; suitable for pre-commit.KMIP_SPEC_PATH_FRAGMENTSandkmip_mitigation()to module level inrisk_score.py; addmitigatedandmitigation_notefields to the JSON finding output; exit 1 only when there are unmitigated CRITICAL findings (not all CRITICALs), so the scanner passes when all criticals are KMIP-spec artefacts.⚠️ Mitigated — <reason>in the Remediation / Mitigation column so auditors have full visibility while understanding the context.crypto-inventory-updatepre-commit hook (triggers on*.rsfile changes): callscrypto_sensor.sh --quickto regeneratedocumentation/docs/certifications_and_compliance/crypto_inventory.mdautomatically on every Rust commit.risk_score.py: Layer 1 readsalgorithm_policy.rsdeny-list (DES/3DES,RC4,MD5,SHA-1) viaload_algorithm_deny_list(); Layer 2 checks expandedKMIP_SPEC_PATH_FRAGMENTScovering crypto, HSM, WASM, test utilities; findings blocked at policy level report "Blocked byalgorithm_policy.rs…"; result: 0 unmitigated CRITICAL and 0 unmitigated HIGH.sys.exit(1)fromscan_source.pyfor CRITICAL findings; the policy-awarerisk_score.pynow owns the pass/fail decision for unmitigated criticals..github/scripts/audit/runtime_security.sh: black-box runtime network security analyser usingopenssl s_client+curl+ optionalnmap/sslyze/nuclei; 7 test groups (reachability, TLS protocol versions, cipher suites, certificate chain, HTTP security headers, mTLS, KMIP protocol probes including SQL injection / OOM / rate-limit tests); outputs JSON + text artefacts undercbom/runtime-<timestamp>/.documentation/docs/certifications_and_compliance/cryptographic_algorithms/audit/runtime_security_audit.md: full MkDocs Material dashboard with Mermaid attack-surface map, network topology, TLS handshake sequence, cipher suite table, certificate chain diagram, HTTP headers matrix, mTLS architecture, KMIP probe flowchart, and STRIDE threat model table.documentation/mkdocs.ymlunder theAuditsection.crypto_sensor.shnow writes to stablecbom/sensor/andruntime_security.shwrites to stablecbom/runtime/— overwritten on each run instead of accumulating timestamped directories.crypto_inventory.mdheader and admonition (commit SHA retained);crypto_inventory.mdis unconditionally regenerated on every sensor run.crypto_inventory.md; mitigated findings are suppressed (count still shown in scorecard) — table now only shows genuinely actionable items; result: 0 rows in table, ✅ success admonition.xychart-betaMermaid diagram inruntime_security_audit.md(unsupported by MkDocs Material Mermaid); replaced with agraph LRshowing per-protocol accept/reject with colour-coded nodes.cbom/runtime-TIMESTAMP/path references inruntime_security_audit.mdto stablecbom/runtime/.runtime_security_audit.mdandcrypto_inventory.md: replace—HTML entities with—, remove emoji from edge labels, remove special characters (≥,'self',*) from Mermaid node labels, fix parallelogram node with\n, remove PQC pie chart from inside HTML<div>(was not rendered), remove emoji from "How the Sensor Works" flowchart labels.api_token_id,rate_limit_per_second, andcors_allowed_originsfields to[http]section ofcrate/server/kms_template.toml(used by--print-default-config); all fields documented with configuration guidance.ckms configurewizard (configure_httpincommands.rs) to cover allHttpClientConfigfields: CA cert for server verification (verified_cert), database secret (database_secret), TLS cipher suites (cipher_suites), custom HTTP headers (custom_headers), and full interactive proxy configuration (proxy_paramswith URL, auth, exclusion list).certifications_and_compliance/docs: movecbom.md,sbom.md,owasp_security_audit.md,multi_framework_security_audit.md,runtime_security_audit.md, andcrypto_inventory.mdinto a newaudit/subdirectory; update all relative links in moved files and inrisk_score.pygenerated templates; updatemkdocs.ymlto placeSBOM,CBOM, and all audit pages under a singleAudit:section..github/scripts/docs/generate_docs.sh: master doc-generation script replacing scattered individual calls; runs all 5 steps (server docs, ckms docs, KMIP tables, crypto inventory, CBOM) with per-step skip flags; used byrelease.ymlandrelease.sh; the pre-commitgenerate-docshook (replacesrenew-server-doc,renew-ckms-markdown,crypto-inventory-update) now calls this single entry point.renew-server-doc,renew-ckms-markdown, andcrypto-inventory-updatehooks with a singlegenerate-docshook that callsgenerate_docs.sh --skip-cbom.