Skip to content

Commit 61fad04

Browse files
committed
2.0.19 fixed false positive for apk no cache arg detection
1 parent e7d3308 commit 61fad04

6 files changed

Lines changed: 59 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
# Cloud (IaC) Security Changelog
44

5-
## [2.0.18] 10-05-2026
5+
## [2.0.19] 01-05-2026
6+
7+
### Fixed
8+
9+
- Fixed false positive for apk no cache arg detection, thanks to [m0nclous](https://github.com/m0nclous)
10+
11+
## [2.0.18] 10-04-2026
612

713
### Changed
814
- Updated plugin to support new version of the IntelliJ Platform, thanks to [kylichist](https://github.com/kylichist)

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pluginGroup = dev.protsenko.securityLinter
22
pluginName = Cloud (IaC) Security
33
pluginRepositoryUrl = https://github.com/NordCoderd/cloud-security-plugin
4-
pluginVersion = 2.0.18
4+
pluginVersion = 2.0.19
55

66
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
77
pluginSinceBuild = 231

src/main/kotlin/dev/protsenko/securityLinter/docker/checker/ApkNoCacheValidator.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,28 @@ package dev.protsenko.securityLinter.docker.checker
33
import dev.protsenko.securityLinter.docker.checker.core.RunCommandValidator
44

55
object ApkNoCacheValidator : RunCommandValidator {
6+
/**
7+
* Matches valid Dockerfile RUN commands for Alpine package installation.
8+
*
9+
* Two alternative valid forms are accepted:
10+
*
11+
* 1. BuildKit cache-mount path: the command has a --mount=type=cache flag whose target
12+
* key equals /var/cache/apk (optional trailing slash or surrounding quotes). BuildKit
13+
* keeps /var/cache/apk off the final image layer, so --no-cache is not needed.
14+
* The exemption is revoked when the command also contains rm -rf /var/cache/apk/star,
15+
* which would defeat the cache-mount benefit.
16+
*
17+
* 2. Standard path: the command either omits apk add entirely or includes --no-cache;
18+
* and it never calls apk update (which bloats image layers); and it never manually
19+
* removes /var/cache/apk/star (redundant when --no-cache is already present).
20+
*/
621
private val VALID_COMMAND_PATTERN =
722
Regex(
8-
"^\\s*RUN(?:(?!.*apk add)|(?=.*--no-cache))(?!.*apk update)(?!.*rm\\s+.*?/var/cache/apk/\\*).*$",
23+
"^\\s*RUN(?:" +
24+
"(?=.*--mount=type=cache(?=\\S*,target=\"?/var/cache/apk/?\"?)\\S*)(?!.*rm\\s+\\S*r\\S*\\s+.*?/var/cache/apk/\\*)" +
25+
"|" +
26+
"(?:(?!.*apk add)|(?=.*--no-cache))(?!.*apk update)(?!.*rm\\s+.*?/var/cache/apk/\\*)" +
27+
").*\$",
928
RegexOption.DOT_MATCHES_ALL,
1029
)
1130

src/test/kotlin/dev/protsenko/securityLinter/utils/ApkNoCacheValidatorTest.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,23 @@ class ApkNoCacheApkNoCacheValidatorTest : TestCase() {
1717
assertTrue(ApkNoCacheValidator.isValid(multiLineValid))
1818
assertTrue(ApkNoCacheValidator.isValid("RUN ./autoupdate-script.sh"))
1919
assertTrue(ApkNoCacheValidator.isValid(" RUN apk add --no-cache git"))
20+
// BuildKit cache mount cases — no --no-cache required (fixing DFS030 false positive)
21+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/var/cache/apk apk add curl git"))
22+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/var/cache/apk/ apk add curl"))
23+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=\"/var/cache/apk\" apk add curl"))
24+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/var/cache/apk,sharing=locked,id=apk apk add curl"))
25+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,id=apk,target=/var/cache/apk apk add curl"))
26+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=secret,id=x --mount=type=cache,target=/var/cache/apk apk add curl"))
27+
val multiLineMount =
28+
"""
29+
RUN --mount=type=cache,target=/var/cache/apk \
30+
apk add curl git
31+
""".trimIndent()
32+
assertTrue(ApkNoCacheValidator.isValid(multiLineMount))
33+
// Both mount and --no-cache present — must remain valid without double-detection
34+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/var/cache/apk apk add --no-cache curl"))
35+
// Mount covers apk update too
36+
assertTrue(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/var/cache/apk apk update && apk add curl"))
2037
}
2138

2239
fun testInvalidCommands() {
@@ -33,5 +50,12 @@ class ApkNoCacheApkNoCacheValidatorTest : TestCase() {
3350
assertFalse(ApkNoCacheValidator.isValid(multiLineInvalid))
3451
assertFalse(ApkNoCacheValidator.isValid("apk add --no-cache git"))
3552
assertFalse(ApkNoCacheValidator.isValid(""))
53+
// Mount present but wrong target — still invalid
54+
assertFalse(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/root/.cache apk add curl"))
55+
// Wrong mount type — only type=cache exempts
56+
assertFalse(ApkNoCacheValidator.isValid("RUN --mount=type=bind,target=/var/cache/apk apk add curl"))
57+
assertFalse(ApkNoCacheValidator.isValid("RUN --mount=type=tmpfs,target=/var/cache/apk apk add curl"))
58+
// Cache mount + explicit rm defeats caching — still invalid
59+
assertFalse(ApkNoCacheValidator.isValid("RUN --mount=type=cache,target=/var/cache/apk apk add curl && rm -rf /var/cache/apk/*"))
3660
}
3761
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
FROM alpine:3.13
2-
RUN apk add --no-cache git
2+
<warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN apk add --no-cache git</warning>
3+
<warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN --mount=type=cache,target=/var/cache/apk apk add curl git</warning>
4+
<warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN --mount=type=cache,target=/var/cache/apk,sharing=locked apk add curl</warning>
5+
<warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN --mount=type=secret,id=s --mount=type=cache,target=/var/cache/apk \
6+
apk add curl</warning>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
FROM alpine:3.13
22
<warning descr="Alpine package installation without --no-cache, consider using it to reduce image size."><warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN apk add git</warning></warning>
3-
<warning descr="Alpine package installation without --no-cache, consider using it to reduce image size."><warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN apk add git && rm -rf /var/cache/apk/*</warning></warning>
3+
<warning descr="Alpine package installation without --no-cache, consider using it to reduce image size."><warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN apk add git && rm -rf /var/cache/apk/*</warning></warning>
4+
<warning descr="Alpine package installation without --no-cache, consider using it to reduce image size."><warning descr="Multiple consecutive 'RUN' instructions. Consider consolidation.">RUN --mount=type=cache,target=/root/.cache apk add curl</warning></warning>

0 commit comments

Comments
 (0)