Files
jaandJunie ccdaf95f15 docs(security): add AppArmor, systemd sandboxing, Falco, YARA, cosign, OIDC, Ansible integration
Complete hardening workflow now covers all key technical concepts:
- AppArmor/SELinux status, systemd sandboxing audit
- Semgrep SAST, YARA malware patterns, Nuclei network scan
- Cosign artifact verification, SHA256 package verification
- Falco/eBPF runtime monitoring, Volatility 3 memory forensics
- OIDC/GAT token best practices
- Ansible integration per .clinerules/workstation.md

Co-authored-by: Junie <junie@jetbrains.com>
2026-03-24 04:35:50 +01:00

14 KiB

description, tags, last_updated, priority
description tags last_updated priority
Arch Linux workstation hardening workflow with daily, weekly, and monthly security checks based on March 2026 supply chain threat landscape.
arch-linux
hardening
security
supply-chain
workflow
2026-03-24 8

Workstation Hardening Workflow (Arch Linux)

Source: docs/tech/supply-chain-security-2026-03.md

Schedule Overview

Cadence Duration Focus
Daily 5 min Service health, network, recent changes
Weekly 15 min Package audit, SBOM scan, journal review
Monthly 30 min IOC sweep, persistence audit, credential rotation

Daily Checks (5 min)

1. Systemd Service Health

# Failed services
systemctl --failed

# Unexpected user services (CanisterWorm pgmon detection)
systemctl --user list-units --type=service --all

Alert if: Unknown services present, especially short names like pgmon.

2. Network Connections

# Established outbound connections
ss -ntu state established

# TeamPCP C2 check
ss -ntu | grep -E "45.148.10.212"

# ICP C2 check (unexpected Dfinity connections)
ss -ntu | grep -E "icp0\.io|dfinity"

Alert if: Connections to unknown external IPs, especially C2 indicators.

3. Boot Performance & Service Timing

# Boot time
systemd-analyze

# Slowest services (flag if >1s unexpected)
systemd-analyze blame | head -10

# Critical chain
systemd-analyze critical-chain

Alert if: New services in critical chain, unexpected boot time increase.

4. Recent Package Changes

# Packages changed in last 24h
pacman -Q --explicit | while read pkg ver; do
  stat -c '%Y %n' /var/lib/pacman/local/$pkg-* 2>/dev/null
done | awk '$1 > '$(date -d 'yesterday' +%s)' {print}'

Alert if: Unexpected package installations or updates.


Weekly Audit (15 min)

1. Package Orphan Cleanup

# List orphans (no longer required)
pacman -Qdt

# Remove orphans (review first)
pacman -Rns $(pacman -Qdtq)

2. npm/pnpm Audit

# Verify scripts disabled
npm config get ignore-scripts  # expect: true

# Audit all active projects
fd -t f -e json -p 'package-lock' ~/internal ~/external 2>/dev/null | while read lock; do
  dir=$(dirname "$lock")
  echo "=== $dir ==="
  (cd "$dir" && pnpm audit 2>&1 | head -20)
done

Alert if: ignore-scripts is not true, high/critical vulnerabilities.

3. SBOM Vulnerability Scan

# Generate and scan SBOM for active projects
fd -t d -p 'node_modules' ~/internal ~/external 2>/dev/null | while read dir; do
  project=$(dirname "$dir")
  echo "=== $project ==="
  syft packages dir:"$project" -o cyclonedx-json 2>/dev/null | grype sbom:/dev/stdin --fail-on high 2>&1 | tail -5
done

Alert if: High/critical CVEs in dependencies.

4. Semgrep SAST Scan

# Scan all repos for supply chain rules
fd -t d -p '.git' ~/internal ~/external 2>/dev/null | while read gitdir; do
  repo=$(dirname "$gitdir")
  echo "=== $repo ==="
  (cd "$repo" && semgrep --config p/supply-chain --config p/javascript --error 2>&1 | tail -5)
done

Alert if: Findings in eval, child_process, Buffer.from, prototype pollution.

5. SHA256 Package Verification

# Verify pacman package integrity against known-good hashes
pacman -Qk 2>&1 | grep -v "0 modified files"

# Check for package downgrade attacks
pacman -Qi linux | grep -E "Install Date|Version"

Alert if: Modified files in package, unexpected version downgrade.

6. Journal Suspicious Activity

# Last 7 days: failed auth, suspicious exec, ptrace
journalctl --since "7 days ago" -p err --no-pager | grep -iE "denied|ptrace|segfault|oom"

# Suspicious process starts from non-standard paths
journalctl --since "7 days ago" --no-pager | grep -E "ExecStart.*\.local" | grep -v "systemd"

Alert if: Repeated auth failures, ptrace from unexpected processes.


Monthly Deep Scan (30 min)

1. Unicode Injection Scan (GlassWorm)

# Scan all code repos for invisible Unicode
fd -t f -e js -e ts -e mjs -e py ~/internal ~/external 2>/dev/null | while read f; do
  # Variation Selectors (U+FE00-FE0F)
  grep -Pl "[\x{FE00}-\x{FE0F}]" "$f" 2>/dev/null && echo "VS_RANGE: $f"
  # Ideographic Variation Selectors (U+E0100-E01EF)
  grep -Pl "[\x{E0100}-\x{E01EF}]" "$f" 2>/dev/null && echo "IVS_RANGE: $f"
  # Decoder pattern
  grep -Pl "codePointAt.*0xFE00|codePointAt.*0xE0100|eval\(Buffer\.from" "$f" 2>/dev/null && echo "DECODER: $f"
done

Alert if: Any matches = immediate investigation, likely compromise.

2. Systemd Persistence Audit (CanisterWorm)

# List all user service files
ls -la ~/.config/systemd/user/

# Check for suspicious ExecStart paths (not /usr/bin or /usr/local)
grep -r "ExecStart" ~/.config/systemd/user/ 2>/dev/null | grep -v "/usr/bin\|/usr/local/bin"

# Check for worm artifacts
find ~ -maxdepth 3 -name "pgmon*" -o -name "uv-proxy" -o -name "pglog" 2>/dev/null

Alert if: Unknown services, ExecStart pointing to dotfiles or temp dirs.

3. IOC Sweep

# TeamPCP exfil repos
gh repo list --limit 100 --json name 2>/dev/null | jq -r '.[].name' | grep -i "tpcp-docs"

# DNS C2 resolution check
getent hosts scan.aquasecurtiy.org 2>/dev/null

# Known malicious extension check
code --list-extensions 2>/dev/null | grep -i "quartz.quartz"

Alert if: Any IOC matches = incident response protocol.

4. Credential Rotation Check

# npm tokens older than 90 days
npm token list 2>/dev/null

# GitHub tokens - check for long-lived PATs
gh auth status 2>/dev/null

# SSH keys - check for keys without passphrase
ssh-add -l 2>/dev/null

Action: Rotate any token older than 90 days. Enforce GAT scoping.

OIDC & Token Best Practices

Practice Implementation
OIDC over PAT Use gh auth login with browser flow, not personal access tokens
GAT scoping gh auth refresh -s repo,read:packages (minimum scopes)
npm OIDC Configure npm-provenance in CI, avoid NPM_TOKEN env vars
Short-lived tokens CI tokens max 1 hour TTL, no long-lived secrets in repos
Secret scanning Enable GitHub secret scanning + push protection

5. YARA Malware Pattern Scan

# Scan home directories with YARA rules (see source doc for rule files)
yara -r /path/to/rules/malware.yar ~/internal ~/external 2>/dev/null

# Quick inline check for known worm patterns
grep -rl "pgmon\|uv-proxy\|pglog" ~/internal ~/external 2>/dev/null
grep -rl "codePointAt.*0xFE00\|0xE0100" ~/internal ~/external 2>/dev/null

Alert if: Any YARA rule match = incident response protocol.

6. Cosign Artifact Verification

# Verify container images before use (example)
cosign verify --key cosign.pub ghcr.io/org/image:tag 2>/dev/null

# Verify with OIDC keyless
cosign verify --certificate-identity=*.satware.ai --certificate-oidc-issuer=https://token.actions.githubusercontent.com ghcr.io/org/image:tag 2>/dev/null

Alert if: Signature verification fails, do not use the artifact.

7. Nuclei Network Template Scan

# Scan local services for known vulnerabilities
nuclei -u http://localhost -t cves/ -severity high,critical -silent 2>/dev/null

# Scan specific ports
nuclei -u http://localhost:3000 -t exposures/ -silent 2>/dev/null

Alert if: High/critical template matches on local services.

8. Full SBOM Regenerate

# Regenerate SBOMs for all active projects
fd -t f -e json -p 'package-lock' ~/internal ~/external 2>/dev/null | while read lock; do
  dir=$(dirname "$lock")
  syft packages dir:"$dir" -o cyclonedx-json > "$dir/sbom.cyclonedx.json" 2>/dev/null
  grype sbom:"$dir/sbom.cyclonedx.json" --fail-on high > "$dir/grype-report.txt" 2>&1
  echo "$dir: $(grep -c 'High\|Critical' "$dir/grype-report.txt" 2>/dev/null || echo 0) findings"
done

Kernel Hardening Check (Monthly)

# Verify kernel parameters
sysctl kernel.kptr_restrict        # expect: 1 (hide kernel pointers)
sysctl kernel.dmesg_restrict       # expect: 1 (restrict dmesg)
sysctl kernel.unprivileged_bpf_disabled  # expect: 1 (restrict eBPF)
sysctl vm.mmap_min_addr            # expect: 65536 (prevent null mapping)

# Verify ASLR
cat /proc/sys/kernel/randomize_va_space  # expect: 2 (full randomization)

# Check loaded kernel modules for suspicious entries
lsmod | awk '{print $1}' | sort

# Verify IOMMU enabled (hardware memory protection)
dmesg | grep -i "DMAR\|IOMMU" | head -3

Alert if: Any parameter is 0/unset, unknown kernel modules loaded.

AppArmor/SELinux Status Check (Monthly)

# AppArmor (Arch default)
sudo aa-status 2>/dev/null | head -20

# Verify profiles are in enforce mode (not complain)
sudo aa-status 2>/dev/null | grep -c "enforce"  # should be > 0
sudo aa-status 2>/dev/null | grep "complain"     # should be empty

# If using SELinux (alternative)
getenforce 2>/dev/null  # expect: Enforcing
sestatus 2>/dev/null

Alert if: No profiles loaded, profiles in complain mode, SELinux permissive.

Systemd Sandboxing Audit (Monthly)

# Check which services lack sandboxing directives
for svc in $(systemctl list-units --type=service --state=running -q --no-pager | awk '{print $1}'); do
  has_sandbox=$(systemctl show "$svc" --property=ProtectSystem,ProtectHome,PrivateTmp,NoNewPrivileges,ReadOnlyPaths 2>/dev/null | grep -v "^$" | wc -l)
  if [ "$has_sandbox" -lt 3 ]; then
    echo "WEAK_SANDBOX: $svc ($has_sandbox directives)"
  fi
done

# Audit user services for sandboxing
systemctl --user show '*.service' --property=ProtectSystem,ProtectHome,PrivateTmp 2>/dev/null | grep -B1 "^$"

Alert if: Critical services (docker, sshd, network) lack sandboxing directives. See source doc for per-service hardening.

Runtime Monitoring (Falco/eBPF) (Ongoing)

# Check Falco daemon status (if deployed)
systemctl status falco 2>/dev/null | head -5

# Review recent Falco alerts
journalctl -u falco --since "7 days ago" --no-pager 2>/dev/null | grep -E "Warning|Critical"

# Alternative: check Tetragon if deployed
kubectl get events --field-selector type=Warning 2>/dev/null | tail -10

Alert if: Falco not running, high-severity alerts in logs. See source doc for Falco rules and Tetragon TracingPolicy YAML.

Memory Forensics (Incident Response Only)

# Create memory dump (requires elevated privileges)
sudo dd if=/dev/mem of=/tmp/memdump.raw bs=1M count=1024 2>/dev/null

# Analyze with Volatility 3
uv tool install volatility3
vol -f /tmp/memdump.raw linux.pslist 2>/dev/null
vol -f /tmp/memdump.raw linux.bash 2>/dev/null

# TeamPCP memory theft detection
vol -f /tmp/memdump.raw linux.check_syscall 2>/dev/null

# Cleanup
rm -f /tmp/memdump.raw

Use only: During active incident investigation. Requires prior setup.

Firewall Status Check (Weekly)

# Check nftables ruleset
sudo nft list ruleset 2>/dev/null | head -30

# If using ufw instead
sudo ufw status verbose 2>/dev/null

# Verify default policies (should be DROP for input)
# nftables: look for "type filter hook input priority 0; policy drop"
# ufw: look for "Default: deny (incoming)"

# Check for unexpected open ports
ss -tlnp | grep -E "LISTEN"

Alert if: Default input policy is ACCEPT, unexpected listening ports, no firewall active.

Ansible Integration

Persistent hardening changes go through ansible/ per .clinerules/workstation.md.

# Verify current hardening state
ansible-playbook ansible/workstation.yml --check

# Apply hardening changes
ansible-playbook ansible/workstation.yml

Required Ansible tasks (add to ansible/roles/common/tasks/main.yml):

  • Kernel sysctl parameters (kptr_restrict, dmesg_restrict, ASLR)
  • Firewall default policies (nftables DROP input)
  • AppArmor profile installation
  • Systemd sandboxing directives for critical services
  • ignore-scripts: true for npm config

Rule: Never apply sysctl or firewall changes manually. Always via Ansible.

Tool Installation (One-Time)

# SBOM, vulnerability scanning, artifact verification, malware patterns
pacman -S syft grype cosign yara

# AppArmor user-space tools
sudo pacman -S apparmor apparmor-profiles

# SAST with supply chain rules
uv tool install semgrep

# Network template scanning
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest

# Memory forensics (incident response)
uv tool install volatility3

# npm package risk scoring
npm install -g socket-cli

Pre-commit Hook Setup (One-Time)

Add to .pre-commit-config.yaml in each repo:

repos:
  - repo: local
    hooks:
      - id: no-invisible-unicode
        name: Block invisible Unicode (GlassWorm defense)
        entry: python3 scripts/unicode-scanner.py
        language: script
        types: [text]

Place the Unicode scanner at scripts/unicode-scanner.py (see source doc for full script).

IDE Hardening (One-Time)

VS Code settings.json:

{
  "editor.renderWhitespace": "all",
  "editor.unicodeHighlight.ambiguousCharacters": true,
  "editor.unicodeHighlight.invisibleCharacters": true
}

Incident Response Quick Reference

Indicator Action
Unknown systemd service Stop + investigate + remove
C2 IP in ss output Kill connection, firewall block, full IOC sweep
Unicode IOC in code Isolate repo, check git history, revert commit
Malicious extension Uninstall immediately, clear extension cache
npm token compromise Revoke token, rotate all tokens, audit publish log

Threat Context (March 2026)

Threat Vector Detection
TeamPCP Tag poisoning, /proc/pid/mem theft SHA pinning, Falco eBPF
CanisterWorm npm worm, systemd persistence Service audit, npm script block
GlassWorm Unicode steganography, invisible chars grep VS ranges, pre-commit hook

Full Reference

Detailed technical background, Falco rules, Tetragon policies, Semgrep rules, YARA rules, and Python scanner: docs/tech/supply-chain-security-2026-03.md