Skip to content

Commit 3c1e6d6

Browse files
authored
Merge pull request #1053 from broadinstitute/upgrade-java-tools
Replace GATK with FreeBayes for variant calling; upgrade Java tools to eliminate CVEs
2 parents 4761631 + cafa55b commit 3c1e6d6

File tree

18 files changed

+441
-416
lines changed

18 files changed

+441
-416
lines changed

.trivy-ignore-policy.rego

Lines changed: 187 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
# 2. Containers have no inbound network listeners (no ports exposed)
1111
# 3. Containers run with dropped capabilities (no CAP_SYS_ADMIN, etc.)
1212
# 4. Containers do not run in privileged mode
13-
# 5. Pipeline inputs are data files (FASTQ, BAM, VCF, reference genomes),
14-
# not attacker-controlled interactive input
13+
# 5. Pipeline inputs are data files (FASTQ, BAM, VCF, reference genomes)
14+
# which may be untrusted or malformed
1515
#
1616
# If any assumption does not hold for a given image or use case,
1717
# DO NOT apply this policy to that image.
@@ -28,8 +28,15 @@
2828
# accordingly. The CVSS vector string location has changed across
2929
# Trivy versions (see https://github.com/aquasecurity/trivy/issues/1627).
3030
#
31-
# VERSION: 1.0
32-
# LAST REVIEWED: 2026-03-19
31+
# CVSS VERSION SUPPORT:
32+
# This policy supports both CVSS v3.1 and CVSS v4.0 vector strings.
33+
# Trivy is transitioning to v4.0 for newer advisories. Some CVEs may
34+
# have only a v4.0 vector (no v3.1). The helper functions at the bottom
35+
# extract vectors from both versions and the rules are written to match
36+
# either format.
37+
#
38+
# VERSION: 2.0
39+
# LAST REVIEWED: 2026-03-20
3340
# REVIEW CADENCE: Quarterly, or when platform architecture changes
3441
#
3542

@@ -44,20 +51,20 @@ default ignore = false
4451
# These CVEs require hands-on hardware interaction (USB, Firewire,
4552
# JTAG, etc.) which is impossible in any cloud PaaS context.
4653
#
54+
# CVSS v3.1: AV:P
55+
# CVSS v4.0: AV:P (same field name)
56+
#
4757
# Risk of false negative: Essentially zero. There is no scenario
4858
# in which a pipeline container is physically accessible to an attacker.
4959
# Confidence: Very High
5060
###############################################################################
5161

5262
ignore {
53-
cvss_vector := get_v3_vector(input)
54-
contains(cvss_vector, "/AV:P/")
63+
has_v3_field(input, "AV:P")
5564
}
5665

57-
# Also catch AV:P at the end of the vector string (no trailing slash)
5866
ignore {
59-
cvss_vector := get_v3_vector(input)
60-
endswith(cvss_vector, "/AV:P")
67+
has_v4_field(input, "AV:P")
6168
}
6269

6370
###############################################################################
@@ -69,19 +76,20 @@ ignore {
6976
# on orchestrated infrastructure where the attacker cannot place
7077
# themselves on an adjacent segment.
7178
#
79+
# CVSS v3.1: AV:A
80+
# CVSS v4.0: AV:A (same field name)
81+
#
7282
# Risk of false negative: Very low. Cloud networking abstractions
7383
# make adjacent-network attacks impractical against pipeline containers.
7484
# Confidence: Very High
7585
###############################################################################
7686

7787
ignore {
78-
cvss_vector := get_v3_vector(input)
79-
contains(cvss_vector, "/AV:A/")
88+
has_v3_field(input, "AV:A")
8089
}
8190

8291
ignore {
83-
cvss_vector := get_v3_vector(input)
84-
endswith(cvss_vector, "/AV:A")
92+
has_v4_field(input, "AV:A")
8593
}
8694

8795
###############################################################################
@@ -102,14 +110,32 @@ ignore {
102110
# - AV:L + UI:R together means "must have local access AND a human
103111
# must do something" - genuinely inapplicable in batch containers.
104112
#
113+
# CVSS v3.1: AV:L + UI:R
114+
# CVSS v4.0: AV:L + UI:P (Passive) or UI:A (Active)
115+
# v4.0 splits "Required" into Passive (viewing content) and Active
116+
# (clicking/interacting). Both require a human, so both are safe to
117+
# ignore in batch containers.
118+
#
105119
# Risk of false negative: Very low for true batch pipeline containers.
106120
# Confidence: High
107121
###############################################################################
108122

123+
# v3: AV:L + UI:R
124+
ignore {
125+
has_v3_field(input, "AV:L")
126+
has_v3_field(input, "UI:R")
127+
}
128+
129+
# v4: AV:L + UI:P (Passive user interaction)
109130
ignore {
110-
cvss_vector := get_v3_vector(input)
111-
contains(cvss_vector, "/AV:L/")
112-
contains(cvss_vector, "/UI:R")
131+
has_v4_field(input, "AV:L")
132+
has_v4_field(input, "UI:P")
133+
}
134+
135+
# v4: AV:L + UI:A (Active user interaction)
136+
ignore {
137+
has_v4_field(input, "AV:L")
138+
has_v4_field(input, "UI:A")
113139
}
114140

115141
###############################################################################
@@ -126,15 +152,22 @@ ignore {
126152
# accessible vulnerability requiring high privileges may still be
127153
# relevant if the service runs as a privileged user.
128154
#
155+
# CVSS v3.1: AV:L + PR:H
156+
# CVSS v4.0: AV:L + PR:H (same field names)
157+
#
129158
# Risk of false negative: Low, assuming containers run as non-root.
130159
# If your containers run as root, REMOVE THIS RULE.
131160
# Confidence: High (conditional on non-root execution)
132161
###############################################################################
133162

134163
ignore {
135-
cvss_vector := get_v3_vector(input)
136-
contains(cvss_vector, "/AV:L/")
137-
contains(cvss_vector, "/PR:H/")
164+
has_v3_field(input, "AV:L")
165+
has_v3_field(input, "PR:H")
166+
}
167+
168+
ignore {
169+
has_v4_field(input, "AV:L")
170+
has_v4_field(input, "PR:H")
138171
}
139172

140173
###############################################################################
@@ -154,60 +187,173 @@ ignore {
154187
# the container-host boundary (e.g., container escape via kernel exploit)
155188
# IS dangerous and is NOT ignored by this rule.
156189
#
190+
# CVSS v3.1: AV:L + S:U
191+
# CVSS v4.0: AV:L + SC:N + SI:N + SA:N
192+
# v4.0 replaced the binary S:U/S:C with three subsequent-component
193+
# impact fields. SC:N + SI:N + SA:N means no impact on any component
194+
# beyond the vulnerable one — equivalent to v3's S:U.
195+
#
157196
# Risk of false negative: Low. The theoretical concern is that AV:L+S:U
158197
# could include reading mounted secrets, but an attacker with code
159198
# execution can already read those secrets directly.
160199
# Confidence: High
161200
###############################################################################
162201

202+
# v3: AV:L + S:U
163203
ignore {
164-
cvss_vector := get_v3_vector(input)
165-
contains(cvss_vector, "/AV:L/")
166-
contains(cvss_vector, "/S:U/")
204+
has_v3_field(input, "AV:L")
205+
has_v3_field(input, "S:U")
167206
}
168207

169-
# Also catch S:U at the end of the vector string (no trailing slash)
208+
# v4: AV:L + no subsequent-component impact
170209
ignore {
171-
cvss_vector := get_v3_vector(input)
172-
contains(cvss_vector, "/AV:L/")
173-
endswith(cvss_vector, "/S:U")
210+
has_v4_field(input, "AV:L")
211+
has_v4_field(input, "SC:N")
212+
has_v4_field(input, "SI:N")
213+
has_v4_field(input, "SA:N")
174214
}
175215

176216
###############################################################################
177-
# HELPER FUNCTION: Extract the CVSS v3 vector string
217+
# SECTION 6: AVAILABILITY-ONLY IMPACT, SCOPE UNCHANGED
218+
#
219+
# Rationale: CVEs where the only impact is availability (DoS/resource
220+
# exhaustion) and scope is unchanged mean: processing crafted input can
221+
# crash or hang the affected process, but cannot read data (C:N),
222+
# modify data (I:N), or affect other components (S:U).
223+
#
224+
# In ephemeral batch containers, a DoS means a single pipeline job
225+
# fails or hangs until it hits its timeout or memory limit. This is
226+
# operationally equivalent to a corrupted input file or OOM — the job
227+
# fails, the container is destroyed, and the next job runs on a fresh
228+
# container. There is no persistent state corruption, no data
229+
# exfiltration, and no lateral movement.
230+
#
231+
# This rule applies regardless of attack vector (including AV:N),
232+
# because the impact is strictly contained: even if triggered by
233+
# network-delivered data, the worst outcome is one failed job.
234+
#
235+
# NOTE: This does NOT ignore:
236+
# - DoS with S:C / SC≠N / SI≠N / SA≠N (scope changed — could
237+
# affect host or other containers)
238+
# - DoS combined with any confidentiality or integrity impact
239+
# (C≠N or I≠N), which could indicate data leaks or corruption
240+
# alongside the crash
241+
#
242+
# CVSS v3.1: C:N + I:N + S:U (with any A value)
243+
# CVSS v4.0: VC:N + VI:N + SC:N + SI:N + SA:N (with any VA value)
244+
#
245+
# Risk of false negative: Low. The concern would be if a DoS could be
246+
# weaponized into a resource exhaustion attack against the compute
247+
# platform (e.g., repeatedly submitting jobs with crafted inputs to
248+
# burn credits). This is a business logic concern mitigated by job
249+
# submission controls and cost alerts, not by container hardening.
250+
# Confidence: High
251+
###############################################################################
252+
253+
# v3: C:N + I:N + S:U (availability-only, scope unchanged)
254+
ignore {
255+
has_v3_field(input, "C:N")
256+
has_v3_field(input, "I:N")
257+
has_v3_field(input, "S:U")
258+
}
259+
260+
# v4: VC:N + VI:N + no subsequent-component impact (availability-only)
261+
ignore {
262+
has_v4_field(input, "VC:N")
263+
has_v4_field(input, "VI:N")
264+
has_v4_field(input, "SC:N")
265+
has_v4_field(input, "SI:N")
266+
has_v4_field(input, "SA:N")
267+
}
268+
269+
###############################################################################
270+
# HELPER FUNCTIONS: Extract and match CVSS vector strings
178271
#
179272
# Trivy's JSON structure nests CVSS data under input.CVSS with vendor
180273
# keys. The vector string location varies by data source. We check
181274
# multiple common paths and prefer NVD.
182275
#
276+
# CVSS v3.1 vectors look like: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
277+
# CVSS v4.0 vectors look like: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
278+
#
279+
# Fields are slash-delimited key:value pairs. The has_vX_field helpers
280+
# check for a field anywhere in the vector, handling both mid-string
281+
# (/field/) and end-of-string (/field) positions.
282+
#
183283
# IMPORTANT: Run `trivy image --format json <your-image>` and inspect
184284
# the .Vulnerabilities[].CVSS structure to confirm these paths work
185-
# for your Trivy version. If the structure differs, update this
186-
# function accordingly.
285+
# for your Trivy version. If the structure differs, update these
286+
# functions accordingly.
187287
###############################################################################
188288

289+
# --- CVSS v3.1 vector extraction ---
290+
189291
get_v3_vector(vuln) = vector {
190292
vector := vuln.CVSS.nvd.V3Vector
191293
} else = vector {
192294
vector := vuln.CVSS.redhat.V3Vector
193295
} else = vector {
194296
vector := vuln.CVSS.ghsa.V3Vector
195297
} else = vector {
196-
# Fallback: try any vendor that has a V3Vector
197298
some vendor
198299
vector := vuln.CVSS[vendor].V3Vector
199300
} else = "" {
200301
true
201302
}
202303

304+
# --- CVSS v4.0 vector extraction ---
305+
306+
get_v4_vector(vuln) = vector {
307+
vector := vuln.CVSS.nvd.V40Vector
308+
} else = vector {
309+
vector := vuln.CVSS.redhat.V40Vector
310+
} else = vector {
311+
vector := vuln.CVSS.ghsa.V40Vector
312+
} else = vector {
313+
some vendor
314+
vector := vuln.CVSS[vendor].V40Vector
315+
} else = "" {
316+
true
317+
}
318+
319+
# --- Field matching helpers ---
320+
# Check if a CVSS vector contains a specific field value.
321+
# Handles both mid-string (/AV:N/) and end-of-string (/AV:N) positions.
322+
323+
has_v3_field(vuln, field) {
324+
cvss_vector := get_v3_vector(vuln)
325+
cvss_vector != ""
326+
contains(cvss_vector, concat("", ["/", field, "/"]))
327+
}
328+
329+
has_v3_field(vuln, field) {
330+
cvss_vector := get_v3_vector(vuln)
331+
cvss_vector != ""
332+
endswith(cvss_vector, concat("", ["/", field]))
333+
}
334+
335+
has_v4_field(vuln, field) {
336+
cvss_vector := get_v4_vector(vuln)
337+
cvss_vector != ""
338+
contains(cvss_vector, concat("", ["/", field, "/"]))
339+
}
340+
341+
has_v4_field(vuln, field) {
342+
cvss_vector := get_v4_vector(vuln)
343+
cvss_vector != ""
344+
endswith(cvss_vector, concat("", ["/", field]))
345+
}
346+
203347
###############################################################################
204348
# RULES INTENTIONALLY NOT INCLUDED (and why):
205349
#
206-
# 1. AV:N (Network attack vector) — NOT ignored.
350+
# 1. AV:N (Network attack vector) — NOT blanket-ignored.
207351
# Even though batch pipeline containers typically have no inbound
208352
# listeners, some AV:N CVEs involve outbound connections triggered
209353
# by processing attacker-influenced data (e.g., Log4Shell). We
210-
# cannot safely blanket-ignore network-vector CVEs.
354+
# cannot safely blanket-ignore network-vector CVEs. However,
355+
# Section 6 does ignore AV:N CVEs that are availability-only with
356+
# no scope change, since the worst outcome is a crashed job.
211357
#
212358
# 2. UI:R alone (without AV:L) — NOT ignored.
213359
# Some AV:N + UI:R vulnerabilities involve scenarios like processing
@@ -233,4 +379,13 @@ get_v3_vector(vuln) = vector {
233379
# boundaries (e.g., container escape via kernel exploit). These are
234380
# dangerous even in ephemeral containers. Only AV:L + S:U (Scope
235381
# Unchanged) is ignored — see Section 5 above.
382+
#
383+
# 6. Inbound-listener-only server CVEs — NOT categorically ignored.
384+
# Many AV:N CVEs in fat JARs (Jetty, ZooKeeper, Netty server-side)
385+
# require an active network listener that we never start. However,
386+
# CVSS does not distinguish inbound-listener vs. data-processing
387+
# attack surfaces within AV:N. Adding package-name-based exceptions
388+
# here would be fragile and is better handled in .trivyignore with
389+
# per-CVE justification documenting that the server component is
390+
# never instantiated.
236391
###############################################################################

.trivyignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,32 @@
5050
# ADDED: 2026-03-19
5151
# -----------------------------------------------------------------------------
5252
CVE-2026-23949
53+
54+
# -----------------------------------------------------------------------------
55+
# CVE-2020-25649 — jackson-databind XXE in DOMDeserializer
56+
# Severity: HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N)
57+
# Package: com.fasterxml.jackson.core:jackson-databind 2.10.5
58+
# Location: opt/conda/share/snpeff-5.2-3/snpEff.jar
59+
#
60+
# JUSTIFICATION:
61+
# The vulnerable code path is DOMDeserializer, which is invoked when
62+
# jackson-databind deserializes XML input into DOM objects without
63+
# disabling external entity resolution. This enables XXE attacks
64+
# (SSRF, local file read) when processing attacker-controlled XML.
65+
#
66+
# snpEff uses jackson-databind for JSON parsing only (config metadata,
67+
# database indices). snpEff's input formats are VCF (tab-delimited),
68+
# GenBank (flat text), and Java properties files. It never parses XML
69+
# through Jackson's DOMDeserializer. The vulnerable code is present in
70+
# the fat JAR but the code path is never traversed.
71+
#
72+
# This exclusion applies only to snpEff's bundled copy. If jackson-
73+
# databind 2.10.5 appears in other JARs, this entry will NOT suppress
74+
# those findings — Trivy matches .trivyignore by CVE ID globally, but
75+
# we accept this because no other JAR in our images bundles this old
76+
# version. If that changes, re-evaluate this entry.
77+
#
78+
# RESOLUTION: Upstream snpEff must update its bundled jackson-databind.
79+
# ADDED: 2026-03-20
80+
# -----------------------------------------------------------------------------
81+
CVE-2020-25649

docker/requirements/assemble-x86.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55
# Gap2Seq: Fills gaps in genome assemblies using short reads
66
# ARM64 build conflicts with pillow/libtiff due to old htslib/libdeflate pins
7-
gap2seq=3.1.1a
7+
gap2seq>=3.1.1a

0 commit comments

Comments
 (0)