From 8564f9d963da8d82a77612d4ade12e36962c594c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Kallehauge?= <3846700+kallehauge@users.noreply.github.com> Date: Mon, 12 Oct 2026 14:07:03 +0200 Subject: [PATCH 1/3] fix(dk/cvr): reject numbers that start with 0 No CVR number starts with 0, and python-stdnum's dk/cvr refuses them with InvalidFormat. Without the check, 00000000 passes as a valid CVR because its modulus 11 sum is 0, so a common placeholder value is accepted as a real company number. --- src/dk/cvr.spec.ts | 10 +++++++++- src/dk/cvr.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dk/cvr.spec.ts b/src/dk/cvr.spec.ts index 541bcd62..43638f6b 100644 --- a/src/dk/cvr.spec.ts +++ b/src/dk/cvr.spec.ts @@ -1,5 +1,5 @@ import { validate, format } from './cvr'; -import { InvalidLength, InvalidChecksum } from '../exceptions'; +import { InvalidLength, InvalidChecksum, InvalidFormat } from '../exceptions'; describe('dk/cvr', () => { it('format:DK 13585628', () => { @@ -31,4 +31,12 @@ describe('dk/cvr', () => { expect(result.error).toBeInstanceOf(InvalidChecksum); }); + + // No CVR number starts with 0. These all pass the modulus 11 check, so the + // leading digit is the only thing that rejects them. + test.each(['00000000', 'DK00000000', '01000004'])('validate:%s', value => { + const result = validate(value); + + expect(result.error).toBeInstanceOf(InvalidFormat); + }); }); diff --git a/src/dk/cvr.ts b/src/dk/cvr.ts index b8e69ca2..cfbe064d 100644 --- a/src/dk/cvr.ts +++ b/src/dk/cvr.ts @@ -54,7 +54,7 @@ const impl: Validator = { if (value.length !== 8) { return { isValid: false, error: new exceptions.InvalidLength() }; } - if (!strings.isdigits(value)) { + if (!strings.isdigits(value) || value[0] === '0') { return { isValid: false, error: new exceptions.InvalidFormat() }; } From 8e94d1b41d81299259ea9273e034742e718caec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Kallehauge?= <3846700+kallehauge@users.noreply.github.com> Date: Mon, 12 Oct 2026 14:22:54 +0200 Subject: [PATCH 2/3] test(dk/cvr): a real company's CVR still passes Novo Nordisk A/S (24256790), active in the Danish CVR register, with and without the DK prefix. --- src/dk/cvr.spec.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/dk/cvr.spec.ts b/src/dk/cvr.spec.ts index 43638f6b..036c8477 100644 --- a/src/dk/cvr.spec.ts +++ b/src/dk/cvr.spec.ts @@ -39,4 +39,11 @@ describe('dk/cvr', () => { expect(result.error).toBeInstanceOf(InvalidFormat); }); + + // Novo Nordisk A/S, active in the Danish CVR register: real numbers still pass. + test.each(['24256790', 'DK24256790'])('validate:%s', value => { + const result = validate(value); + + expect(result.isValid && result.compact).toEqual('24256790'); + }); }); From dd809555a158e479ac7377323cf2735cd1a150c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Kallehauge?= <3846700+kallehauge@users.noreply.github.com> Date: Mon, 12 Oct 2026 14:24:06 +0200 Subject: [PATCH 3/3] test(dk/cvr): describe the registered number by its rule, not its owner --- src/dk/cvr.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dk/cvr.spec.ts b/src/dk/cvr.spec.ts index 036c8477..a20e519c 100644 --- a/src/dk/cvr.spec.ts +++ b/src/dk/cvr.spec.ts @@ -40,7 +40,7 @@ describe('dk/cvr', () => { expect(result.error).toBeInstanceOf(InvalidFormat); }); - // Novo Nordisk A/S, active in the Danish CVR register: real numbers still pass. + // A registered CVR number still passes. test.each(['24256790', 'DK24256790'])('validate:%s', value => { const result = validate(value);