After melange finishes building a package it runs a set of automated lint checks on the produced APK files. These checks catch structural mistakes — wrong install paths, world-writable files, unstripped binaries, temporary files accidentally included in the package — before the package ever reaches a repository. Catching these problems early is far cheaper than debugging them after deployment.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/chainguard-dev/melange/llms.txt
Use this file to discover all available pages before exploring further.
Available linters
melange ships with the following linters, each targeted at a specific class of problem:dev — Unexpected files under /dev
dev — Unexpected files under /dev
If a package is creating device nodes under
/dev, it should use udev rules instead. Any files found under /dev that were not placed there by udev will trigger this linter. Resolution: remove the offending files from the package, or switch to a udev-based approach.opt — Files installed into /opt
opt — Files installed into /opt
Files placed under
/opt indicate the package should follow the -compat convention (see below) rather than installing directly to /opt.setuidgid — setuid or setgid bits are set
setuidgid — setuid or setgid bits are set
The
setuid and setgid permission bits grant a binary elevated privileges when executed. These are rarely appropriate in modern container-oriented packaging. Resolution: remove the bits in your pipeline, or explicitly disable this linter with a justification if the package genuinely requires them.srv — Files installed into /srv
srv — Files installed into /srv
Files placed under
/srv indicate the package should use the -compat convention instead.strip — Binary not stripped
strip — Binary not stripped
Debug symbols left in a binary inflate package size unnecessarily. Ensure your pipeline includes a
strip step (the strip built-in pipeline step handles this automatically).tempdir — Files left in temporary directories
tempdir — Files left in temporary directories
Any files found under
/tmp, /var/tmp, or similar temporary directories indicate that the build pipeline failed to clean up after itself. Remove the offending files in the pipeline before the package is emitted.usrlocal — Files installed into /usr/local
usrlocal — Files installed into /usr/local
Packages should install into
/usr/bin, /usr/lib, etc. rather than /usr/local. If upstream software hard-codes /usr/local, create a -compat subpackage to provide symlinks.varempty — Files left in /var/empty
varempty — Files left in /var/empty
/var/empty is reserved and must remain empty. Remove any files your pipeline places there.worldwrite — World-writable files or directories
worldwrite — World-writable files or directories
World-writable permissions are a security risk. Change the permissions of any offending files in the pipeline, disable the linter with justification, or use the
-compat convention if applicable.Default linter configuration
melange separates linters into two categories: those that must pass (build fails on violation) and those that only warn (build succeeds but the warning is logged). The default--lint-require linters are:
--lint-warn linters are:
These defaults may change as new linters are added. Pass
--lint-require and --lint-warn explicitly to melange build if you need stable, reproducible lint behaviour across melange versions.The -compat package convention
In nearly every case, binaries belong in /usr/bin/, libraries in /usr/lib/, configuration in /etc/, and so on. However, some upstream software (Helm charts, legacy scripts, Docker entrypoints) expects things at non-standard locations like /usr/local/bin or /opt.
The melange convention for handling this is the -compat subpackage:
- Have the main package install files into the standard location (e.g.,
/usr/bin/mytool). - Create a subpackage named
<package>-compatthat moves or symlinks those files to the location the upstream expects (e.g.,/usr/local/bin/mytool).
mytool-compat in addition to (or instead of) mytool. This keeps the main package clean while fully supporting legacy consumers.
Disabling a linter
Lints should only be disabled after confirming that the flag is genuinely inappropriate for the package. When you do disable a linter, always include a comment explaining why. Add achecks.disabled list under package::
Linting existing APK files
melange also exposes a standalonemelange lint command for linting APK files that already exist on disk, without re-running a full build:
Persisting lint results
Pass--persist-lint-results to melange build to write lint findings to JSON files in packages/{arch}/ alongside the APK files. This is useful for automated auditing in CI pipelines:
