| name | workstation-security |
| description | Sikkerhetssjekk for macOS-utviklermaskiner — brannmur, SSH, Git, hemmeligheter, nettverk og Nav-plattformverktøy |
| license | MIT |
| compatibility | macOS developer workstation |
| metadata | {"domain":"auth","tags":"security macos developer-tools audit hardening"} |
Workstation Security Audit
Run these checks with run_in_terminal or bash. Report every finding with a severity (CRITICAL / HIGH / MEDIUM / INFO / PASS) and a concrete fix. Summarize results in a table at the end.
1. macOS System Security
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null
/usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode 2>/dev/null
fdesetup status 2>/dev/null
csrutil status 2>/dev/null
spctl --status 2>/dev/null
| Check | Expected | If failing | Severity |
|---|
| Firewall | enabled | System Settings → Network → Firewall | HIGH |
| Stealth mode | on | sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on | MEDIUM |
| FileVault | On | System Settings → Privacy & Security → FileVault | CRITICAL |
| SIP | enabled | Boot Recovery → csrutil enable | CRITICAL |
| Gatekeeper | assessments enabled | System Settings → Privacy & Security → Allow apps from App Store and identified developers | HIGH |
Additional OS Hardening
-
Automatic security updates — must be enabled:
softwareupdate --schedule 2>/dev/null
defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates 2>/dev/null
defaults read /Library/Preferences/com.apple.SoftwareUpdate CriticalUpdateInstall 2>/dev/null
defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload 2>/dev/null
CriticalUpdateInstall and AutomaticDownload should return 1. If not → MEDIUM. Fix: System Settings → General → Software Update → Automatic Updates.
-
Screen lock — must require password immediately:
sysadminctl -screenLock status 2>/dev/null
If not immediate → MEDIUM. Fix: System Settings → Lock Screen → Require password immediately.
-
Remote Login (SSH server) — should be off unless needed (requires admin):
sudo systemsetup -getremotelogin 2>/dev/null || echo "Requires admin — check System Settings → General → Sharing → Remote Login"
If "On" → MEDIUM. Fix: System Settings → General → Sharing → disable Remote Login.
-
Login items and LaunchAgents — review for unexpected persistence:
ls ~/Library/LaunchAgents/ 2>/dev/null
ls /Library/LaunchAgents/ 2>/dev/null
Flag unknown or suspicious entries → MEDIUM.
2. Nav Platform Security
These checks are specific to Nav developer machines connected to the NAIS platform.
Note: Only check the tools listed below. Missing optional developer tools (Copilot CLI, nav-pilot, etc.) are not security findings and should not be reported.
-
naisdevice — must be installed and healthy:
ls /Applications/naisdevice.app 2>/dev/null && echo "INSTALLED" || echo "NOT INSTALLED"
Not installed → HIGH. Fix: brew install --cask nais/tap/naisdevice.
-
Kolide agent — must be enrolled and running:
ps aux | grep -i kolide | grep -v grep | head -3
ls /private/var/kolide-k2/ 2>/dev/null
Not running → HIGH. Fix: Enroll at https://auth.kolide.com/device/registrations/new. Resolve any Kolide issues flagged in Slack.
-
GitHub CLI — check auth state:
gh auth status 2>/dev/null
Not logged in or expired → MEDIUM. Fix: gh auth login.
-
Security scanning tools — should be installed:
which trivy gitleaks zizmor 2>/dev/null
Missing tools → INFO. Fix: brew install trivy gitleaks zizmor.
-
gcloud authentication — check for active credentials:
gcloud auth list 2>/dev/null | head -5
Review active accounts — ensure only your Nav identity is active.
3. SSH Configuration
- Check
~/.ssh/ directory permissions — must be 700:
stat -f "%Sp %p" ~/.ssh 2>/dev/null
- Check private key permissions — must be
600:
find ~/.ssh -type f -name "id_*" ! -name "*.pub" -exec stat -f "%Sp %p %N" {} \;
- Check SSH key algorithm strength — weak keys are HIGH:
for key in ~/.ssh/id_*; do
[ -f "$key" ] && [[ "$key" != *.pub ]] && ssh-keygen -l -f "$key" 2>/dev/null
done
RSA < 3072 bits → HIGH. DSA → CRITICAL (deprecated). Ed25519 or ECDSA → PASS.
- SSH private keys should be encrypted — unencrypted keys are HIGH:
for key in ~/.ssh/id_*; do
if [ -f "$key" ] && [[ "$key" != *.pub ]]; then
ssh-keygen -y -P "" -f "$key" &>/dev/null && echo "Unencrypted key: $key"
fi
done
Any reported key is not encrypted. Fix: set a passphrase on the key(s), manage them in your password manager, or use a tool like Secretive.
- Check for
ForwardAgent yes — HIGH if enabled for untrusted hosts:
grep -n "ForwardAgent" ~/.ssh/config 2>/dev/null
Fix: remove ForwardAgent yes; use ssh -A <host> only when needed.
- Check for
StrictHostKeyChecking no — HIGH if set globally:
grep -n "StrictHostKeyChecking" ~/.ssh/config 2>/dev/null
4. Git Configuration
- Credential helper —
osxkeychain or manager is secure; store is HIGH (plaintext); cache is MEDIUM:
git config --global credential.helper
- Plaintext credentials — must not exist (CRITICAL):
ls -la ~/.git-credentials ~/.netrc 2>/dev/null
- Commit signing — recommended (INFO if missing):
git config --global commit.gpgsign
- TLS verification — must not be
false (CRITICAL):
git config --global http.sslVerify
- Pre-commit hooks — check for secret scanners (gitleaks, detect-secrets):
git config --global core.hooksPath
5. Credential Files
-
Sensitive files must be 600 (owner-only). Check each that exists:
for f in ~/.npmrc ~/.yarnrc.yml ~/.kube/config ~/.docker/config.json \
~/.pulumi/credentials.json ~/.terraform.d/credentials.tfrc.json \
~/.config/gh/hosts.yml ~/.aws/credentials ~/.azure/accessTokens.json \
~/.netrc; do
[ -f "$f" ] && stat -f "%Sp %N" "$f"
done
Any file with group/other read → HIGH. Fix: chmod 600 <file>.
-
Scan for plaintext tokens (CRITICAL if found):
grep -l "authToken=ghp_\|authToken=npm_\|authToken=glpat-\|_password=" ~/.npmrc 2>/dev/null
grep -l "npmAuthToken:" ~/.yarnrc.yml 2>/dev/null
grep -l "password" ~/.pypirc ~/.netrc 2>/dev/null
Fix: remove hardcoded tokens; use environment variables or credential helpers.
-
Cloud provider credentials — JSON files in ~/.config/gcloud/, ~/.aws/, ~/.azure/ should be 600:
find ~/.config/gcloud ~/.aws ~/.azure -name "*.json" -o -name "credentials" 2>/dev/null | \
xargs -I{} stat -f "%Sp %N" {} 2>/dev/null
6. Shell Configuration
- History files must be
600:
stat -f "%Sp %p" ~/.zsh_history ~/.bash_history 2>/dev/null
- History privacy — sensitive commands should be excludable (INFO if not set):
- zsh:
grep HIST_IGNORE_SPACE ~/.zshrc
- bash:
grep HISTCONTROL ~/.bashrc
- Secrets in shell profiles — scan for hardcoded API keys, tokens, passwords (HIGH if found):
grep -nE '^\s*export\s+\w*(API_KEY|SECRET|_TOKEN|PASSWORD|AWS_SECRET|GITHUB_TOKEN|NPM_TOKEN|PRIVATE_KEY)\s*=' \
~/.zshrc ~/.zprofile ~/.zshenv ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null
- Remote code execution patterns —
curl | bash in profiles (MEDIUM):
grep -nE 'curl\s.*\|\s*(ba)?sh|wget\s.*\|\s*(ba)?sh' \
~/.zshrc ~/.zprofile ~/.bashrc ~/.bash_profile 2>/dev/null
Note: eval "$(brew shellenv)" and eval "$(mise activate)" are standard and safe.
7. Network Exposure
-
Services listening on all interfaces (0.0.0.0) — flag anything unexpected (MEDIUM):
lsof -i -P -n 2>/dev/null | grep LISTEN | grep -v '127.0.0.1\|::1' | awk '{print $1, $9}' | sort -u
Known safe: rapportd (Apple Handoff), Tailscale/IPNExtension (VPN), ControlCenter (AirPlay — disable if unused).
Dev servers (node, python) on 0.0.0.0 should bind to 127.0.0.1 instead.
-
Firewall exceptions — review for stale entries:
/usr/libexec/ApplicationFirewall/socketfilterfw --listapps 2>/dev/null | head -1
Flag if >30 exceptions (INFO). Remove stale entries in System Settings → Firewall → Options.
8. Package Managers & Developer Tools
-
npm — check TLS and script settings:
npm config get strict-ssl 2>/dev/null
npm config get ignore-scripts 2>/dev/null
strict-ssl=false → HIGH (TLS disabled). ignore-scripts absent → INFO.
-
pip — check for TLS bypass:
python3 -m pip config list 2>/dev/null | grep -E 'trusted-host|index-url'
trusted-host set → HIGH (TLS bypassed). Custom index-url not pointing to pypi.org → MEDIUM.
-
Go — check checksum verification:
go env GONOSUMCHECK GONOSUMDB GOFLAGS 2>/dev/null
Non-empty GONOSUMCHECK → MEDIUM (checksum verification bypassed).
-
Docker — check for plaintext credentials:
cat ~/.docker/config.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('credHelpers:', d.get('credHelpers',{})); print('credsStore:', d.get('credsStore','')); print('auths:', list(d.get('auths',{}).keys()))" 2>/dev/null
Plaintext auth or password in auths → HIGH. Using credHelpers or credsStore → PASS.
-
Homebrew — list third-party taps for awareness:
brew tap 2>/dev/null | grep -v '^homebrew/'
Review for unexpected taps → INFO.
-
VS Code — list extensions for review:
code --list-extensions 2>/dev/null | wc -l
Review for extensions from unknown publishers → INFO.
9. Outdated Software
Outdated tools can contain known vulnerabilities. Check each package manager for pending updates.
-
Homebrew formulae — check for outdated packages:
brew outdated 2>/dev/null
Security-critical tools outdated (trivy, gitleaks, zizmor, git) → MEDIUM. Others → INFO. Fix: brew upgrade.
-
Homebrew casks — check for outdated applications:
brew outdated --cask 2>/dev/null
Outdated browsers or naisdevice → MEDIUM. Others → INFO. Fix: brew upgrade --cask.
-
npm global packages:
npm outdated -g 2>/dev/null
Outdated → INFO. Fix: npm update -g.
-
pip packages:
pip3 list --outdated 2>/dev/null
Outdated → INFO. Fix: pip3 install --upgrade <package>.
-
mise/asdf runtimes:
mise outdated 2>/dev/null
Outdated → INFO. Fix: mise upgrade.
-
macOS system updates:
softwareupdate -l 2>/dev/null
Pending security updates → MEDIUM. Other updates → INFO. Fix: softwareupdate -ia.
Report Format
Summarize all findings in a table:
| Severity | Category | Finding | Remediation |
|----------|-------------|--------------------------------------|-----------------------|
| CRITICAL | Credentials | Plaintext token in ~/.npmrc | Remove token, use env |
| HIGH | SSH | ForwardAgent enabled for 'myhost' | Remove from config |
| PASS | FileVault | Disk encryption enabled | |
End with an overall verdict: CRITICAL / HIGH / MEDIUM / GOOD based on the worst finding, and a count summary (e.g., "0 critical, 1 high, 2 medium, 18 passed").
Related
| Resource | Use For |
|---|
@security-champion | Trusselmodellering, compliance, Navs sikkerhetsarkitektur |
@security-review | Sikkerhetssjekk av kodeendringer før commit/push |
@auth-agent | JWT-validering, TokenX, ID-porten, Maskinporten |
@nais-agent | Nais-manifest, accessPolicy, hemmeligheter |
| sikkerhet.nav.no | Navs Golden Path og autoritative sikkerhetsretningslinjer |