Skip to content

fix(tls): generate MITM certificates accepted by strict X509 clients - #264

Merged
congwang-mk merged 2 commits into
multikernel:mainfrom
jamesboyzj-design:fix/strict-mitm-tls
Oct 2, 2026
Merged

congwang-mk merged 2 commits into
multikernel:mainfrom
jamesboyzj-design:fix/strict-mitm-tls

Conversation

@jamesboyzj-design

Copy link
Copy Markdown
Contributor

Closes #263.

Changes

  • Set use_authority_key_identifier_extension on generated MITM leaf certificates.
  • Set KeyCertSign and CrlSign usages on the generated CA. Adding only AKI
    exposes the next strict-verification error: missing CA key usage.
  • Add an independent CLI integration test using a real loopback HTTPS server,
    synthetic bearer credential and Python VERIFY_X509_STRICT.

No client-verification bypass, dependency update, global trust-store edit or
policy change. Caller-provided CAs are not rewritten to add missing extensions.

Validation

Executed on Ubuntu 25.04 ARM64, Linux 7.0.14 (OrbStack), Landlock ABI 8,
Python 3.13.3, OpenSSL 3.4.1:

  • The probe fails against the unmodified upstream binary with missing AKI.
  • This exact upstream-only branch: cargo test --release -p sandlock-cli --test strict_tls: 1 passed.
  • cargo test --release -p sandlock-core --lib transparent_proxy:: -- --test-threads=1: 8 passed.

The integration test requires Python, OpenSSL CLI and the Debian-style system
CA bundle. It uses no public network service or production credential.
This PR does not enforce HTTPS-only credential injection and does not claim
validation of every cloud SDK or other CPU architecture.

Set leaf Authority Key Identifier and CA keyCertSign/cRLSign usages. Add a real local HTTPS probe with Python strict verification and synthetic credential injection; do not weaken client verification.

@congwang-mk congwang-mk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the fix itself looks right. rcgen's from_ca_cert_pem keeps the CA's SKI as PreSpecified, so the leaf AKI also matches bring-your-own CAs.

The test needs rework though:

  1. Location. This belongs in crates/sandlock-core/tests/integration/ (registered in tests/integration.rs), next to test_http_acl.rs and test_http_inject_ca.rs. The bug is in core and nothing here is CLI specific. Please use Sandbox::builder() with inline python3 -c, and no standalone .py file.

  2. No upstream needed. Strict verification fails during the client handshake with the proxy, before anything goes upstream. Allow GET allowed.test/*, inject the CA into a temp bundle, and have the sandboxed Python client (VERIFY_X509_STRICT) fetch https://denied.test/. Then assert it gets a 403 rather than SSLCertVerificationError. That removes the openssl CLI, the Debian-only /etc/ssl/certs/ca-certificates.crt path, the upstream certs and the SSL_CERT_FILE override, which would leak across tests if the supervisor runs in the test process. HTTPS credential injection end to end is a separate follow-up (see the note at the end of test_http_acl.rs).

  3. Unit test. Please add one in transparent_proxy/tls.rs that parses the minted leaf and CA with x509-parser (as a dev-dependency). It should assert that the leaf AKI equals the CA SKI and that the CA key usage includes keyCertSign. That guards the fix on any host with no external tools.

Exercise Sandbox MITM with an injected temporary CA bundle and assert the exact local HTTP ACL denial. Add production-minted certificate AKI/SKI and CA keyCertSign assertions using x509-parser.

Validated on Linux ARM64 with Python 3.13.3/OpenSSL 3.4.1, including independent AKI and key-usage red/green mutations. Focused tests pass. The full workspace suite reproduces the same four failures as pristine PR head; repository-wide formatting also has baseline failures.
@jamesboyzj-design

Copy link
Copy Markdown
Contributor Author

Hi,

Thanks for the detailed review. I’ve completed the requested revisions locally. They have not been pushed
yet.

The changes address all three points:

  1. Move regression coverage to core. Removed the two CLI test files and added a registered core integration
    test using Sandbox::builder() with inline Python.

  2. Remove the upstream-server fixture. The test uses an empty temporary CA bundle, http_inject_ca, explicit
    VERIFY_X509_STRICT, and normal certificate-chain and hostname verification. It requires HTTP 403 with
    the exact body Blocked by sandlock HTTP ACL policy.

    One adjustment to the suggested fixture: full Sandbox startup resolves concrete ACL hosts, and the proxy
    validates the request host against the destination IP. I therefore allow GET localhost/allowed and
    request https://localhost/denied. This avoids public DNS and system host-file changes while exercising
    the actual MITM and ACL path, without an upstream listener.

  3. Add certificate-structure unit tests. Using x509-parser, the tests explicitly require the generated CA’s
    SKI and keyCertSign usage, and verify that the production-minted leaf’s AKI matches that SKI. A small
    private mint helper is shared with server_config_for; caching, served-chain behavior, and caller-
    provided CA handling remain unchanged.

Validation

On Linux ARM64, Landlock ABI 8, Python 3.13.3 and OpenSSL 3.4.1:

  • Removing AKI independently causes both the unit test and strict TLS integration to fail.
  • Removing generated CA KeyUsage independently causes both tests to fail.
  • With both fixes present, proxy tests pass 10/10, CA injection 1/1, and HTTP ACL 15/15. The strict TLS
    integration also passes repeated runs.

The full workspace suite is not entirely green locally: 1682 passed, 4 failed, 8 ignored. The identical
command on the unmodified PR head reproduces the same four failures. Repository-wide formatting also has
baseline failures; the changed TLS/test files and git diff --check pass.

HTTPS credential injection E2E remains a separate follow-up, as requested. PR #265 is untouched.

@congwang-mk
congwang-mk merged commit 42be724 into multikernel:main Oct 2, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generated MITM certificates fail strict X509 verification (missing leaf AKI and CA key usage)

2 participants