diff --git a/src/LdifDotNet/RfcGrammar.cs b/src/LdifDotNet/RfcGrammar.cs
index 3a615f8..204f435 100644
--- a/src/LdifDotNet/RfcGrammar.cs
+++ b/src/LdifDotNet/RfcGrammar.cs
@@ -15,7 +15,15 @@ internal static class RfcGrammar
///
internal static readonly UTF8Encoding StrictUtf8 = new(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
- /// RFC 4512 numericoid / RFC 2849 ldap-oid: 1*DIGIT *("." 1*DIGIT).
+ ///
+ /// Numeric OID, deliberately the looser RFC 2849 ldap-oid grammar
+ /// (1*DIGIT *("." 1*DIGIT)) rather than RFC 4512's numericoid: leading-zero
+ /// arcs and single-arc OIDs are accepted. Correct per spec on every LDIF
+ /// boundary, and matched to slapd on the schema boundary — slaptest 2.6
+ /// accepts 01.2.3.4.5, 1.02.3, and bare 1 in attributetype directives, so
+ /// tightening this would reject files slapd loads. Pinned by tests; do not
+ /// "fix" toward RFC 4512 without re-probing slapd.
+ ///
internal static bool IsNumericOid(string text)
{
bool expectDigit = true;
diff --git a/tests/LdifDotNet.Tests/AttributeDescriptionTests.cs b/tests/LdifDotNet.Tests/AttributeDescriptionTests.cs
index b4c8309..748dca6 100644
--- a/tests/LdifDotNet.Tests/AttributeDescriptionTests.cs
+++ b/tests/LdifDotNet.Tests/AttributeDescriptionTests.cs
@@ -26,6 +26,7 @@ public void HasOption_matches_whole_options_case_insensitively(string descriptio
[Theory]
[InlineData("cn", true)]
[InlineData("2.5.4.3", true)]
+ [InlineData("01.2.3", true)] // RFC 2849 ldap-oid allows leading zeros — deliberate, see RfcGrammar.IsNumericOid
[InlineData("userCertificate;binary", true)]
[InlineData("cn;lang-en;binary", true)]
[InlineData("", false)]
diff --git a/tests/LdifDotNet.Tests/SchemaParserTests.cs b/tests/LdifDotNet.Tests/SchemaParserTests.cs
index 6cde7cc..4e0e63b 100644
--- a/tests/LdifDotNet.Tests/SchemaParserTests.cs
+++ b/tests/LdifDotNet.Tests/SchemaParserTests.cs
@@ -12,6 +12,23 @@ public static TheoryData SchemaFiles()
return data;
}
+ [Theory]
+ [InlineData("01.2.3.4.5")] // leading-zero arc — illegal per RFC 4512 numericoid
+ [InlineData("1.02.3")] // interior leading zero
+ [InlineData("1")] // single arc — RFC 4512 requires at least two
+ public void Oid_leniency_matches_slapd_not_rfc4512(string oid)
+ {
+ // Deliberate: IsNumericOid implements RFC 2849's looser ldap-oid, and
+ // slapd is exactly as loose — slaptest (OpenLDAP 2.6.10, 2026-08-03)
+ // accepted attributetype directives with every OID shape below.
+ // Tightening to RFC 4512's numericoid would reject schema files slapd
+ // loads, breaking the tolerant-reader / slapd-compatibility invariant.
+ var schema = LdapSchema.Parse(
+ $"attributetype ( {oid} NAME 'probeAttr' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )\n");
+
+ Assert.Equal(oid, schema.AttributeTypes[0].Oid);
+ }
+
[Fact]
public void Ldapsyntax_directive_parses_in_file_mode()
{