Skip to content

Commit b11577f

Browse files
committed
fix: ignore escaped compose variables (SPEC-C04)
1 parent 28f0212 commit b11577f

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

‎src/spec/checkPackageSpec.ts‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,14 @@ export function checkPackageSpec({
194194
const composePath = path.join(dir, composeFileName);
195195
if (fs.existsSync(composePath)) {
196196
const text = fs.readFileSync(composePath, "utf8");
197-
const interpolated = [...new Set(text.match(/\$\{[^}]*\}/g) || [])];
197+
// Compose consumes dollar signs in escaped pairs before interpolating.
198+
const interpolated = [
199+
...new Set(
200+
[...text.matchAll(/(\$+)\{[^}]*\}/g)]
201+
.filter(match => match[1].length % 2 === 1)
202+
.map(match => match[0].slice(match[1].length - 1))
203+
)
204+
];
198205
if (interpolated.length > 0)
199206
add(
200207
"SPEC-C04",

‎test/spec/checkPackageSpec.test.ts‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,57 @@ describe("package spec checks", function () {
151151
).to.include('version "v1.0.0"');
152152
});
153153

154+
it("accepts escaped compose variables without reporting interpolation", () => {
155+
write("dappnode_package.json", {
156+
name: "demo.dnp.dappnode.eth",
157+
version: "0.1.0"
158+
});
159+
write(
160+
"docker-compose.yml",
161+
yaml.dump({
162+
services: {
163+
app: {
164+
image: "alpine:3.21",
165+
environment: {
166+
HEALTH_PORT: "$${PORT:-9090}",
167+
HEALTH_TOKEN: "$${ANON_KEY}",
168+
LITERAL: "$$$${LITERAL}"
169+
}
170+
}
171+
}
172+
})
173+
);
174+
expect(check(dir)).to.deep.equal([]);
175+
});
176+
177+
it("reports real interpolation after escaped dollar pairs", () => {
178+
write("dappnode_package.json", {
179+
name: "demo.dnp.dappnode.eth",
180+
version: "0.1.0"
181+
});
182+
write(
183+
"docker-compose.yml",
184+
yaml.dump({
185+
services: {
186+
app: {
187+
image: "alpine:3.21",
188+
environment: {
189+
PORT: "${PORT:-80}",
190+
PREFIXED: "$$${TOKEN}",
191+
REPEATED: "${PORT:-80}",
192+
ESCAPED: "$${SAFE}"
193+
}
194+
}
195+
}
196+
})
197+
);
198+
const findings = check(dir).filter(finding => finding.rule === "SPEC-C04");
199+
expect(findings).to.have.length(1);
200+
expect(findings[0].message).to.equal(
201+
"Uses environment interpolation ${PORT:-80}, ${TOKEN}; write the values out."
202+
);
203+
});
204+
154205
it("accepts digest-pinned args, shorter variant upstream lists and real avatars", () => {
155206
write("dappnode_package.json", {
156207
upstream: [

0 commit comments

Comments
 (0)