oven-sh/bun · error · TypeError

PERMITTED_VIOLATION

PERMITTED_VIOLATION

Error message

PERMITTED_VIOLATION

What it means

CertError::PERMITTED_VIOLATION maps BoringSSL X509_V_ERR_PERMITTED_VIOLATION (verify code 47). A CA in the chain carries a nameConstraints extension with permittedSubtrees, and the name being validated (SAN/subject of a lower cert) falls outside every permitted subtree. Message: "permitted subtree violation".

Source

Thrown at src/http/error.rs:215

    #[error("PROXY_PATH_LENGTH_EXCEEDED")]
    PROXY_PATH_LENGTH_EXCEEDED,
    #[error("KEYUSAGE_NO_DIGITAL_SIGNATURE")]
    KEYUSAGE_NO_DIGITAL_SIGNATURE,
    #[error("PROXY_CERTIFICATES_NOT_ALLOWED")]
    PROXY_CERTIFICATES_NOT_ALLOWED,
    #[error("INVALID_EXTENSION")]
    INVALID_EXTENSION,
    #[error("INVALID_POLICY_EXTENSION")]
    INVALID_POLICY_EXTENSION,
    #[error("NO_EXPLICIT_POLICY")]
    NO_EXPLICIT_POLICY,
    #[error("DIFFERENT_CRL_SCOPE")]
    DIFFERENT_CRL_SCOPE,
    #[error("UNSUPPORTED_EXTENSION_FEATURE")]
    UNSUPPORTED_EXTENSION_FEATURE,
    #[error("UNNESTED_RESOURCE")]
    UNNESTED_RESOURCE,
    #[error("PERMITTED_VIOLATION")]
    PERMITTED_VIOLATION,
    #[error("EXCLUDED_VIOLATION")]
    EXCLUDED_VIOLATION,
    #[error("SUBTREE_MINMAX")]
    SUBTREE_MINMAX,
    #[error("APPLICATION_VERIFICATION")]
    APPLICATION_VERIFICATION,
    #[error("UNSUPPORTED_CONSTRAINT_TYPE")]
    UNSUPPORTED_CONSTRAINT_TYPE,
    #[error("UNSUPPORTED_CONSTRAINT_SYNTAX")]
    UNSUPPORTED_CONSTRAINT_SYNTAX,
    #[error("UNSUPPORTED_NAME_SYNTAX")]
    UNSUPPORTED_NAME_SYNTAX,
    #[error("CRL_PATH_VALIDATION_ERROR")]
    CRL_PATH_VALIDATION_ERROR,
    #[error("SUITE_B_INVALID_VERSION")]
    SUITE_B_INVALID_VERSION,
    #[error("SUITE_B_INVALID_ALGORITHM")]

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Print the constraints: openssl x509 -in ca.pem -noout -text and read the Name Constraints permitted subtrees
  2. Reissue the leaf with only names inside the permitted subtrees (drop the offending SAN)
  3. Or widen the CA's permittedSubtrees to include the name and reissue the CA chain
  4. Verify the chain locally: openssl verify -CAfile constrained-ca.pem leaf.pem

Example fix

# before: CA permits DNS:corp.example.com ; leaf requests a foreign SAN
[leaf_ext]
subjectAltName = DNS:api.corp.example.com, DNS:api.partner.org

# after: SANs within the permitted subtree
[leaf_ext]
subjectAltName = DNS:api.corp.example.com
Defensive patterns

Strategy: validation

Validate before calling

// Before issuing/before trusting: check the SAN sits inside the CA's permitted subtrees
import { X509Certificate } from "node:crypto";
export function sanWithinPermitted(leafPem, caPem, permitted /* e.g. ["corp.example.com"] */) {
  const leaf = new X509Certificate(leafPem);
  const ca = new X509Certificate(caPem);
  if (!/(Name Constraints|permittedSubtrees)/i.test(ca.toString())) return true; // unconstrained
  const dns = (leaf.subjectAltName ?? "").match(/DNS:([^,\s]+)/g)?.map((s) => s.slice(4)) ?? [];
  return dns.every((name) => permitted.some((p) => name === p || name.endsWith("." + p)));
}

Type guard

export function isPermittedViolation(e): e is Error & { code: "PERMITTED_VIOLATION" } {
  return e instanceof Error && (e as any).code === "PERMITTED_VIOLATION";
}

Try / catch

try {
  await fetch(url);
} catch (e) {
  if (e?.code === "PERMITTED_VIOLATION") {
    // SAN is outside the CA's permittedSubtrees - reissue leaf or widen the CA
    reportToCaOwner(new URL(url).hostname);
  } else throw e;
}

Prevention

When it happens

Trigger: CA has nameConstraints permittedSubtrees = DNS:example.com, but a cert under it was issued with SAN www.other.org (or an IP/email/URI outside the permitted list). Any name present in the cert that is constrained must match a permitted subtree.

Common situations: Internal CAs constrained to corporate domains asked to sign certs for a new/acquired domain; CA templates copied between unconstrained and constrained hierarchies; mixing an enterprise intermediate under a constrained public root.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/e4b779f6ed0047c1. Report an issue: GitHub.