Skip to content

Corregir crash al parsear Subject DN con comas en la razón social#7

Open
jonas1ara wants to merge 1 commit intoFiscalAPI:mainfrom
jonas1ara:main
Open

Corregir crash al parsear Subject DN con comas en la razón social#7
jonas1ara wants to merge 1 commit intoFiscalAPI:mainfrom
jonas1ara:main

Conversation

@jonas1ara
Copy link
Copy Markdown

@jonas1ara jonas1ara commented Apr 23, 2026

El SAT emite certificados FIEL donde la razón social (O=) puede contener
comas (ej: "SEMILLAS, HORTALIZAS Y FLORES"). El código anterior hacía
Split(',') sobre el Subject completo y luego accedía a Split('=')[1]
directamente, lanzando IndexOutOfRangeException cuando un fragmento no
contenía '='.

Solución: usar Split('=', 2) con máximo 2 partes y filtrar fragmentos
sin '=' antes de mapear a KeyValuePair. Aplicado en SubjectKeyValuePairs
e IssuerKeyValuePairs.

Esto resolvio mi problema al tratar con una razon social que lleva una coma en el nombre

Summary by CodeRabbit

Bug Fixes

  • Enhanced certificate data parsing to handle edge cases with malformed components, preventing failures and improving overall stability when processing certificates.

 El SAT emite certificados FIEL donde la razón social (O=) puede contener
 comas (ej: "SEMILLAS, HORTALIZAS Y FLORES"). El código anterior hacía
 Split(',') sobre el Subject completo y luego accedía a Split('=')[1]
 directamente, lanzando IndexOutOfRangeException cuando un fragmento no
 contenía '='.

 Solución: usar Split('=', 2) con máximo 2 partes y filtrar fragmentos
 sin '=' antes de mapear a KeyValuePair. Aplicado en SubjectKeyValuePairs
 e IssuerKeyValuePairs.

Esto resolvio mi problema al tratar con una razon social que lleva una coma en el nombre
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

Certificate issuer and subject parsing now uses Split('=', 2) and validates that exactly two parts are produced, replacing direct indexing that would crash on malformed certificate components lacking or containing extra equals signs.

Changes

Cohort / File(s) Summary
Certificate Parsing Robustness
Core/Certificate.cs
Enhanced issuer and subject field parsing with proper element validation using split-with-limit and explicit two-part checks, preventing failures on malformed certificate data.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 With whiskers twitching, I've found the fix so neat,
Where parsing certificates no longer meets defeat!
Now each equals sign is handled just right,
And malformed components won't cause a fright. 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main bug being fixed: a crash when parsing Subject DN with commas in company names (razón social). It directly addresses the core issue in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
Core/Certificate.cs (1)

132-138: Mismo defecto y duplicación de lógica con SubjectKeyValuePairs.

IssuerKeyValuePairs aplica exactamente la misma cadena de operaciones que SubjectKeyValuePairs (Lines 156–160) y, por tanto, hereda el mismo problema descrito arriba: si el Issuer (la AC del SAT) trae un atributo con coma escapada/entrecomillada, también se descarta silenciosamente. Al refactorizar para usar X500DistinguishedName (ver comentario en SubjectKeyValuePairs), extrae un único helper privado (p. ej. ParseDistinguishedName(X500DistinguishedName)) y reutilízalo en ambos getters: usa _x509Certificate2.IssuerName y _x509Certificate2.SubjectName para no re-parsear strings ya descodificados por el runtime.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Core/Certificate.cs` around lines 132 - 138, Refactor IssuerKeyValuePairs and
SubjectKeyValuePairs to avoid duplicating brittle string-splitting logic: create
a private helper ParseDistinguishedName(X500DistinguishedName dn) that extracts
key/value pairs from the runtime-parsed dn (handling escaped commas/quotes
correctly), and have both getters call this helper using
_x509Certificate2.IssuerName and _x509Certificate2.SubjectName respectively
instead of re-parsing the raw Issuer/Subject strings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Core/Certificate.cs`:
- Around line 156-160: The current SubjectKeyValuePairs/IssuerKeyValuePairs
logic naively splits Subject/Issuer strings on commas which corrupts values
containing escaped commas; replace both identical blocks with a shared helper
ParseDistinguishedName that accepts an X500DistinguishedName, calls
dn.Decode(X500DistinguishedNameFlags.UseNewLines), splits on newline characters
(not commas), then splits each line on '=' (limit 2), trims and returns
List<KeyValuePair<string,string>>; update SubjectKeyValuePairs and
IssuerKeyValuePairs to call
ParseDistinguishedName(_x509Certificate2.SubjectName) /
ParseDistinguishedName(_x509Certificate2.IssuerName) and add a unit test with
CN=FOO, O="ACME, S.A. DE C.V.", C=MX to assert Organization preserves the
embedded comma.

---

Nitpick comments:
In `@Core/Certificate.cs`:
- Around line 132-138: Refactor IssuerKeyValuePairs and SubjectKeyValuePairs to
avoid duplicating brittle string-splitting logic: create a private helper
ParseDistinguishedName(X500DistinguishedName dn) that extracts key/value pairs
from the runtime-parsed dn (handling escaped commas/quotes correctly), and have
both getters call this helper using _x509Certificate2.IssuerName and
_x509Certificate2.SubjectName respectively instead of re-parsing the raw
Issuer/Subject strings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7eb55c75-2d3c-4e5a-a2d0-11c1bbe5d5fd

📥 Commits

Reviewing files that changed from the base of the PR and between 68ee7ea and 379e4d0.

📒 Files selected for processing (1)
  • Core/Certificate.cs

Comment thread Core/Certificate.cs
Comment on lines 156 to +160
get => _x509Certificate2.Subject.Split(',')
.Select(x => new KeyValuePair<string, string>(x.Split('=')[0].Trim(), x.Split('=')[1].Trim())).ToList();
.Select(x => x.Split('=', 2))
.Where(parts => parts.Length == 2)
.Select(parts => new KeyValuePair<string, string>(parts[0].Trim(), parts[1].Trim()))
.ToList();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

X500DistinguishedName Decode UseNewLines .NET 8 escape comma

💡 Result:

In .NET 8, X500DistinguishedName supports formatting/decoding options via X500DistinguishedNameFlags. To control comma/newline escaping: 1) UseNewLines (for decoding/formatting) - X500DistinguishedNameFlags.UseNewLines (value 256) is the flag that indicates the distinguished name uses the new line character. This is part of the X500DistinguishedNameFlags enum used with X500DistinguishedName’s decode/encode operations. 2) UseCommas vs UseNewLines are mutually exclusive - The flags doc states you should use only one of UseCommas, UseNewLines, and UseSemicolons. 3) “escape comma” in the input string (parsing) - The X500DistinguishedName(string ...) constructor parses a textual DN using the platform parsing routine (it’s backed by an X500 name parsing implementation). If you pass an input like ...OU=Docs, Adatum..., the parser may fail with “invalid X500 name ... delimiter/value” depending on the exact escaping/quoting the parser expects. - There isn’t a dedicated “escape comma in the input string” flag. The flags primarily affect how .NET formats/decodes the DN, not whether it accepts arbitrary escaped-comma syntax in the constructor input. Practical guidance - If your goal is to round-trip and avoid comma-delimiter ambiguities, prefer building the DN with X500DistinguishedNameBuilder (stronger than parsing a raw escaped string). - If you must parse the raw input, you may need to rewrite/quote the escaped comma according to what the parser accepts (e.g., converting the escaped comma form into a quoted form around the attribute value). Relevant API surfaces - X500DistinguishedName.Decode(X500DistinguishedNameFlags) decodes using the specified characteristics. - X500DistinguishedNameFlags includes UseNewLines and UseCommas and documents their intended usage constraints.

Citations:


🌐 Web query:

.NET X509Certificate2 Subject RFC 2253 escaped comma format

💡 Result:

In .NET, X509Certificate2.SubjectName gives you an X500DistinguishedName object (not a raw RFC 2253 string). The X500DistinguishedName API uses a “comma-delimited distinguished name” string format internally, and escaping rules for special characters follow the LDAP/RFC distinguished-name string escaping mechanism. For the specific case of an escaped comma in RFC 2253 (i.e., a comma that is part of the attribute value, not an RDN delimiter): - RFC 2253 says the comma character “,” must be escaped in attribute values by prefixing it with a backslash. - So the correct representation of a literal comma inside an attribute value is: , (backslash + comma). RFC 2253 escaping rule (comma in value): - The character to escape is one of: ",", "^", "", ... (including comma). If it is in that list, it is prefixed by a backslash. Otherwise it may be hex-escaped. Practical .NET guidance: 1) Prefer to avoid manual parsing/escaping of Subject strings. Use X509Certificate2.GetNameInfo(...) when you just need specific components, because it “should always be used instead of parsing the certificate”. 2) If you must round-trip/format the DN string yourself, use X500DistinguishedName and its Decode/Name/Format facilities rather than string operations. The X500DistinguishedNameFlags enum controls formatting (use commas/semicolons, etc.), but RFC 2253 escaping is still required for commas that belong to attribute values. Example (conceptual): - If the certificate subject has an attribute like CN=“R. Smith, O=Big Company” (comma inside CN value), RFC 2253 requires the comma be escaped in the string form as CN=R. Smith, O=Big Company (the comma after “Smith” is preceded by a backslash so it’s not treated as an RDN separator). Answer to your query wording (“.NET X509Certificate2 Subject RFC 2253 escaped comma format”): - The correct RFC 2253 escaped-comma syntax is: \, i.e. a literal “comma inside an attribute value” is represented as a backslash followed by a comma.

Citations:


🌐 Web query:

X500DistinguishedName.Decode UseNewLines vs UseCommas practical example

💡 Result:

Practical difference - X500DistinguishedName.Decode(flag) uses the flag to choose the separator used when rendering RDNs (relative distinguished names) into a string. - X500DistinguishedNameFlags.UseCommas renders the DN using comma+space separators. - X500DistinguishedNameFlags.UseNewLines renders the DN using the platform new-line sequence instead of comma separators. These flags are mutually exclusive with each other (Microsoft notes only one of UseCommas/UseNewLines/UseSemicolons should be specified). What you should do in code 1) Create an X500DistinguishedName from the certificate/ASN.1 value (so the DN parsing is already done). 2) Call Decode(...) with either UseCommas or UseNewLines depending on how you want to display it. Example (C#) using System; using System.Security.Cryptography.X509Certificates; class Demo { static void Main { // Example: use the subject DN from a certificate you already have. // Replace with your own X509Certificate2. X509Certificate2 cert = GetSomeCertificate; X500DistinguishedName dn = new X500DistinguishedName(cert.SubjectName.Name); string commas = dn.Decode(X500DistinguishedNameFlags.UseCommas); string newLines = dn.Decode(X500DistinguishedNameFlags.UseNewLines); Console.WriteLine("-- commas --"); Console.WriteLine(commas); Console.WriteLine("-- new lines --"); Console.WriteLine(newLines); } static X509Certificate2 GetSomeCertificate => throw new NotImplementedException; } Notes about “UseNewLines vs UseCommas” - UseCommas affects only the rendered layout (separator) of the decoded string. - UseNewLines affects only the rendered layout (separator) of the decoded string. Common gotcha (input parsing vs output formatting) - The DN string constructor X500DistinguishedName(string, flags) is for parsing/encoding a DN into ASN.1. Separators/escaping in the input have to be valid for what the underlying encoder expects. - Separate from Decode formatting: if your input DN contains commas inside attribute values, you may need proper quoting/escaping; otherwise you can get “invalid X500 name … delimiter” exceptions. If you tell me your exact DN example and your target .NET version (e.g., .NET 6/7/8), I can show the safest way to display it (Decode) and the safest way to ingest it (constructor vs X500DistinguishedNameBuilder).

Citations:


🏁 Script executed:

# Check if the Certificate.cs file exists and review the current implementation
fd -e cs -p 'Certificate.cs' | head -5

Repository: FiscalAPI/fiscalapi-credentials-net

Length of output: 119


🏁 Script executed:

# Read the Certificate.cs file to verify the implementation
cat -n Core/Certificate.cs | head -200

Repository: FiscalAPI/fiscalapi-credentials-net

Length of output: 7611


🏁 Script executed:

# Search for the exact context around lines 134-138 and 156-160
sed -n '80,170p' Core/Certificate.cs | cat -n

Repository: FiscalAPI/fiscalapi-credentials-net

Length of output: 3698


🏁 Script executed:

# Search for test files related to Certificate.cs to understand the PR context
fd -e cs -p 'Test.*Certificate|Certificate.*Test' | head -10

Repository: FiscalAPI/fiscalapi-credentials-net

Length of output: 61


🏁 Script executed:

# Check git history for recent changes to Certificate.cs
git log --oneline -10 -- Core/Certificate.cs 2>/dev/null || echo "Git not available"

Repository: FiscalAPI/fiscalapi-credentials-net

Length of output: 152


🏁 Script executed:

# Search for any mentions of "comma" or "SEMILLAS" in the repo (PR context)
rg -i "comma|semillas" --type cs | head -20

Repository: FiscalAPI/fiscalapi-credentials-net

Length of output: 61


Silent data truncation when Organization name contains commas: requires proper RFC 2253 parsing

The crash is fixed (no more IndexOutOfRangeException), but Split(',') on RFC 2253–formatted Subject DNs causes silent truncation when attribute values contain commas. In RFC 2253, a comma within a value is escaped as \, (e.g., O=SEMILLAS\, HORTALIZAS Y FLORES, C=MX). Naively splitting by , fragments this into O=SEMILLAS\, HORTALIZAS Y FLORES, C=MX—the middle fragment is silently dropped by the Where(parts => parts.Length == 2) filter, leaving Organization with a truncated and corrupted value (SEMILLAS\ instead of the full name). This is worse than the original crash because it silently corrupts the Organization field, which is critical for Mexican SAT invoicing.

Recommended fix: Use X500DistinguishedName.Decode(X500DistinguishedNameFlags.UseNewLines) to render each RDN on a separate line, preserving escaped characters within values. Extract a shared helper method to eliminate duplication (lines 134–138 and 156–160 are identical):

public List<KeyValuePair<string, string>> IssuerKeyValuePairs
{
    get => ParseDistinguishedName(_x509Certificate2.IssuerName);
}

public List<KeyValuePair<string, string>> SubjectKeyValuePairs
{
    get => ParseDistinguishedName(_x509Certificate2.SubjectName);
}

private static List<KeyValuePair<string, string>> ParseDistinguishedName(X500DistinguishedName dn)
{
    var formatted = dn.Decode(X500DistinguishedNameFlags.UseNewLines);
    return formatted
        .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
        .Select(line => line.Split('=', 2))
        .Where(parts => parts.Length == 2)
        .Select(parts => new KeyValuePair<string, string>(parts[0].Trim(), parts[1].Trim()))
        .ToList();
}

Add a test with CN=FOO, O="ACME, S.A. DE C.V.", C=MX to verify Organization returns the full name with the embedded comma intact.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Core/Certificate.cs` around lines 156 - 160, The current
SubjectKeyValuePairs/IssuerKeyValuePairs logic naively splits Subject/Issuer
strings on commas which corrupts values containing escaped commas; replace both
identical blocks with a shared helper ParseDistinguishedName that accepts an
X500DistinguishedName, calls dn.Decode(X500DistinguishedNameFlags.UseNewLines),
splits on newline characters (not commas), then splits each line on '=' (limit
2), trims and returns List<KeyValuePair<string,string>>; update
SubjectKeyValuePairs and IssuerKeyValuePairs to call
ParseDistinguishedName(_x509Certificate2.SubjectName) /
ParseDistinguishedName(_x509Certificate2.IssuerName) and add a unit test with
CN=FOO, O="ACME, S.A. DE C.V.", C=MX to assert Organization preserves the
embedded comma.

@mendozagit
Copy link
Copy Markdown
Contributor

@jonas1ara muchasgracias por tu contribución, la revisaré ASAP :)

QQ. Hiciste testing con razones sociales sin coma como parte del nombre / LegalName ?

@jonas1ara
Copy link
Copy Markdown
Author

jonas1ara commented Apr 23, 2026

@mendozagit si, tengo 400 razones sociales y 1 sola tenia coma, en este momento ya descargue 14 sin coma y sigue trabajando bien.

Revísala con calma, si ayuda a la librería, un gusto.

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.

2 participants