What practices keep publishing credentials out of source control and logs, and what are common mistakes teams make here?
answer
- never in script or committed gradle.properties
- ~/.gradle/gradle.properties (per-user)
- CI: ORG_GRADLE_PROJECT_* from secret store
- no tokens in URLs, no logging
- scope + rotate tokens
basics
~10 sNever hardcode credentials in build scripts. Put them in ~/.gradle/gradle.properties (per-user, never committed) or inject via ORG_GRADLE_PROJECT_* env vars in CI. Use the credentials(PasswordCredentials::class) convention so values stay external.
solid answer
~40 sThe cardinal rule: secrets never live in the build script or a committed `gradle.properties`. Use the `credentials(PasswordCredentials::class)` convention and supply `<repoName>Username`/`<repoName>Password` from `~/.gradle/gradle.properties` locally (per-user, outside the project) or from `ORG_GRADLE_PROJECT_*` environment variables in CI sourced from a secret store. Common mistakes: committing the project `gradle.properties` with real values, echoing secrets via `println` or `--info`/`--debug` logs, embedding tokens in repository URLs, and storing them in `local.properties` thinking it's safe (it can still be committed). Prefer lazy `providers.gradleProperty(...)` so the value isn't read until needed and isn't captured by the configuration cache. Rotate and scope tokens, and keep `~/.gradle/gradle.properties` and any secret files in `.gitignore`.
code
toml · 6 lines# ~/.gradle/gradle.properties (per-user, NEVER committed)
myRepoUsername=ci-deployer
myRepoPassword=glpat-xxxxxxxxxxxxxxxx
# Project .gitignore should include any secret-bearing files;
# the project gradle.properties must hold NO credentials.go deeper
Know not to hardcode secrets and that ~/.gradle/gradle.properties is the per-user place for them.
List the safe sources (per-user file, CI env vars) and the common leak vectors (committed files, URLs, logs).
Add lazy-resolution/config-cache reasoning and least-privilege, rotatable tokens; recognize init.gradle distribution risks.
Define org secret-management policy: central secret store, scoped deploy tokens, rotation, and audit; ensure conventions make the safe path the default.
## The one rule **Secrets must not be in version control or in the build script.** Everything else follows from making that true while still letting Gradle resolve them. ## Safe storage locations - **`~/.gradle/gradle.properties`** — per-user, outside the project tree, never committed. Best place for a developer's personal publishing creds. - **CI secret store → `ORG_GRADLE_PROJECT_*` env vars** — the secret exists only in the job process. No file on disk. - **Command-line `-P`** — possible but risky (visible in process listings / shell history); avoid for real secrets. The project's own `gradle.properties` is fine for **non-secret** config but must never hold credentials, because it's typically committed. ## How the convention helps `credentials(PasswordCredentials::class)` already forces values out of the script — you reference a *property*, not a literal. That's the main reason to use the type-based form rather than inline literals. ## Avoid leaking via logs - Don't `println(password)` or log credential values. - Be careful with `--info`/`--debug`; avoid printing resolved credentials. - Don't embed tokens in repository URLs (`https://user:token@host/...`) — they show up in logs and error output. ## Laziness reduces exposure Use `providers.gradleProperty("...")` (lazy) rather than eager `System.getenv()` reads, so: - the secret is only read when a publish task runs, and - it isn't serialized into the configuration cache. ## Common mistakes (interview gold) 1. Committing project `gradle.properties` (or `local.properties`) with real credentials. 2. Hardcoding literals in the `build.gradle.kts`. 3. Putting tokens in the repo URL. 4. Logging/echoing secrets in custom tasks or CI scripts. 5. Long-lived, over-scoped tokens that are never rotated. 6. Checking secrets into a shared `init.gradle` without realizing it's distributed. ## Operational hygiene - `.gitignore` any secret-bearing file. - Scope tokens to the minimum (publish-only, single repo) and rotate them. - Use deploy/service tokens rather than personal credentials in CI.
- Is it safe to keep credentials in the project's own `gradle.properties`?No — it's normally committed, so it would leak the secret. Use `~/.gradle/gradle.properties` or CI env vars instead.
- Why avoid embedding the token directly in the repository URL?URLs appear in logs, error messages, and process listings, so the token leaks easily; keep it in credentials sourced from a property.
- How does using `providers.gradleProperty(...)` reduce secret exposure compared to `System.getenv()`?It's lazy — read only when publishing runs and not captured by the configuration cache — so the secret is touched less and isn't serialized.
saying these in an interview costs you the question
- Treating the committed project `gradle.properties` or `local.properties` as a safe place for secrets.
- Suggesting `https://user:token@host` URLs.
- Printing/logging credential values for debugging.
- Using a personal long-lived token in CI instead of a scoped, rotatable deploy token.