Skip to content

Commit d78da2f

Browse files
committed
fix: Improve remediation database accuracy and coverage
- Add 30+ common algorithms to remediation database: - Authenticated encryption: ChaCha20-Poly1305, AES-GCM, XSalsa20-Poly1305 - MACs: HMAC, HMAC-SHA256, HMAC-SHA512, Poly1305 - Post-quantum: ML-KEM, ML-DSA (mark as quantum-safe) - NIST curves: P-256, P-384, P-521, secp256k1 - RSA variants: RSA-OAEP, RSA-PSS, PS256/384/512 - ECDH variants: ECDH-ES - Hash functions: BLAKE2b, BLAKE2s, BLAKE3 - Chinese algorithms: SM2, SM3, SM4 - Fix @noble/ed25519 database entry (removed false positives) - Fix Maven property placeholder resolution: - Parse <properties> section and resolve ${...} references - Now shows actual version (1.77) instead of ${bouncycastle.version}
1 parent 6b5a6cd commit d78da2f

File tree

3 files changed

+404
-74
lines changed

3 files changed

+404
-74
lines changed

data/crypto-database.json

Lines changed: 8 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -19387,35 +19387,11 @@
1938719387
"ecosystem": "npm",
1938819388
"analysis": {
1938919389
"date": "2025-12-26T19:10:13.132255639Z",
19390-
"method": "inferred",
19390+
"method": "verified",
1939119391
"tool": "cryptodeps",
1939219392
"toolVersion": ""
1939319393
},
1939419394
"crypto": [
19395-
{
19396-
"algorithm": "ECDSA",
19397-
"type": "signature",
19398-
"quantumRisk": "VULNERABLE",
19399-
"severity": "HIGH",
19400-
"location": {
19401-
"file": "",
19402-
"line": 0
19403-
},
19404-
"remediation": "Migrate to ML-DSA (FIPS 204) or SLH-DSA (FIPS 205) for signatures",
19405-
"confidence": "high"
19406-
},
19407-
{
19408-
"algorithm": "ECDH",
19409-
"type": "key-exchange",
19410-
"quantumRisk": "VULNERABLE",
19411-
"severity": "HIGH",
19412-
"location": {
19413-
"file": "",
19414-
"line": 0
19415-
},
19416-
"remediation": "Migrate to ML-KEM (FIPS 203) for key exchange",
19417-
"confidence": "medium"
19418-
},
1941919395
{
1942019396
"algorithm": "Ed25519",
1942119397
"type": "signature",
@@ -19425,8 +19401,8 @@
1942519401
"file": "",
1942619402
"line": 0
1942719403
},
19428-
"remediation": "Migrate to ML-DSA (FIPS 204) or SLH-DSA (FIPS 205) for signatures",
19429-
"confidence": "high"
19404+
"remediation": "Migrate to ML-DSA (FIPS 204) for signatures",
19405+
"confidence": "verified"
1943019406
},
1943119407
{
1943219408
"algorithm": "X25519",
@@ -19438,49 +19414,14 @@
1943819414
"line": 0
1943919415
},
1944019416
"remediation": "Migrate to ML-KEM (FIPS 203) for key exchange",
19441-
"confidence": "high"
19442-
},
19443-
{
19444-
"algorithm": "RSA",
19445-
"type": "encryption",
19446-
"quantumRisk": "VULNERABLE",
19447-
"severity": "HIGH",
19448-
"location": {
19449-
"file": "",
19450-
"line": 0
19451-
},
19452-
"remediation": "Migrate to ML-KEM (FIPS 203) for encryption or ML-DSA (FIPS 204) for signatures",
19453-
"confidence": "high"
19454-
},
19455-
{
19456-
"algorithm": "AES",
19457-
"type": "encryption",
19458-
"quantumRisk": "PARTIAL",
19459-
"severity": "MEDIUM",
19460-
"location": {
19461-
"file": "",
19462-
"line": 0
19463-
},
19464-
"remediation": "Use AES-256 for 128-bit post-quantum security",
19465-
"confidence": "high"
19466-
},
19467-
{
19468-
"algorithm": "ChaCha20-Poly1305",
19469-
"type": "encryption",
19470-
"quantumRisk": "UNKNOWN",
19471-
"severity": "INFO",
19472-
"location": {
19473-
"file": "",
19474-
"line": 0
19475-
},
19476-
"confidence": "high"
19417+
"confidence": "verified"
1947719418
}
1947819419
],
1947919420
"quantumSummary": {
19480-
"vulnerable": 5,
19481-
"partial": 1,
19421+
"vulnerable": 2,
19422+
"partial": 0,
1948219423
"safe": 0,
19483-
"unknown": 1
19424+
"unknown": 0
1948419425
}
1948519426
},
1948619427
{
@@ -69525,4 +69466,4 @@
6952569466
}
6952669467
}
6952769468
]
69528-
}
69469+
}

internal/manifest/maven.go

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package manifest
66
import (
77
"encoding/xml"
88
"os"
9+
"regexp"
10+
"strings"
911

1012
"github.com/csnp/qramm-cryptodeps/pkg/types"
1113
)
@@ -25,13 +27,44 @@ func (p *MavenParser) Filenames() []string {
2527

2628
// pomXML represents the structure of a pom.xml file.
2729
type pomXML struct {
28-
XMLName xml.Name `xml:"project"`
29-
GroupID string `xml:"groupId"`
30-
ArtifactID string `xml:"artifactId"`
31-
Version string `xml:"version"`
30+
XMLName xml.Name `xml:"project"`
31+
GroupID string `xml:"groupId"`
32+
ArtifactID string `xml:"artifactId"`
33+
Version string `xml:"version"`
34+
Properties pomProperties `xml:"properties"`
3235
Dependencies pomDependencies `xml:"dependencies"`
3336
}
3437

38+
// pomProperties captures all property elements as a map
39+
type pomProperties struct {
40+
Entries map[string]string
41+
}
42+
43+
// UnmarshalXML implements xml.Unmarshaler for pomProperties
44+
func (p *pomProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
45+
p.Entries = make(map[string]string)
46+
47+
for {
48+
token, err := d.Token()
49+
if err != nil {
50+
return err
51+
}
52+
53+
switch t := token.(type) {
54+
case xml.StartElement:
55+
var value string
56+
if err := d.DecodeElement(&value, &t); err != nil {
57+
return err
58+
}
59+
p.Entries[t.Name.Local] = value
60+
case xml.EndElement:
61+
if t.Name == start.Name {
62+
return nil
63+
}
64+
}
65+
}
66+
}
67+
3568
type pomDependencies struct {
3669
Dependency []pomDependency `xml:"dependency"`
3770
}
@@ -44,6 +77,35 @@ type pomDependency struct {
4477
Optional string `xml:"optional"`
4578
}
4679

80+
// propertyPattern matches Maven property references like ${property.name}
81+
var propertyPattern = regexp.MustCompile(`\$\{([^}]+)\}`)
82+
83+
// resolveProperties replaces ${property} placeholders with their values
84+
func resolveProperties(value string, props map[string]string) string {
85+
if props == nil {
86+
return value
87+
}
88+
89+
return propertyPattern.ReplaceAllStringFunc(value, func(match string) string {
90+
// Extract property name from ${...}
91+
propName := strings.TrimPrefix(strings.TrimSuffix(match, "}"), "${")
92+
93+
// Handle nested dots (e.g., project.version -> check both forms)
94+
if resolved, ok := props[propName]; ok {
95+
return resolved
96+
}
97+
98+
// Try with dots converted to hyphens (some Maven conventions)
99+
hyphenName := strings.ReplaceAll(propName, ".", "-")
100+
if resolved, ok := props[hyphenName]; ok {
101+
return resolved
102+
}
103+
104+
// Return original if not found
105+
return match
106+
})
107+
}
108+
47109
// Parse parses a pom.xml file and returns the list of dependencies.
48110
func (p *MavenParser) Parse(path string) ([]types.Dependency, error) {
49111
data, err := os.ReadFile(path)
@@ -56,6 +118,16 @@ func (p *MavenParser) Parse(path string) ([]types.Dependency, error) {
56118
return nil, err
57119
}
58120

121+
// Build property map including project properties
122+
props := pom.Properties.Entries
123+
if props == nil {
124+
props = make(map[string]string)
125+
}
126+
// Add project.version as a property
127+
if pom.Version != "" {
128+
props["project.version"] = pom.Version
129+
}
130+
59131
var deps []types.Dependency
60132

61133
for _, dep := range pom.Dependencies.Dependency {
@@ -65,9 +137,12 @@ func (p *MavenParser) Parse(path string) ([]types.Dependency, error) {
65137
// Construct Maven coordinate name
66138
name := dep.GroupID + ":" + dep.ArtifactID
67139

140+
// Resolve property placeholders in version
141+
version := resolveProperties(dep.Version, props)
142+
68143
deps = append(deps, types.Dependency{
69144
Name: name,
70-
Version: dep.Version,
145+
Version: version,
71146
Ecosystem: types.EcosystemMaven,
72147
Direct: !isTest, // Mark test deps as not direct for now
73148
})

0 commit comments

Comments
 (0)