๐ป Developer Workstation Hardening for AppSec and DevSecOps
Intro: A developer workstation is not just a laptop. It is an execution environment for code, containers, secrets, package managers, browser sessions, cloud CLIs, and signing keys. For Product Security, a compromised workstation can become source-code theft, secret leakage, poisoned artifacts, or trusted-signature abuse.
What this page includes
- secure baseline for VS Code and JetBrains users;
- pre-commit bundles for local guardrails;
- local Docker security, including rootless mode and safer defaults;
- commit signing, Cosign, and key hygiene;
- secrets hygiene and safe sandboxing patterns for labs, PoCs, and untrusted code.
The workstation threat model
A developer workstation typically has:
- access to source code and design notes;
- cloud CLIs and cached tokens;
- package registries and build tools;
- local containers and virtual machines;
- browser sessions into GitHub, GitLab, Jira, cloud consoles, and secrets systems;
- signing keys or the ability to request signatures.
That means one compromised workstation can affect:
- confidentiality of code and secrets;
- integrity of commits, tags, and release artifacts;
- trust in CI/CD and production deploys.
Recommended secure baseline
1. Separate trust zones on the same machine
Use at least two categories of environments:
- daily engineering zone โ your normal editor, browser, and tools;
- unsafe or experimental zone โ disposable VM, dev container, or remote sandbox for PoCs, unknown scripts, and exploit labs.
Do not run unfamiliar shell scripts, offensive labs, or unknown Docker images in the same environment where your long-lived cloud tokens and signing material live.
2. Prefer passkeys or phishing-resistant MFA for key portals
High-value portals include:
- GitHub / GitLab;
- cloud consoles;
- password managers;
- artifact registries;
- CI/CD admin portals;
- SSO / IdP admin interfaces.
3. Keep local admin privileges limited
The more your workstation is operated as permanent local admin/root, the easier it is for malicious scripts or poisoned packages to pivot into lasting host compromise.
VS Code setup
Recommended extensions for security feedback
- Semgrep extension for fast inline finding feedback;
- YAML / Docker / Terraform extensions only from trusted publishers;
- avoid random marketplace extensions that request broad workspace access without justification.
Semgrepโs official VS Code extension supports scanning as you open and change files, showing inline results and autofix where rules provide it. ๎cite๎turn359551search2๎
Recommended VS Code settings
{
"security.workspace.trust.enabled": true,
"extensions.autoCheckUpdates": true,
"extensions.autoUpdate": true,
"git.enableCommitSigning": true,
"files.autoSave": "off",
"terminal.integrated.confirmOnExit": "always"
}
Practical comments
- keep Workspace Trust enabled, especially when opening unfamiliar repos or extracted conference/demo material;
- do not install one-off extensions from random blog posts for parsing IaC or security files unless the publisher is trusted;
- prefer dev containers or a disposable VM when opening complex PoCs that include helper scripts.
JetBrains setup
JetBrains IDEs are strong for teams that want connected VCS hygiene and built-in Git/GPG integration.
JetBrains documents current GPG commit signing under Settings / Preferences โ Version Control โ Git โ Configure GPG Key. The 2025.3 docs explicitly recommend using a proper gpg2 setup with working pinentry support. ๎cite๎turn838320search0๎
JetBrains baseline
- enable commit signing;
- use trusted plugins only;
- review IDE HTTP client environment files and run configurations for secrets;
- avoid storing persistent credentials in run configurations checked into the repo.
Pre-commit bundle
Use a local pre-commit stack to catch the easiest issues before they ever reach CI.
Recommended first bundle
gitleaksorgit-secretsfor secrets;semgrepfor fast code and config checks;- formatting / linting hooks for YAML, JSON, Dockerfiles, and shell where relevant.
Example .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.2
hooks:
- id: gitleaks
- repo: https://github.com/returntocorp/semgrep
rev: v1.120.0
hooks:
- id: semgrep
args:
- --config=p/owasp-top-ten
- --config=p/secrets
- --config=p/terraform
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
Install
python3 -m pip install --user pre-commit
pre-commit install
pre-commit run --all-files
Git signing
Why sign commits
Commit signing does not prove code is safe, but it improves provenance and makes repo history harder to tamper with silently.
GitHub supports GPG, SSH, and S/MIME commit signature verification. The docs explicitly note that for most individual users, GPG or SSH are the most practical choices, and that SSH signing requires Git 2.34 or later. ๎cite๎turn838320search1๎turn838320search5๎
Recommended 2026 default
For many teams, SSH commit signing is now simpler than GPG for daily commits. Keep GPG for teams with existing smartcard/YubiKey workflows or policy requirements.
Example SSH signing setup
ssh-keygen -t ed25519 -C "dev-signing@example.com" -f ~/.ssh/id_ed25519_signing
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519_signing.pub
git config --global commit.gpgsign true
git config --global tag.gpgsign true
Then upload the public signing key to your Git hosting provider as a signing key, not only as an auth key.
Example GPG signing setup
gpg --full-generate-key
gpg --list-secret-keys --keyid-format=long
git config --global user.signingkey <LONG_KEY_ID>
git config --global commit.gpgsign true
git config --global tag.gpgsign true
Cosign on the workstation
Why Cosign belongs on developer workstations
Cosign is not only for CI. It is useful locally for:
- verifying the provenance of security tools you download;
- verifying signed container images;
- testing blob signing and verification before CI rollout;
- debugging attestation flows.
Sigstoreโs current docs still position Cosign as the recommended CLI for signing and verifying software artifacts. Installation options include go install, Homebrew, distro packages, GitHub Actions, GitLab, and container images. ๎cite๎turn359551search1๎turn359551search4๎
Install Cosign
# Homebrew / Linuxbrew
brew install cosign
# or Go
GO111MODULE=on go install github.com/sigstore/cosign/v3/cmd/cosign@latest
Verify a blob locally
cosign sign-blob artifact.tar.gz --bundle artifact.sigstore.json
cosign verify-blob artifact.tar.gz --bundle artifact.sigstore.json \
--certificate-identity-regexp '.*' \
--certificate-oidc-issuer https://oauth2.sigstore.dev/auth
Local Docker security
Recommended baseline
- prefer rootless Docker where compatible;
- avoid mounting
/var/run/docker.sockinto random containers; - avoid
--privilegedunless you have a short-lived, explicit reason; - do not treat local third-party images as trusted code;
- prune old images and build cache regularly.
Dockerโs current docs say rootless mode runs both the daemon and containers inside a user namespace, unlike userns-remap, where the daemon still runs as root. ๎cite๎turn359551search0๎
Rootless Docker quick setup
# prerequisites vary by distro; uidmap is typically required
sudo apt-get install -y uidmap
dockerd-rootless-setuptool.sh install
systemctl --user start docker
systemctl --user enable docker
Verify user namespace mapping
docker run --rm alpine cat /proc/self/uid_map
Safer defaults when testing images
docker run --rm -it \
--read-only \
--tmpfs /tmp:size=64m,noexec,nosuid \
--cap-drop=ALL \
--security-opt no-new-privileges \
alpine:3.20 sh
Secrets hygiene
Principles
- do not store secrets in shell history, repo files, IDE run configs, or screenshots;
- prefer federated auth and short-lived credentials over long-lived static keys;
- separate human access from automation identities;
- rotate local cloud credentials and delete stale CLI profiles.
Fast local checks
gitleaks dir .
git secrets --scan-history
Common workstation leak points
.envfiles committed accidentally;- cloud CLIs leaving cached tokens in home directories;
- IDE database/browser connectors with saved passwords;
- copied kubeconfigs shared over chat or left in screenshots;
- shell history with
export AWS_SECRET_ACCESS_KEY=....
Safe sandboxing for labs and PoCs
Good options
- disposable VM for malware-ish or offensive material;
- dev container for ordinary untrusted build/test content;
- remote throwaway cloud account or isolated lab for cloud exploitation exercises;
- separate browser profile for conference tools, demos, and disposable SaaS signups.
Bad option
Running random PoC code in the same host session where you:
- are logged into GitHub/GitLab;
- have AWS/GCP/Azure CLI tokens cached;
- have
~/.kube/configfor production clusters; - can sign commits or images.
Suggested workstation checklist
- full-disk encryption enabled
- phishing-resistant MFA for code, cloud, and SSO portals
- trusted password manager in use
- commit signing enabled
- Semgrep and secret scanning available locally
- pre-commit hooks installed in high-value repos
- Docker rootless or otherwise reduced-privilege local runtime considered
- separate sandbox for labs, PoCs, and suspicious repos
- stale cloud credentials and kubeconfigs reviewed regularly
Cross-links
- Secure Coding Training Platforms for Developers
- IDE Security Linters and Pre-Commit SAST
- Git Commit Signing and Image Signing
- Dockerfile Security Best Practices
- AppArmor and Seccomp for Docker
Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.