Transport security where the client establishes trust: TLS version floor, certificate chain and hostname verification, the trust store, connecting by IP, mTLS and workload identity as authentication, gRPC channel credentials, and SMTP STARTTLS. Use when generating HTTP, gRPC, or SMTP clients and servers, configuring TLS in code or platform config, wiring service-to-service authentication, or when tempted to disable certificate verification.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add ShieldNet-360/secure-vibe --skill protocol-security --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Protocol Security?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/shieldnet-360-protocol-security)More formats (shields.io, HTML) on the badges page.
---
name: protocol-security
description: "Transport security where the client establishes trust: TLS version floor, certificate chain and hostname verification, the trust store, connecting by IP, mTLS and workload identity as authentication, gRPC channel credentials, and SMTP STARTTLS. Use when generating HTTP, gRPC, or SMTP clients and servers, configuring TLS in code or platform config, wiring service-to-service authentication, or when tempted to disable certificate verification."
---
<!-- Native skill bundle for agent-skills (cross-tool convention). Generated by `secure-vibe dev regenerate`. -->
<!-- Do not edit by hand; the source of truth is skills/protocol-security/SKILL.md. -->
# Protocol Security
Transport security where the client establishes trust: TLS version floor, certificate chain and hostname verification, the trust store, connecting by IP, mTLS and workload identity as authentication, gRPC channel credentials, and SMTP STARTTLS. Use when generating HTTP, gRPC, or SMTP clients and servers, configuring TLS in code or platform config, wiring service-to-service authentication, or when tempted to disable certificate verification.
## ALWAYS
- Default to **TLS 1.3**, and permit TLS 1.2 only where a peer genuinely requires it. Disable TLS 1.0, 1.1, and every SSL version. Cipher-suite selection is a consequence of the version floor rather than a separate decision — `references/tls-configuration.md` carries the suite lists and the per-platform config keys.
- Verify the full certificate chain on every connection: a trusted issuer, an unexpired validity window, and a hostname that matches a **`subjectAltName` dNSName** entry. The hostname is checked *against* the SAN — SAN is not an alternative place to look, and a `CN` match is not a fallback, because current browsers and TLS libraries removed CN as a hostname source.
- When connecting to an **IP address** rather than a name, set the expected name explicitly (`ServerName` in Go's `tls.Config`, the equivalent SNI/verification hostname elsewhere) so verification has something to check, or require a certificate carrying an `iPAddress` SAN. Reaching an endpoint by IP is the single most common reason a developer disables verification — this is the fix that keeps it on.
- Resolve a self-signed or internal-CA endpoint by **adding that CA to the client's trust configuration**, not by turning verification off. Every language has a way to supply a custom root pool; using it keeps hostname and expiry checks intact, which is exactly what the shortcut discards.
- Use **mutual TLS** for service-to-service traffic inside a trust domain, and treat it as what it is: a cryptographic caller identity, which *is* authentication — unlike network position, which is not. A SPIFFE workload identity (`spiffe://trust-domain/...`) with short-lived certificates is the form of this worth reaching for over a long-lived shared API key.
- For gRPC, build the channel with credentials: Python `grpc.secure_channel(target, grpc.ssl_channel_credentials())`, Go `grpc.WithTransportCredentials( credentials.NewTLS(cfg))`. The insecure variants exist for local development and say so in their names.
- For SMTP, either connect with **implicit TLS** (submissions, port 465) or issue `STARTTLS` on submission (port 587) and **fail if the upgrade does not happen**. An on-path attacker strips the server's STARTTLS advertisement and a client that treats TLS as opportunistic then sends credentials in plaintext without error. Verify the certificate after the upgrade, exactly as for any other connection.
- Track certificate expiry and automate renewal. An expired certificate is among the most common real transport incidents, and the pressure it creates is what produces the `InsecureSkipVerify` that outlives it.
- Consult `frontend-security` for HSTS and the browser response-header set, `websocket-security` for `Origin` validation and handshake authentication, `database-security` for database transport, and `mobile-security` before adding certificate pinning — that skill owns the rotation planning that decides whether a pin is a control or a future outage.
## NEVER
- Disable certificate verification: `InsecureSkipVerify: true`, `verify=False`, `rejectUnauthorized: false`, `CURLOPT_SSL_VERIFYPEER=0`, `NODE_TLS_REJECT_UNAUTHORIZED=0`, `OpenSSL::SSL::VERIFY_NONE`. Each of these turns off chain, expiry, and hostname checking together, which is why "just to get past this one certificate error" removes three controls rather than one.
- Implement a custom trust callback that accepts everything — an `X509TrustManager` with an empty `checkServerTrusted`, a `HostnameVerifier` returning `true`, a `URLSessionDelegate` that trusts any challenge, a `ServerCertificateValidationCallback` returning `true`. These are the same defect as the flag above, written so a reviewer has to read the body to see it.
- Send credentials, tokens, or session material over plaintext — including on a private network, where an internal foothold or a co-tenant reads it.
- Use `grpc.insecure_channel(...)` or `insecure.NewCredentials()` in production.
## KNOWN FALSE POSITIVES
- A test that runs against a localhost ephemeral certificate may pin a custom root or skip verification, provided the code path cannot be reached by a production build. The finding is a dev shortcut that ships, not the existence of the test.
- Pinning `MinVersion` to TLS 1.2 is correct where a named peer requires it and the reason is recorded. What is not correct is a 1.2 floor with no such peer, which is the version this skill's default rules out.
- A client that supplies its own root CA pool is doing verification, not bypassing it — the finding is an empty or always-true trust callback, not a non-system trust store.
- A plaintext listener that exists only to redirect to HTTPS is expected. The finding is a plaintext listener that serves content.
## Reference files
Read these only when the task calls for them.
- `references/tls-configuration.md`
- `references/verifying-findings.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!