> ## Documentation Index
> Fetch the complete documentation index at: https://tally.wharflab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# tally/copy-after-user-without-chown

> COPY/ADD without --chown after USER creates root-owned files.

COPY/ADD without --chown after USER creates root-owned files.

| Property | Value |
| - | - |
| Severity | Warning |
| Category | Correctness |
| Default | Enabled |
| Auto-fix | Yes (two alternatives) |

## Description

Docker's `COPY` and `ADD` instructions always create files owned by `root:root`
(UID 0, GID 0), regardless of the active `USER` instruction. This is a common
source of confusion: authors set `USER nonroot` and then expect subsequent
`COPY`/`ADD` to create files owned by that user.

This rule detects `COPY` or `ADD` instructions that follow a non-root `USER`
without an explicit `--chown` flag. The mismatch means the non-root process may
not be able to write to or modify the copied files at runtime.

## Suppression

The rule is automatically suppressed when:

* The `COPY`/`ADD` instruction already has `--chown` set.
* The effective `USER` at that point in the stage is root (or no `USER` has been
  set).
* A subsequent `RUN chown` command in the same stage targets the same
  destination path (or a parent directory), indicating the author is managing
  ownership explicitly.

## Cross-stage inheritance

The rule walks the `FROM <stage>` ancestry chain. If a parent stage sets a
non-root `USER` that flows into a child stage via `FROM`, `COPY`/`ADD` in the
child stage without `--chown` will trigger the rule.

## Relationship to other rules

| | `tally/copy-after-user-without-chown` | `tally/prefer-copy-chmod` |
| - | - | - |
| Fires when | COPY/ADD after non-root USER without --chown | COPY followed by RUN chmod |
| Fix | Adds `--chown=<user>` or moves USER | Merges into `COPY --chmod` |
| Scope | All stages | All stages |

Both rules can fire on the same `COPY` instruction. Their fixes compose
correctly: the result is `COPY --chown=user --chmod=mode file /dest`.

## Windows stages

On Windows containers `--chown` is silently ignored (see
[`tally/windows/no-chown-flag`](./windows/no-chown-flag)), so the "add
`--chown`" fix is suppressed. The rule still fires — the ownership confusion is
real — but only the "move `USER`" rearrangement fix is offered.

## Auto-fix

Two fix alternatives are offered:

1. **Add `--chown=<user>`** (preferred, safe): inserts `--chown=<user>` to
   match the active `USER`, fixing the ownership mismatch directly.

2. **Move `USER` after COPY/ADD** (safe): relocates the `USER` instruction to
   just before the first `RUN` or `WORKDIR` that follows. This is a semantic
   no-op because `COPY`/`ADD` ownership is always `root:root` regardless of
   `USER`. It clarifies that `USER` only affects `RUN`, `WORKDIR`, and runtime
   identity. This alternative is only offered when no `RUN` or `WORKDIR` exists
   between the `USER` and the `COPY`/`ADD`.

## References

* [Dockerfile reference -- USER](https://docs.docker.com/reference/dockerfile/#user)
* [Dockerfile reference -- COPY --chown](https://docs.docker.com/reference/dockerfile/#copy---chown)
* [Dockerfile reference -- ADD --chown](https://docs.docker.com/reference/dockerfile/#add---chown)
* [Docker Blog -- Understanding the Docker USER Instruction](https://www.docker.com/blog/understanding-the-docker-user-instruction/)

## Examples

### Bad

```dockerfile theme={null}
# COPY after USER without --chown: files are root-owned
FROM ubuntu:22.04
RUN useradd -r appuser
USER appuser
COPY app /app
CMD ["/app"]
```

```dockerfile theme={null}
# ADD after USER without --chown
FROM ubuntu:22.04
USER 1000:1000
ADD config.tar.gz /etc/app/
RUN setup.sh
```

### Good

```dockerfile theme={null}
# Explicit --chown matches the active USER
FROM ubuntu:22.04
RUN useradd -r appuser
USER appuser
COPY --chown=appuser app /app
CMD ["/app"]
```

```dockerfile theme={null}
# USER placed after COPY, before RUN (clarifies intent)
FROM ubuntu:22.04
RUN useradd -r appuser
COPY app /app
USER appuser
RUN setup.sh
CMD ["/app"]
```

```dockerfile theme={null}
# Ownership managed via RUN chown (suppressed)
FROM ubuntu:22.04
RUN useradd -r appuser
USER appuser
COPY app /app
RUN chown -R appuser:appuser /app
CMD ["/app"]
```

```dockerfile theme={null}
# Numeric UID with --chown
FROM ubuntu:22.04
USER 1000:1000
COPY --chown=1000:1000 app /app
CMD ["/app"]
```

## Configuration

```toml theme={null}
[rules.tally.copy-after-user-without-chown]
severity = "warning"  # Options: "off", "error", "warning", "info", "style"
```


## Related topics

- [tally/windows/no-chown-flag](/rules/tally/windows/no-chown-flag.md)
- [tally/named-identity-in-passwdless-stage](/rules/tally/named-identity-in-passwdless-stage.md)
- [tally/world-writable-state-path-workaround](/rules/tally/world-writable-state-path-workaround.md)
- [tally/user-explicit-group-drops-supplementary-groups](/rules/tally/user-explicit-group-drops-supplementary-groups.md)
- [tally/user-created-but-never-used](/rules/tally/user-created-but-never-used.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.