Secure Tooling Practices
Secret di shell history, logs, env, Git; token permission, SSH/GPG key, commit signing, credential helper, CI secret, least privilege, clipboard risk, dan local machine hygiene.
Part 048 — Secure Tooling Practices
1. Core idea
Secure tooling practices adalah discipline untuk memakai command line, Git, GitHub, CI/CD, secret, token, key, dan local machine tanpa menciptakan security incident.
Senior backend engineer sering punya akses luas:
- source code,
- private repositories,
- internal package repositories,
- CI/CD secrets,
- container registry,
- Kubernetes clusters,
- cloud accounts,
- production logs,
- database access,
- feature flags,
- deployment pipelines.
Semakin senior engineer, semakin besar risiko tooling mistake:
- token masuk shell history,
- secret tercetak di logs,
- credential ter-commit ke Git,
- personal access token terlalu luas,
- CI workflow memakai permission write secara default,
- third-party GitHub Action tidak dipin,
- SSH key tidak dilindungi,
- GPG/signing key salah kelola,
- debug artifact berisi PII,
- command salah account/cluster,
- clipboard menyimpan secret,
- local laptop menjadi weak link.
Secure tooling bukan paranoia. Secure tooling adalah membuat workflow aman sebagai default.
2. Threat model untuk engineering tooling
Attack atau leakage surface:
- command line arguments,
- environment variables,
- shell history,
.envfiles,- config files,
- Git commits,
- PR comments,
- CI logs,
- build artifacts,
- Docker layers,
- container image labels,
- Kubernetes manifests,
- debug dumps,
- screenshots,
- clipboard,
- terminal scrollback,
- local cache,
- IDE plugins,
- browser extensions.
Senior engineer harus mampu bertanya:
Di mana credential ini berada, siapa bisa membacanya, berapa lama hidupnya, dan apa blast radius jika bocor?
3. Secret handling mental model
Secret adalah informasi yang memberi kemampuan akses atau mengungkap data sensitif.
Contoh:
- password,
- API key,
- OAuth token,
- JWT,
- session cookie,
- private key,
- SSH key,
- GPG private key,
- database connection string,
- cloud access key,
- container registry credential,
- webhook secret,
- encryption key,
- mTLS private key,
- service account token,
- signed URL,
- production customer data sample.
Secret lifecycle
Pertanyaan untuk setiap secret:
- Siapa issuer-nya?
- Di mana secret disimpan?
- Bagaimana secret dikirim ke runtime?
- Siapa bisa membaca?
- Apakah ada expiry?
- Bagaimana rotation dilakukan?
- Bagaimana revoke dilakukan?
- Apakah usage diaudit?
- Apa scope permission-nya?
4. Secrets in shell history
Shell history adalah leakage surface yang sering diremehkan.
Bad:
curl -H "Authorization: Bearer eyJhbGciOi..." https://api.internal/orders
psql "postgres://user:password@host:5432/db"
export AWS_SECRET_ACCESS_KEY=abc123
Command seperti itu bisa tersimpan di:
~/.bash_history,~/.zsh_history,- terminal scrollback,
- shell session recorder,
- debug logs,
- screen sharing recording,
- copied documentation,
- incident chat.
Safer patterns
Gunakan approved secret manager atau credential helper. Jika harus memakai token sementara, hindari menaruh value langsung di command.
Contoh menggunakan file header sementara dengan permission ketat:
umask 077
cat > /tmp/api-headers.$$ <<'EOF_HEADERS'
Authorization: Bearer <token-from-approved-secure-source>
Content-Type: application/json
EOF_HEADERS
curl -sS -H @/tmp/api-headers.$$ https://api.internal/health
rm -f /tmp/api-headers.$$
Tetap pastikan token tidak tertulis di file yang tersisa.
History controls awareness
Beberapa shell mendukung spasi di awal command agar tidak masuk history, tetapi jangan mengandalkan ini sebagai kontrol utama.
export TOKEN=...
Masalahnya:
- setting shell bisa berbeda,
- terminal recorder tetap bisa menangkap,
- environment process masih bisa terbaca dalam kondisi tertentu,
- command bisa tetap muncul di audit system.
Prinsip: jangan mengetik secret mentah ke terminal kecuali memang approved dan unavoidable.
5. Secrets in environment variables
Environment variable nyaman, tetapi bukan tempat aman universal.
Risiko:
- bisa muncul di process inspection,
- bisa tercetak oleh debug script,
- bisa ikut crash report,
- bisa muncul di CI logs jika echo salah,
- bisa diwariskan ke child process,
- bisa tersimpan di shell profile,
- bisa masuk Docker image jika salah pakai
ENV, - bisa masuk Kubernetes manifest jika tidak memakai Secret mechanism.
Bad local pattern
export DB_PASSWORD=production-password
mvn test
Bad Dockerfile pattern
ENV DB_PASSWORD=production-password
Secret di Dockerfile bisa masuk image layer/history.
Better direction
- Gunakan secret manager internal.
- Gunakan short-lived credentials.
- Gunakan OIDC federation untuk CI/CD jika tersedia.
- Gunakan Kubernetes Secret atau external secret operator sesuai standard internal.
- Batasi environment dump dalam logs.
- Redact known sensitive keys.
Redaction in scripts
print_config_safe() {
env | sort | sed -E 's/(PASSWORD|TOKEN|SECRET|KEY)=.*/\1=<redacted>/I'
}
Jangan pernah env penuh ke CI log tanpa redaction.
6. Secrets in logs
Logs sering bertahan lebih lama daripada secret itu sendiri.
Secret bisa bocor melalui:
- request header,
- query string,
- exception message,
- stack trace with config,
- debug-level logging,
- HTTP client wire log,
- SQL log,
- failed command output,
- CI build logs,
- application startup config dump.
Dangerous examples
Authorization: Bearer eyJhbGciOi...
Set-Cookie: SESSION=...
jdbc:postgresql://host/db?user=app&password=secret
Logging guardrails
- Jangan log full headers.
- Jangan log full request body untuk sensitive endpoint.
- Redact tokens/cookies/passwords.
- Hindari secret di URL query string.
- Matikan HTTP wire log di production kecuali emergency approved.
- Gunakan structured logging dengan redaction policy.
- Review exception message dari library/client.
PR review question
Jika kode ini gagal di production, apakah exception/log-nya akan mencetak secret, credential, token, PII, atau customer data?
7. Secrets in Git
Git adalah append-only-ish history. Secret yang pernah commit tidak cukup hanya dihapus dari file terbaru.
Bad:
git add .env
git commit -m "Add local config"
git push
Jika secret terlanjur masuk Git:
- Anggap secret compromised.
- Revoke/rotate secret.
- Jalankan incident/security process internal.
- Bersihkan history jika perlu, sesuai policy.
- Tambahkan preventive control.
Menghapus file dan commit baru bukan recovery cukup:
git rm .env
git commit -m "Remove secret"
Secret tetap ada di history sebelumnya.
Preventive controls
.gitignoreuntuk.env, local config, key files.- Secret scanning pre-commit.
- GitHub secret scanning.
- Avoid copy-paste secret ke config example.
- Gunakan
.env.exampletanpa value sensitif. - Gunakan placeholder eksplisit.
Example .gitignore:
.env
.env.*
!.env.example
*.pem
*.key
*.p12
*.jks
secrets/
local-*.yaml
Example safe config template
DB_URL=jdbc:postgresql://localhost:5432/app
DB_USERNAME=app
DB_PASSWORD=<set-via-secret-manager-or-local-env>
8. Token permission and least privilege
Least privilege berarti token hanya punya permission yang dibutuhkan, untuk durasi yang dibutuhkan, pada resource yang dibutuhkan.
Bad token design
- Personal access token dengan access semua repo.
- Token tidak punya expiry.
- Token dipakai di local dan CI sekaligus.
- Token write/admin padahal hanya perlu read.
- Token disimpan di shared document.
- Token service account tidak diaudit.
Better token design
- Short-lived token.
- Fine-grained token.
- Repo-scoped permission.
- Read-only jika cukup.
- Separate token untuk local vs automation.
- Rotation policy.
- Owner jelas.
- Audit usage.
GitHub Actions permission example
Bad:
permissions: write-all
Better default:
permissions:
contents: read
Add only what is needed:
permissions:
contents: read
packages: write
id-token: write
id-token: write biasanya dipakai untuk OIDC federation. Jangan aktifkan tanpa memahami trust policy cloud/provider.
9. SSH keys
SSH key memberi akses kuat ke repository atau server. Perlakukan seperti production credential.
Good practice
- Gunakan key berbeda untuk personal/work jika policy meminta.
- Gunakan passphrase.
- Gunakan hardware-backed key jika tersedia.
- Jangan share private key.
- Jangan commit private key.
- Jangan copy private key ke server random.
- Rotate jika laptop hilang/compromised.
- Remove key lama dari GitHub/internal systems.
File permission
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
Jika permission terlalu longgar, SSH bisa menolak key.
SSH config example
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Debugging SSH safely
ssh -T git@github.com
ssh -vT git@github.com
Hati-hati membagikan output ssh -v; biasanya tidak mencetak private key, tetapi tetap bisa mengandung path, username, host internal, dan environment detail.
10. GPG key and commit signing
Commit signing membantu membuktikan bahwa commit dibuat oleh identity yang memegang signing key.
Namun signing bukan magic security. Signing tidak membuktikan code benar, hanya membantu integrity/identity.
Concepts
- GPG key/private key,
- public key,
- signed commit,
- verified commit,
- signed tag,
- trust model,
- key expiry,
- revocation certificate.
Git config example
git config --global user.signingkey <key-id>
git config --global commit.gpgsign true
Verify signatures
git log --show-signature -1
git tag -v v1.42.0
Failure modes
- Signing key expired.
- Wrong email identity.
- Commit verified locally but not in GitHub because key not uploaded.
- CI bot commits unsigned while branch requires signed commits.
- Developer rotates key but old key still active.
- Signing creates false sense of safety while PR review weak.
Internal verification checklist
- Apakah commit signing diwajibkan?
- Apakah tag signing diwajibkan untuk release?
- Apakah bot/automation punya signing process?
- Bagaimana key rotation dilakukan?
- Bagaimana revoked key ditangani?
11. Credential helpers
Git credential helper menyimpan credential agar developer tidak mengetik token berulang-ulang.
Contoh melihat config:
git config --global --get credential.helper
Common helpers:
- OS keychain,
- Git Credential Manager,
- cache helper,
- store helper.
Warning about store helper
store bisa menyimpan credential dalam plaintext file.
git config --global credential.helper store
Ini harus diverifikasi dengan policy internal. Untuk environment enterprise, OS keychain atau approved credential manager biasanya lebih aman.
Review questions
- Credential disimpan di mana?
- Apakah encrypted at rest?
- Apakah protected by OS account?
- Bagaimana revoke jika laptop hilang?
- Apakah token punya expiry?
12. CI secret safety
CI/CD adalah high-value target karena punya akses build, publish artifact, push image, deploy, dan membaca secrets.
CI secret leakage paths
echo $SECRET,- debug mode
set -x, - printing environment,
- test failure output,
- dependency tool logs,
- uploading workspace as artifact,
- Docker build args,
- cache containing credentials,
- third-party action reading environment,
- PR from fork accessing secrets,
- overly broad workflow permissions.
Bash set -x danger
Bad:
set -x
curl -H "Authorization: Bearer $TOKEN" https://api.internal/deploy
This can print expanded command with token.
Safer:
set +x
curl -sS -H "Authorization: Bearer ${TOKEN}" https://api.internal/deploy
Even better: use approved deployment action or OIDC-based auth.
Docker build secret danger
Bad:
ARG TOKEN
RUN curl -H "Authorization: Bearer $TOKEN" https://repo.internal/package
Build args can leak through image history or logs.
Use BuildKit secrets or approved internal mechanism if available:
DOCKER_BUILDKIT=1 docker build \
--secret id=repo_token,env=REPO_TOKEN \
.
Dockerfile:
RUN --mount=type=secret,id=repo_token \
token="$(cat /run/secrets/repo_token)" && \
curl -H "Authorization: Bearer ${token}" https://repo.internal/package
Verify internal policy and tool support before standardizing this.
13. GitHub Actions security posture
GitHub Actions workflow harus diperlakukan sebagai executable production automation.
Secure defaults
permissions:
contents: read
Pin third-party actions:
- uses: actions/checkout@v4
For higher assurance, pin by SHA for third-party actions outside trusted set:
- uses: vendor/action@<full-commit-sha>
Risky patterns
pull_request_target:
pull_request_target can be dangerous because it runs with context of base repository. It needs careful design, especially when combined with checkout of untrusted PR code.
Risky:
- run: |
echo "Deploying..."
./scripts/deploy.sh
Questions:
- Who can trigger this workflow?
- Does it run on fork PR?
- Are secrets available?
- What permissions does
GITHUB_TOKENhave? - Are actions pinned?
- Are scripts from PR branch executed with privileged token?
- Are artifacts trusted?
OIDC federation
OIDC can reduce long-lived cloud secrets in CI, but trust policy must be tight:
- restrict repository,
- restrict branch/tag/environment,
- restrict workflow if possible,
- restrict audience,
- use least privilege cloud role,
- audit assumptions.
14. Local machine hygiene
Developer machine adalah part of engineering system.
Hygiene checklist
- Full disk encryption enabled.
- OS updated.
- Browser and IDE updated.
- Approved password manager used.
- Screen lock enabled.
- No shared OS user account.
- Work and personal credentials separated.
- SSH/GPG keys protected.
- Malware/untrusted tools avoided.
- CLI tools installed from trusted source.
- Old credentials removed.
- Local sensitive files minimized.
- Debug dumps cleaned according to policy.
CLI tool supply-chain
Be careful installing random tools via:
curl https://example.com/install.sh | bash
This pattern executes remote code immediately.
Safer approach:
curl -fsSLO https://example.com/install.sh
less install.sh
sha256sum install.sh
bash install.sh
Even this requires trust in source and checksum. Prefer package managers, internal mirrors, signed releases, or approved tool catalogs.
15. Clipboard, screenshots, and sharing risk
Secret leakage is not only files and Git.
Risks:
- copying token to clipboard,
- screen sharing terminal with env dump,
- posting screenshot with URL containing token,
- sharing logs with customer data,
- pasting stack trace with secret in chat,
- uploading heap dump to ticket,
- adding production sample payload to PR.
Safe sharing checklist
Before sharing evidence:
- Are tokens/cookies redacted?
- Are customer identifiers allowed to be shared?
- Are internal hostnames allowed?
- Is the destination approved?
- Does the artifact expire or need deletion?
- Is access limited?
- Does this belong in incident record or private security channel?
Redaction pattern
sed -E \
-e 's/(Authorization: Bearer )[A-Za-z0-9._-]+/\1<redacted>/g' \
-e 's/(password=)[^& ]+/\1<redacted>/gi' \
-e 's/(token=)[^& ]+/\1<redacted>/gi' \
input.log > output.redacted.log
Always inspect redacted output before sharing.
16. Secure use of cloud and Kubernetes CLI
Cloud/Kubernetes CLI mistakes can be severe because context determines target.
Context safety
Before changing anything:
kubectl config current-context
kubectl get ns
aws sts get-caller-identity
az account show --query '{name:name, id:id, tenantId:tenantId}'
For destructive commands, require explicit context confirmation in scripts.
require_context() {
expected="$1"
actual="$(kubectl config current-context)"
if [ "$actual" != "$expected" ]; then
echo "Refusing: current context is $actual, expected $expected" >&2
exit 1
fi
}
Namespace safety
Always use explicit namespace for production commands:
kubectl get pods -n quote-prod
Avoid relying on current namespace in scripts.
Secret inspection warning
Bad:
kubectl get secret app-secret -n prod -o yaml
This can dump base64-encoded secret. Base64 is encoding, not encryption.
Safer:
kubectl describe secret app-secret -n prod
Even metadata can be sensitive in some environments. Follow internal policy.
17. Secure Maven and dependency tooling
Build tooling can introduce supply-chain risk.
Maven risk areas
- unpinned plugin versions,
- untrusted repositories,
- HTTP repositories,
- dependency confusion,
- malicious transitive dependency,
- compromised plugin,
- snapshot dependency in release,
- broad repository mirrors,
- credentials in
settings.xml, - credentials committed to POM,
- generated sources from untrusted processor,
- shade plugin hiding vulnerable code.
Settings file caution
~/.m2/settings.xml may contain credentials.
Do not commit it.
Example safe pattern:
<server>
<id>internal-repo</id>
<username>${env.MAVEN_REPO_USER}</username>
<password>${env.MAVEN_REPO_TOKEN}</password>
</server>
Even env-based credentials need secure injection.
Repository review questions
- Are repositories internal/approved?
- Are plugin repositories controlled?
- Are plugin versions pinned?
- Are snapshots allowed?
- Is dependency verification/SCA enabled?
- Is SBOM generated?
- Is license policy enforced?
18. Secure scripts
Automation scripts can encode dangerous assumptions.
Script security checklist
- Quote variables.
- Avoid
evalunless absolutely necessary. - Validate arguments.
- Validate environment/context.
- Avoid printing secrets.
- Disable xtrace around sensitive operations.
- Use temp files securely.
- Clean up temp files.
- Use least privilege credentials.
- Add dry-run mode for destructive operations.
- Add explicit confirmation for prod changes.
- Fail closed, not open.
Dangerous examples
Unquoted variable:
rm -rf $TARGET_DIR
Safer:
: "${TARGET_DIR:?TARGET_DIR is required}"
rm -rf -- "$TARGET_DIR"
But for destructive commands, add guard:
case "$TARGET_DIR" in
/tmp/my-tool/*) rm -rf -- "$TARGET_DIR" ;;
*) echo "Refusing unsafe target: $TARGET_DIR" >&2; exit 1 ;;
esac
Avoid eval:
eval "$USER_SUPPLIED_COMMAND"
This is command injection unless input is tightly controlled.
19. Secure debugging artifacts
Debugging artifacts can be more sensitive than logs.
High-risk artifacts:
- heap dump,
- thread dump,
- core dump,
- database dump,
- production payload sample,
- HAR file,
- full HTTP trace,
- CI workspace archive,
- Kubernetes secret dump,
- cloud IAM policy export,
- config bundle,
- support bundle.
Handling questions
- Does this artifact contain PII/customer data?
- Does it contain secrets/tokens?
- Where will it be stored?
- Who can access it?
- How long will it be retained?
- Is encryption required?
- Is approval required?
- How will it be deleted?
Heap dump rule
Heap dumps should be treated as sensitive data stores. Do not casually create or share them.
20. Incident response for leaked secrets
If a secret is leaked, do not just delete the message/file.
Response sequence
- Stop further spread if possible.
- Notify according to internal security process.
- Identify secret type and scope.
- Revoke or rotate immediately if safe.
- Identify systems that used the secret.
- Audit usage after suspected leak.
- Remove exposed copies according to policy.
- Add preventive control.
- Document timeline and remediation.
Common mistake
Bad:
I deleted the secret from the PR, so it is fine.
Correct:
The secret must be treated as compromised, rotated/revoked, and checked for unauthorized use.
21. PR review checklist for secure tooling
Saat mereview perubahan pada scripts, CI/CD, Maven, GitHub Actions, Dockerfile, Kubernetes manifests, docs, atau runbooks, gunakan checklist berikut.
Secrets
- Apakah ada hardcoded token/password/key?
- Apakah command mencetak secret?
- Apakah secret masuk env/log/artifact/cache?
- Apakah
.env.exampleaman? - Apakah secret handling sesuai platform internal?
Permissions
- Apakah token permission least privilege?
- Apakah workflow memakai
write-alltanpa alasan? - Apakah cloud role terlalu luas?
- Apakah deployment environment protected?
- Apakah approval gate sesuai risiko?
Supply chain
- Apakah GitHub Actions dipin?
- Apakah dependency/plugin version dipin?
- Apakah repository source trusted?
- Apakah SBOM/SCA/license scan berjalan?
- Apakah Docker base image trusted?
Script safety
- Apakah script punya context guard?
- Apakah destructive action punya dry-run/confirmation?
- Apakah variable di-quote?
- Apakah
evaldihindari? - Apakah temp file permission aman?
Evidence and logs
- Apakah logging meredact sensitive data?
- Apakah debug mode aman?
- Apakah artifact upload mengecualikan secret?
- Apakah runbook memperingatkan command berisiko?
22. Internal verification checklist for CSG/team
Detail berikut harus diverifikasi di internal CSG/team:
- Secret management platform yang digunakan.
- Policy local
.envdan secret injection. - GitHub secret scanning policy.
- Dependabot/dependency scanning policy.
- Required commit signing/tag signing.
- Approved credential helper.
- SSH/GPG key policy.
- PAT/fine-grained token policy.
- CI/CD secret policy.
- GitHub Actions allowed actions/pinning policy.
- OIDC federation availability dan trust policy.
- Cloud IAM/RBAC access process.
- Kubernetes secret access policy.
- Production log redaction policy.
- Evidence sharing and retention policy.
- Heap dump/thread dump handling policy.
- Incident response process untuk leaked secret.
- Local machine security baseline.
- Approved CLI/tool installation source.
- Artifact repository credential policy.
- Container registry access policy.
23. Senior heuristics
- A secret typed into a terminal is already at risk.
- Deleting a leaked secret is not remediation. Rotation/revocation is remediation.
- Base64 is not encryption.
- CI logs are production artifacts. Treat them as shared evidence.
set -xand secrets do not mix.- Least privilege should be encoded in tooling, not remembered manually.
- A workflow file is code with permissions. Review it like production code.
- A third-party action is a dependency with execution rights.
- Local laptop hygiene is part of supply-chain security.
- Secure tooling should make the safe path easier than the shortcut.
24. Practical exercises
- Cek shell history lokal. Pastikan tidak ada token, password, connection string, atau cookie.
- Review
.gitignorerepo. Apakah.env, key file, local config, dan secret bundle sudah dikecualikan? - Ambil satu GitHub Actions workflow. Turunkan permission ke minimum yang dibutuhkan.
- Cek apakah workflow memakai third-party action yang tidak dipin.
- Review satu script deploy/debug. Cari
set -x,eval, unquoted variable, dan command destructive tanpa guard. - Cek
~/.m2/settings.xml. Pastikan tidak pernah masuk Git dan permission file aman. - Cek apakah service startup log mencetak config sensitive.
- Cek apakah CI artifact upload mengandung
.env, build secret, atau workspace penuh. - Simulasikan secret leak response: siapa dikontak, secret mana di-rotate, audit apa yang dicek?
- Buat personal checklist sebelum menjalankan command production yang memakai cloud/kubectl credentials.
25. Summary
Secure tooling practices adalah fondasi production trust. Backend engineer tidak hanya menulis code yang aman; backend engineer juga harus memakai toolchain secara aman.
Target senior engineer:
- tidak membocorkan secret lewat shell, logs, Git, CI, Docker, atau artifact,
- memahami token permission dan least privilege,
- menjaga SSH/GPG/credential helper dengan benar,
- mereview GitHub Actions sebagai executable privileged code,
- menghindari supply-chain risk dari dependency/action/plugin/tool random,
- menjaga local machine sebagai bagian dari engineering system,
- menangani leaked secret sebagai security incident,
- dan membuat secure path menjadi default dalam scripts, docs, runbooks, dan pipeline.
Dalam enterprise Java/JAX-RS system, security tidak berhenti di application code. Security juga hidup di command yang dijalankan developer, workflow yang menjalankan CI, secret yang masuk runtime, dan artifact yang dipakai production.
You just completed lesson 48 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.