This document provides comprehensive security information for developers and operators using wsc (WebAssembly Signature Component).
- Overview
- Keyless Signing Security Model
- Certificate-Based Signing Security
- Security Guarantees
- Threat Model
- Operational Security
- Certificate Pinning
- Comparison with Other Systems
wsc provides two signing approaches, each with distinct security models:
- Keyless Signing - Ephemeral keys with OIDC identity and Rekor transparency log
- Certificate-Based Signing - Long-lived keys with X.509 PKI and hardware security
This document focuses primarily on keyless signing security (addressing Issues #4 and #2).
┌─────────────┐ ┌──────────────┐ ┌───────────┐
│ CI/CD │────▶│ OIDC Token │────▶│ Fulcio │
│ Environment │ │ (Identity) │ │ (Certs) │
└─────────────┘ └──────────────┘ └─────┬─────┘
│
┌───────────────────────────┘
│
▼
┌───────────────┐
│ Ephemeral │
│ ECDSA P-256 │◀───── Generated on-demand
│ Private Key │ Zeroized after use
└───────┬───────┘
│
│ Signs
▼
┌───────────────┐
│ WASM Module │
│ + Signature │
└───────┬───────┘
│
│ Upload
▼
┌───────────────┐
│ Rekor Log │◀───── Public transparency
│ (Timestamp + │ Inclusion proof
│ Proof) │ Checkpoint signature
└───────────────┘
Keyless signing uses ephemeral ECDSA P-256 keys that exist only for the duration of a single signing operation.
// Generated using cryptographically secure random number generator
let signing_key = SigningKey::<p256::NistP256>::random(&mut OsRng);Security Properties:
- Generated using OS-provided CSPRNG (
OsRng) - 256-bit key strength (128-bit security level)
- Never written to disk
- Never leaves process memory
let verifying_key = signing_key.verifying_key();
let public_key_bytes = verifying_key.to_encoded_point(false);Security Properties:
- Public key can be freely shared
- Used for Fulcio certificate request
- Encoded in uncompressed SEC1 format
let certificate = fulcio.get_certificate(&oidc_token, public_key, &proof)?;Process:
- Prove possession of private key (sign OIDC
subclaim) - Fulcio validates OIDC token
- Fulcio issues short-lived X.509 certificate (~10 minutes validity)
- Certificate binds public key to OIDC identity
Trust Assumptions:
- OIDC provider correctly authenticates user
- Fulcio CA is trusted and not compromised
- Network connection to Fulcio is secure (TLS)
let module_hash = Sha256::digest(&module_bytes);
let signature = signing_key.sign_digest(module_hash);Security Properties:
- Signs SHA-256 hash of WASM module
- Signature binds to exact module content
- Uses ECDSA with deterministic nonce (RFC 6979)
let rekor_entry = rekor.upload_entry(&module_hash, &signature, &certificate)?;Process:
- Upload signature + certificate + hash to Rekor
- Rekor validates and timestamps the entry
- Returns signed entry timestamp (SET) and inclusion proof
- Provides public auditability
Security Properties:
- Immutable public log (append-only)
- Cryptographic proof of inclusion in log
- Timestamped by trusted timestamping authority
- Enables detection of misissuance or compromise
// Automatic when signing_key goes out of scope
// SigningKey's internal SecretKey implements ZeroizeOnDropSecurity Properties:
- Private key bytes overwritten with zeros
- Happens even on panic/error (Rust Drop guarantee)
- Prevents key recovery from memory dumps
- Mitigates cold boot attacks
Implementation: See src/lib/src/signature/keyless/signer.rs:142-157
-
OIDC Provider (e.g., GitHub Actions)
- Correctly authenticates workflow identity
- Protects token issuance
- Provides authentic
subandissclaims
-
Fulcio Certificate Authority
- Issues certificates only for valid OIDC tokens
- Properly validates proof of possession
- Certificate validity period is accurate (~10 min)
- Root CA private key is secure
-
Rekor Transparency Log
- Accepts and timestamps all entries honestly
- Provides correct inclusion proofs
- Signed tree heads (checkpoints) are authentic
- Log is append-only and immutable
-
Cryptographic Primitives
- ECDSA P-256 is secure (no known practical attacks)
- SHA-256 is collision-resistant
- Random number generator is unpredictable
- Zeroize library correctly clears memory
-
Rust Language & Libraries
- Memory safety prevents use-after-free, buffer overflows
- Type system prevents many logic errors
p256,ecdsa,webpkicrates are correctly implemented
-
The Signer's Environment
- May be compromised or malicious
- Ephemeral key only exists during signing
- No long-lived secrets to steal
-
Network Infrastructure
- TLS protects in transit
- But assumes HTTPS is properly configured
- Certificate pinning can be added (Issue #12)
-
Verification Environment
- Verifier must have correct Fulcio root CA
- Must check Rekor inclusion proof
- Must validate certificate at correct timestamp
Attack: Adversary steals OIDC token from environment variables.
Impact: Can request Fulcio certificate for stolen identity.
Mitigations:
- Tokens are single-use with short lifetime (~15 minutes)
- Token zeroized from memory after use (Issue #11 ✅)
- Rekor log provides audit trail of all signatures
- Token theft requires environment access (same as private key theft)
Residual Risk: LOW - Token lifetime limits exposure window
Attack: Memory dump or debugger extracts private key.
Impact: Can forge signatures for the duration of key's lifetime.
Mitigations:
- Key exists only during signing operation (<1 second)
- Zeroized immediately after use (Issue #14 ✅)
- Requires attacker to time attack perfectly
- Signature is logged in Rekor (detectable)
Residual Risk: VERY LOW - Tiny attack window
Attack: Intercept communication with Fulcio/Rekor.
Impact: Could steal OIDC token, modify responses.
Mitigations:
- TLS encryption for all HTTPS requests
- Fulcio certificate chains to trusted root
- Rekor entries have signed timestamps
- Certificate pinning available (Issue #12 - future)
Residual Risk: LOW - Requires TLS compromise
Attack: Modify Rekor log after signature creation.
Impact: Could hide evidence of signature or forge timestamps.
Mitigations:
- Merkle tree inclusion proofs (Issue #15 ✅)
- Signed tree heads (checkpoints) from Rekor
- Gossip protocol for checkpoint consistency (Sigstore project)
- Multiple monitors can detect tampering
Residual Risk: LOW - Cryptographically protected
Threat: Fulcio or Rekor completely compromised.
Rationale: If core infrastructure is compromised, system security fails. This is a trust anchor. Mitigation requires infrastructure-level security (HSMs, monitoring, incident response) which is Sigstore's responsibility.
Threat: Timing attacks, power analysis, electromagnetic emanation.
Rationale:
- p256 crate uses constant-time operations
- ECDSA nonce is deterministic (RFC 6979), eliminating nonce attacks
- Ephemeral keys reduce exposure window
- Production environments typically not vulnerable to physical side-channels
Threat: Shor's algorithm breaks ECDSA.
Rationale:
- Not currently practical
- Post-quantum migration is industry-wide effort
- Ephemeral keys limit retroactive compromise risk
- Will adopt post-quantum algorithms when standardized
✅ Authenticity - Signature proves WASM module came from specific OIDC identity ✅ Integrity - Any modification to module invalidates signature ✅ Non-Repudiation - Public Rekor log prevents denial of signing ✅ Freshness - Rekor timestamp proves when signature was created ✅ Auditability - All signatures publicly logged and verifiable ✅ No Key Management - No long-lived private keys to protect
❌ Revocation - Cannot revoke a signature after creation (certificate expired anyway) ❌ Offline Verification - Requires Rekor access for inclusion proof ❌ Anonymity - OIDC identity is in certificate (intentional) ❌ Forward Secrecy - Compromise of Fulcio CA root invalidates all past signatures
| Property | Keyless | Certificate-Based |
|---|---|---|
| Offline verification | ❌ No (needs Rekor) | ✅ Yes |
| Key management | ✅ None | ❌ Complex |
| Transparency log | ✅ Yes (Rekor) | ❌ No |
| Hardware security | ✅ Yes (ATECC608) | |
| Revocation | ❌ Expiry only | ❌ Expiry only |
| Internet required | ✅ Yes (signing) | ❌ No |
| Best for | CI/CD, cloud | IoT, embedded, air-gapped |
GitHub Actions Example:
permissions:
id-token: write # Required for OIDC token
steps:
- uses: actions/checkout@v4
- run: wasmsign2 sign --keyless -i module.wasm -o signed.wasmSecurity Checklist:
- ✅ Enable
id-token: writepermission - ✅ Verify workflow identity matches expectations
- ✅ Review Rekor log for unexpected signatures
- ✅ Use branch protection to control who can trigger workflows
Verification includes:
- Certificate chain validation (to Fulcio root CA)
- Certificate validity at Rekor timestamp
- Signature verification against module hash
- Rekor inclusion proof verification
- Optional: identity and issuer validation
Example:
KeylessVerifier::verify(
&module,
Some("https://github.com/owner/repo/.github/workflows/build.yml@refs/heads/main"),
Some("https://token.actions.githubusercontent.com")
)?;Monitor Rekor for:
- Unexpected signatures from your identity
- Signatures outside normal build times
- Signatures for unknown modules
Tools:
- Rekor search API:
https://rekor.sigstore.dev/api/v1/log/entries/retrieve - Monitor by identity: Check for your OIDC subject claim
OIDC tokens are sensitive:
- Never log
ACTIONS_ID_TOKEN_REQUEST_TOKEN - Tokens are single-use but should be zeroized
- Use GitHub's OIDC provider security best practices
Outbound HTTPS Required:
https://fulcio.sigstore.dev- Certificate issuancehttps://rekor.sigstore.dev- Transparency loghttps://token.actions.githubusercontent.com- OIDC (GitHub)
Firewall Rules:
- Allow outbound HTTPS (port 443)
- Certificate pinning available (future - Issue #12)
Note: Currently no rate limiting (Issue #6)
- Fulcio/Rekor have their own rate limits
- Excessive signing may be throttled by Sigstore
Certificate pinning adds defense-in-depth protection for TLS connections to Sigstore endpoints (Fulcio and Rekor). Even if a trusted Certificate Authority is compromised, pinning prevents man-in-the-middle attacks by validating that server certificates match known fingerprints.
Threats Mitigated:
- ✅ CA compromise (rogue certificates from trusted CAs)
- ✅ DNS/BGP hijacking with valid certificates
- ✅ State-level adversaries with CA access
- ✅ Certificate mis-issuance attacks
Current State: ✅ Fully implemented and enforced
The wsc library includes complete certificate pinning with enforcement:
- SHA256 fingerprint validation for Fulcio and Rekor endpoints
- Custom
PinnedRustlsConnectorusing ureq'sConnectortrait - Custom
ServerCertVerifierimplementation using rustls - Support for multiple pinned certificates (rotation)
- Configurable pins via environment variables
Current Behavior:
- Certificate pinning is enforced for all Fulcio/Rekor connections
- Connections fail if certificates don't match expected pins
- Falls back to standard WebPKI validation only if pinning initialization fails
# Fulcio production endpoint
export WSC_FULCIO_PINS="sha256_fingerprint1,sha256_fingerprint2"
# Rekor production endpoint
export WSC_REKOR_PINS="sha256_fingerprint1,sha256_fingerprint2"
# Custom Sigstore instance
export WSC_FULCIO_PINS="custom_fingerprint"# Get current Fulcio certificate fingerprint
echo | openssl s_client -connect fulcio.sigstore.dev:443 -servername fulcio.sigstore.dev 2>/dev/null | \
openssl x509 -outform DER | sha256sum
# Get current Rekor certificate fingerprint
echo | openssl s_client -connect rekor.sigstore.dev:443 -servername rekor.sigstore.dev 2>/dev/null | \
openssl x509 -outform DER | sha256sumTo require that pinning be enforced (fail if cannot):
export WSC_REQUIRE_CERT_PINNING=1This will cause connection attempts to fail with an error if certificate pinning cannot be enforced due to HTTP client limitations.
Certificate pins should be rotated when Sigstore updates their TLS certificates:
- Pre-rotation: Add new certificate fingerprints alongside existing ones
- Grace period: Accept both old and new pins for 30-90 days
- Post-rotation: Remove deprecated pins after grace period
- Monitoring: Alert on pin mismatches to detect rotation events
When Enforced (future):
- Prevents MITM even with compromised CA
- Validates leaf certificate fingerprint
- Optionally validates intermediate certificates
- Combines with standard WebPKI validation (defense-in-depth)
Current State:
- Standard WebPKI validation only
- Pinning infrastructure ready for integration
- Manual validation possible via custom code
src/lib/src/signature/keyless/cert_pinning.rs- Complete pinning implementationsrc/lib/src/signature/keyless/fulcio.rs- Fulcio client integrationsrc/lib/src/signature/keyless/rekor.rs- Rekor client integration
(See docs/security-analysis.md for comprehensive coverage)
Summary:
- Uses Ed25519 signatures with SHA-256
- Supports multi-signature workflows
- Hardware-backed keys (ATECC608)
- Offline verification capability
- Certificate expiry provides revocation
wsc's keyless signing is built on Sigstore infrastructure (Fulcio + Rekor) but targets WASM modules specifically.
| Feature | wsc | Cosign |
|---|---|---|
| WASM Support | ✅ Native | |
| Keyless | ✅ Yes | ✅ Yes |
| Fulcio | ✅ Yes | ✅ Yes |
| Rekor | ✅ Yes | ✅ Yes |
| Multi-signature | ✅ Composition | ✅ Attestations |
| Hardware keys | ✅ ATECC608 | ❌ Software only (keyless) |
| Offline | ✅ Cert mode | ✅ Key mode |
| Feature | wsc Keyless | Apple Code Sign | Windows Authenticode |
|---|---|---|---|
| Algorithm | ECDSA P-256 | RSA/ECDSA | RSA |
| Timestamp | Rekor | TSA | TSA |
| Hardware | Optional | Optional (T2) | Optional (HSM) |
| Transparency | ✅ Rekor | ❌ No | ❌ No |
| Revocation | ❌ Expiry | ✅ CRL/OCSP | ✅ CRL/OCSP |
| Key Mgmt | ✅ None | ❌ Complex | ❌ Complex |
| Cost | Free | $99+/year | $100+/year |
This section documents known security limitations that users should be aware of.
Limitation: WSC does not implement OCSP (Online Certificate Status Protocol) or CRL (Certificate Revocation Lists) checking.
Impact: Cannot revoke a compromised signing certificate before its natural expiration.
Mitigation: Fulcio certificates have a 10-minute validity window, inherently limiting the exposure window. For long-lived certificates (non-Fulcio deployments), use short validity periods (1-7 days).
Roadmap: OCSP stapling planned for Q2 2026 for non-Fulcio deployments.
Limitation: Hardware Security Module support is scaffolded but not complete.
Impact: Cannot achieve Security Level 3+ under IEC 62443 without hardware-backed key storage.
Mitigation: Use file-based keys with strict permissions (0600), process isolation, and encrypted filesystems. The platform/ module provides the interface for future HSM integration.
Roadmap: HSM integration for ATECC608A, TPM 2.0, and NXP SE050 planned for Q2 2026.
Limitation: Key material in memory could be swapped to disk by the operating system.
Impact: Forensic recovery of key material from swap space theoretically possible.
Mitigation:
- Use
mlock()on production systems to prevent swapping - Use encrypted swap partitions
- Ephemeral keys reduce exposure (sub-second lifetime)
- Zeroization on drop minimizes window
Note: The zeroize crate ensures keys are cleared from memory, but cannot prevent OS-level swap writes before Drop is called.
Limitation: Keyless signature verification requires Rekor access for inclusion proof verification.
Impact: Air-gapped or offline environments cannot verify keyless signatures without pre-fetching Rekor entries.
Mitigation:
- Use certificate-based signing for offline environments
- Pre-fetch and distribute Rekor entries with modules
- The
--offlineflag supports verification with pre-distributed trust bundles
Limitation: OIDC tokens exist in memory for the duration of the signing operation.
Impact: Memory dump during signing could expose token (until expiration).
Mitigation:
- Tokens are zeroized immediately after use
- Token lifetime is typically <15 minutes
- GitHub Actions OIDC tokens are bound to specific workflow runs
For automotive (ISO/SAE 21434) and industrial IoT (IEC 62443) deployments, see:
- docs/THREAT_MODEL.md - STRIDE threat analysis
- docs/TARA_COMPLIANCE.md - Standards compliance mapping
- docs/KEY_LIFECYCLE.md - Key management procedures
- docs/INCIDENT_RESPONSE.md - Security incident runbook
Do not open public issues for security vulnerabilities.
Contact: [security contact from repository settings]
Include:
- Description of vulnerability
- Steps to reproduce
- Potential impact
- Suggested mitigation (if any)
- ✅ Fixed timing attack vulnerability - Replaced
==with constant-time comparison (ct_codecs::verify) for all cryptographic material comparisons insimple.rsandmulti.rs - ✅ Added intermediate buffer zeroization - Message buffers now wrapped with
Zeroizing<Vec<u8>>to prevent secret residue in memory - ✅ Release profile hardening - Added
overflow-checks = trueto detect integer overflow in release builds - ✅ Certificate pinning enforcement - Created custom
PinnedRustlsConnectorusing ureq'sConnectortrait to enforce certificate pinning for Fulcio and Rekor connections - ✅ TARA compliance documentation - Added comprehensive documentation for ISO/SAE 21434 and IEC 62443 compliance:
docs/THREAT_MODEL.md- STRIDE analysisdocs/TARA_COMPLIANCE.md- Standards mappingdocs/KEY_LIFECYCLE.md- Key management proceduresdocs/INCIDENT_RESPONSE.md- Security incident runbook
- ✅ Added ephemeral key zeroization (Issue #14)
- ✅ Added OIDC token zeroization (Issue #11)
- ✅ Implemented Rekor inclusion proof verification (Issue #15)
- ✅ Sanitized error messages for information disclosure (Issue #9)
- ✅ Added comprehensive zeroization tests (17 new tests)
- ✅ Implemented certificate pinning infrastructure (Issue #12)
- Complete SHA256 fingerprint validation
- Support for custom pins via environment variables
- ✅ Implemented Rekor checkpoint-based verification (Issue #1)
- ✅ Full certificate chain verification (Issue #16)
- Sigstore Documentation
- Fulcio CA
- Rekor Transparency Log
- ECDSA P-256
- RFC 6962: Certificate Transparency
- RFC 6979: Deterministic ECDSA
Last Updated: 2026-01-04 Addresses: Issues #2 (Security Model Documentation), #4 (Ephemeral Key Lifecycle), #12 (Certificate Pinning)