syncable_cli/analyzer/hadolint/rules/
dl3010.rs1use crate::analyzer::hadolint::parser::instruction::Instruction;
7use crate::analyzer::hadolint::rules::{simple_rule, SimpleRule};
8use crate::analyzer::hadolint::shell::ParsedShell;
9use crate::analyzer::hadolint::types::Severity;
10
11pub fn rule() -> SimpleRule<impl Fn(&Instruction, Option<&ParsedShell>) -> bool + Send + Sync> {
12 simple_rule(
13 "DL3010",
14 Severity::Info,
15 "Use ADD for extracting archives into an image.",
16 |instr, _shell| {
17 match instr {
18 Instruction::Copy(args, _) => {
19 !args.sources.iter().any(|src| is_local_archive(src))
21 }
22 _ => true,
23 }
24 },
25 )
26}
27
28fn is_local_archive(src: &str) -> bool {
30 if src.starts_with("http://") || src.starts_with("https://") || src.starts_with("ftp://") {
32 return false;
33 }
34
35 if src.starts_with('$') {
37 return false;
38 }
39
40 let archive_extensions = [
42 ".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz2", ".tar.xz", ".txz",
43 ".tar.zst", ".tar.lz", ".tar.lzma"
44 ];
45
46 let lower = src.to_lowercase();
47 archive_extensions.iter().any(|ext| lower.ends_with(ext))
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use crate::analyzer::hadolint::lint::{lint, LintResult};
54 use crate::analyzer::hadolint::config::HadolintConfig;
55
56 fn lint_dockerfile(content: &str) -> LintResult {
57 lint(content, &HadolintConfig::default())
58 }
59
60 #[test]
61 fn test_copy_tar_file() {
62 let result = lint_dockerfile("FROM ubuntu:20.04\nCOPY app.tar.gz /app/");
63 assert!(result.failures.iter().any(|f| f.code.as_str() == "DL3010"));
64 }
65
66 #[test]
67 fn test_copy_tgz_file() {
68 let result = lint_dockerfile("FROM ubuntu:20.04\nCOPY archive.tgz /tmp/");
69 assert!(result.failures.iter().any(|f| f.code.as_str() == "DL3010"));
70 }
71
72 #[test]
73 fn test_copy_regular_file() {
74 let result = lint_dockerfile("FROM ubuntu:20.04\nCOPY app.js /app/");
75 assert!(!result.failures.iter().any(|f| f.code.as_str() == "DL3010"));
76 }
77
78 #[test]
79 fn test_copy_directory() {
80 let result = lint_dockerfile("FROM ubuntu:20.04\nCOPY src/ /app/");
81 assert!(!result.failures.iter().any(|f| f.code.as_str() == "DL3010"));
82 }
83}