Problem
If a project ships a .licscan.yml that only sets manufacturer: / product: blocks (for CRA evidence) and omits deny: / warn:, the policy engine currently treats those empty lists as an explicit "allow everything" — even GPL / AGPL deps come back as ✓ allow and --ci exits 0.
The intuitive expectation is the opposite: if the user did not specify a policy, the built-in default policy should still apply (deny GPL/AGPL/SSPL/BSL/..., warn LGPL/MPL/EPL/CDDL).
Reproduction
.licscan.yml:
manufacturer:
name: Acme GmbH
email: [email protected]
url: https://acme.example
country: DE
product:
name: legacy-app
version: 1.0.0
package-lock.json contains a dependency licensed AGPL-3.0.
Current behaviour: licscan scan . --ci exits 0, AGPL dep marked ✓ allow.
Expected behaviour: exits 1, AGPL dep marked ✗ deny (per default policy).
Workaround
Duplicate the default deny: + warn: lists into every .licscan.yml. See codelake-dev/test-licscan fixtures for the literal copy.
Suggested fix
In internal/scanner/policy/policy.go, after Load() parses an on-disk file, if deny == nil && warn == nil, merge in the defaults from Default(). An explicit empty list (deny: []) should still mean "explicitly allow everything" — only the absence of the key should fall back.
Scope
Small. ~10 LOC + 1 test. No breaking change for users who already set explicit lists.
Problem
If a project ships a
.licscan.ymlthat only setsmanufacturer:/product:blocks (for CRA evidence) and omitsdeny:/warn:, the policy engine currently treats those empty lists as an explicit "allow everything" — even GPL / AGPL deps come back as ✓ allow and--ciexits 0.The intuitive expectation is the opposite: if the user did not specify a policy, the built-in default policy should still apply (deny GPL/AGPL/SSPL/BSL/..., warn LGPL/MPL/EPL/CDDL).
Reproduction
.licscan.yml:package-lock.jsoncontains a dependency licensedAGPL-3.0.Current behaviour:
licscan scan . --ciexits 0, AGPL dep marked ✓ allow.Expected behaviour: exits 1, AGPL dep marked ✗ deny (per default policy).
Workaround
Duplicate the default
deny:+warn:lists into every.licscan.yml. See codelake-dev/test-licscan fixtures for the literal copy.Suggested fix
In
internal/scanner/policy/policy.go, afterLoad()parses an on-disk file, ifdeny == nil && warn == nil, merge in the defaults fromDefault(). An explicit empty list (deny: []) should still mean "explicitly allow everything" — only the absence of the key should fall back.Scope
Small. ~10 LOC + 1 test. No breaking change for users who already set explicit lists.