shipwright-cli 1.10.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -36
- package/completions/_shipwright +212 -32
- package/completions/shipwright.bash +97 -25
- package/docs/strategy/01-market-research.md +619 -0
- package/docs/strategy/02-mission-and-brand.md +587 -0
- package/docs/strategy/03-gtm-and-roadmap.md +759 -0
- package/docs/strategy/QUICK-START.txt +289 -0
- package/docs/strategy/README.md +172 -0
- package/package.json +4 -2
- package/scripts/sw +208 -1
- package/scripts/sw-activity.sh +500 -0
- package/scripts/sw-adaptive.sh +925 -0
- package/scripts/sw-adversarial.sh +1 -1
- package/scripts/sw-architecture-enforcer.sh +1 -1
- package/scripts/sw-auth.sh +613 -0
- package/scripts/sw-autonomous.sh +664 -0
- package/scripts/sw-changelog.sh +704 -0
- package/scripts/sw-checkpoint.sh +1 -1
- package/scripts/sw-ci.sh +602 -0
- package/scripts/sw-cleanup.sh +1 -1
- package/scripts/sw-code-review.sh +637 -0
- package/scripts/sw-connect.sh +1 -1
- package/scripts/sw-context.sh +605 -0
- package/scripts/sw-cost.sh +1 -1
- package/scripts/sw-daemon.sh +432 -130
- package/scripts/sw-dashboard.sh +1 -1
- package/scripts/sw-db.sh +540 -0
- package/scripts/sw-decompose.sh +539 -0
- package/scripts/sw-deps.sh +551 -0
- package/scripts/sw-developer-simulation.sh +1 -1
- package/scripts/sw-discovery.sh +412 -0
- package/scripts/sw-docs-agent.sh +539 -0
- package/scripts/sw-docs.sh +1 -1
- package/scripts/sw-doctor.sh +59 -1
- package/scripts/sw-dora.sh +615 -0
- package/scripts/sw-durable.sh +710 -0
- package/scripts/sw-e2e-orchestrator.sh +535 -0
- package/scripts/sw-eventbus.sh +393 -0
- package/scripts/sw-feedback.sh +471 -0
- package/scripts/sw-fix.sh +1 -1
- package/scripts/sw-fleet-discover.sh +567 -0
- package/scripts/sw-fleet-viz.sh +404 -0
- package/scripts/sw-fleet.sh +8 -1
- package/scripts/sw-github-app.sh +596 -0
- package/scripts/sw-github-checks.sh +1 -1
- package/scripts/sw-github-deploy.sh +1 -1
- package/scripts/sw-github-graphql.sh +1 -1
- package/scripts/sw-guild.sh +569 -0
- package/scripts/sw-heartbeat.sh +1 -1
- package/scripts/sw-hygiene.sh +559 -0
- package/scripts/sw-incident.sh +617 -0
- package/scripts/sw-init.sh +88 -1
- package/scripts/sw-instrument.sh +699 -0
- package/scripts/sw-intelligence.sh +1 -1
- package/scripts/sw-jira.sh +1 -1
- package/scripts/sw-launchd.sh +363 -28
- package/scripts/sw-linear.sh +1 -1
- package/scripts/sw-logs.sh +1 -1
- package/scripts/sw-loop.sh +64 -3
- package/scripts/sw-memory.sh +1 -1
- package/scripts/sw-mission-control.sh +487 -0
- package/scripts/sw-model-router.sh +545 -0
- package/scripts/sw-otel.sh +596 -0
- package/scripts/sw-oversight.sh +689 -0
- package/scripts/sw-pipeline-composer.sh +1 -1
- package/scripts/sw-pipeline-vitals.sh +1 -1
- package/scripts/sw-pipeline.sh +687 -24
- package/scripts/sw-pm.sh +693 -0
- package/scripts/sw-pr-lifecycle.sh +522 -0
- package/scripts/sw-predictive.sh +1 -1
- package/scripts/sw-prep.sh +1 -1
- package/scripts/sw-ps.sh +1 -1
- package/scripts/sw-public-dashboard.sh +798 -0
- package/scripts/sw-quality.sh +595 -0
- package/scripts/sw-reaper.sh +1 -1
- package/scripts/sw-recruit.sh +573 -0
- package/scripts/sw-regression.sh +642 -0
- package/scripts/sw-release-manager.sh +736 -0
- package/scripts/sw-release.sh +706 -0
- package/scripts/sw-remote.sh +1 -1
- package/scripts/sw-replay.sh +520 -0
- package/scripts/sw-retro.sh +691 -0
- package/scripts/sw-scale.sh +444 -0
- package/scripts/sw-security-audit.sh +505 -0
- package/scripts/sw-self-optimize.sh +1 -1
- package/scripts/sw-session.sh +1 -1
- package/scripts/sw-setup.sh +1 -1
- package/scripts/sw-standup.sh +712 -0
- package/scripts/sw-status.sh +1 -1
- package/scripts/sw-strategic.sh +658 -0
- package/scripts/sw-stream.sh +450 -0
- package/scripts/sw-swarm.sh +583 -0
- package/scripts/sw-team-stages.sh +511 -0
- package/scripts/sw-templates.sh +1 -1
- package/scripts/sw-testgen.sh +515 -0
- package/scripts/sw-tmux-pipeline.sh +554 -0
- package/scripts/sw-tmux.sh +1 -1
- package/scripts/sw-trace.sh +485 -0
- package/scripts/sw-tracker-github.sh +188 -0
- package/scripts/sw-tracker-jira.sh +172 -0
- package/scripts/sw-tracker-linear.sh +251 -0
- package/scripts/sw-tracker.sh +117 -2
- package/scripts/sw-triage.sh +603 -0
- package/scripts/sw-upgrade.sh +1 -1
- package/scripts/sw-ux.sh +677 -0
- package/scripts/sw-webhook.sh +627 -0
- package/scripts/sw-widgets.sh +530 -0
- package/scripts/sw-worktree.sh +1 -1
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
3
|
+
# ║ shipwright security-audit — Comprehensive Security Auditing ║
|
|
4
|
+
# ║ Secret detection · License checking · Vulnerability scanning · SBOM ║
|
|
5
|
+
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
|
+
|
|
9
|
+
VERSION="2.0.0"
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
|
+
|
|
13
|
+
# ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
|
|
14
|
+
CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
|
|
15
|
+
PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
|
|
16
|
+
BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
|
|
17
|
+
GREEN='\033[38;2;74;222;128m' # success
|
|
18
|
+
YELLOW='\033[38;2;250;204;21m' # warning
|
|
19
|
+
RED='\033[38;2;248;113;113m' # error
|
|
20
|
+
DIM='\033[2m'
|
|
21
|
+
BOLD='\033[1m'
|
|
22
|
+
RESET='\033[0m'
|
|
23
|
+
|
|
24
|
+
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
25
|
+
# shellcheck source=lib/compat.sh
|
|
26
|
+
[[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
|
|
27
|
+
|
|
28
|
+
# ─── Output Helpers ─────────────────────────────────────────────────────────
|
|
29
|
+
info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
|
|
30
|
+
success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
|
|
31
|
+
warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
|
|
32
|
+
error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
|
|
33
|
+
|
|
34
|
+
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
35
|
+
|
|
36
|
+
# ─── Audit State ───────────────────────────────────────────────────────────
|
|
37
|
+
FINDINGS=()
|
|
38
|
+
CRITICAL_COUNT=0
|
|
39
|
+
HIGH_COUNT=0
|
|
40
|
+
MEDIUM_COUNT=0
|
|
41
|
+
LOW_COUNT=0
|
|
42
|
+
|
|
43
|
+
# Append finding with priority
|
|
44
|
+
add_finding() {
|
|
45
|
+
local priority="$1" # CRITICAL, HIGH, MEDIUM, LOW
|
|
46
|
+
local category="$2" # secrets, licenses, vulnerabilities, permissions, network, compliance
|
|
47
|
+
local title="$3"
|
|
48
|
+
local description="$4"
|
|
49
|
+
local remediation="$5"
|
|
50
|
+
|
|
51
|
+
local color=""
|
|
52
|
+
case "$priority" in
|
|
53
|
+
CRITICAL) color="$RED"; ((CRITICAL_COUNT++)) ;;
|
|
54
|
+
HIGH) color="$RED"; ((HIGH_COUNT++)) ;;
|
|
55
|
+
MEDIUM) color="$YELLOW"; ((MEDIUM_COUNT++)) ;;
|
|
56
|
+
LOW) color="$BLUE"; ((LOW_COUNT++)) ;;
|
|
57
|
+
esac
|
|
58
|
+
|
|
59
|
+
FINDINGS+=("${priority}|${category}|${title}|${description}|${remediation}")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# ─── Secret Detection ───────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
scan_secrets() {
|
|
65
|
+
info "Scanning for hardcoded secrets..."
|
|
66
|
+
|
|
67
|
+
local patterns=(
|
|
68
|
+
"AKIA[0-9A-Z]{16}" # AWS Access Key ID
|
|
69
|
+
"aws_secret_access_key\s*=\s*['\"]?[^\s'\"]*['\"]?" # AWS Secret
|
|
70
|
+
"password\s*[=:]\s*['\"]?[^\s'\"]*['\"]?" # Generic password
|
|
71
|
+
"api[_-]?key\s*[=:]\s*['\"]?[^\s'\"]*['\"]?" # API key
|
|
72
|
+
"token\s*[=:]\s*['\"]?[^\s'\"]*['\"]?" # Generic token
|
|
73
|
+
"gh_[a-zA-Z0-9_]{36}" # GitHub token
|
|
74
|
+
"-----BEGIN RSA PRIVATE KEY-----" # RSA private key
|
|
75
|
+
"-----BEGIN PRIVATE KEY-----" # Generic private key
|
|
76
|
+
"PRIVATE KEY" # Private key marker
|
|
77
|
+
"AUTH_TOKEN" # Auth token
|
|
78
|
+
"oauth_token\s*[=:]" # OAuth token
|
|
79
|
+
"x-api-key\s*[=:]" # API key header
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
local secret_files=()
|
|
83
|
+
while IFS= read -r file; do
|
|
84
|
+
[[ -z "$file" ]] && continue
|
|
85
|
+
for pattern in "${patterns[@]}"; do
|
|
86
|
+
if grep -qEi "$pattern" "$file" 2>/dev/null; then
|
|
87
|
+
secret_files+=("$file")
|
|
88
|
+
break
|
|
89
|
+
fi
|
|
90
|
+
done
|
|
91
|
+
done < <(find "$REPO_DIR" -type f \( -name "*.sh" -o -name "*.py" -o -name "*.js" -o -name "*.json" -o -name ".env*" -o -name "*.yaml" -o -name "*.yml" \) 2>/dev/null | grep -v ".git\|node_modules\|.worktree" || true)
|
|
92
|
+
|
|
93
|
+
if [[ ${#secret_files[@]} -gt 0 ]]; then
|
|
94
|
+
for file in "${secret_files[@]}"; do
|
|
95
|
+
add_finding "CRITICAL" "secrets" "Potential hardcoded secret in $file" \
|
|
96
|
+
"Found patterns matching secret formats (AWS keys, API keys, tokens, private keys)" \
|
|
97
|
+
"Rotate credentials immediately. Remove secrets from version control. Use environment variables or secret management system instead. Use git-secrets or pre-commit hooks to prevent future leaks."
|
|
98
|
+
done
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Check for .env files in git
|
|
102
|
+
if find "$REPO_DIR" -name ".env" -type f ! -path "*/.git/*" ! -path "*/.worktree/*" 2>/dev/null | grep -q .; then
|
|
103
|
+
add_finding "HIGH" "secrets" ".env file in repository" \
|
|
104
|
+
".env files containing secrets should never be committed to version control" \
|
|
105
|
+
"Add .env to .gitignore. Use .env.example template instead. Document required variables in README."
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
local secret_count=${#secret_files[@]}
|
|
109
|
+
[[ $secret_count -eq 0 ]] && success "No obvious hardcoded secrets detected" || warn "Found $secret_count files with potential secrets"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# ─── License Compliance ─────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
scan_licenses() {
|
|
115
|
+
info "Scanning for license compliance..."
|
|
116
|
+
|
|
117
|
+
# Detect package manager
|
|
118
|
+
local has_npm=false has_pip=false has_go=false has_cargo=false
|
|
119
|
+
|
|
120
|
+
[[ -f "$REPO_DIR/package.json" ]] && has_npm=true
|
|
121
|
+
[[ -f "$REPO_DIR/requirements.txt" || -f "$REPO_DIR/setup.py" ]] && has_pip=true
|
|
122
|
+
[[ -f "$REPO_DIR/go.mod" ]] && has_go=true
|
|
123
|
+
[[ -f "$REPO_DIR/Cargo.toml" ]] && has_cargo=true
|
|
124
|
+
|
|
125
|
+
# Check npm licenses
|
|
126
|
+
if $has_npm && command -v npm &>/dev/null; then
|
|
127
|
+
while IFS= read -r line; do
|
|
128
|
+
[[ "$line" =~ GPL|AGPL ]] && [[ ! "$line" =~ MIT|Apache|BSD ]] && \
|
|
129
|
+
add_finding "MEDIUM" "licenses" "GPL/AGPL dependency in npm project" \
|
|
130
|
+
"Found GPL/AGPL licensed package: $line" \
|
|
131
|
+
"Review license compatibility. Consider alternatives with permissive licenses. Document GPL/AGPL usage."
|
|
132
|
+
done < <(npm list --depth=0 2>/dev/null | grep -i "gpl\|agpl" || true)
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# Check for LICENSES directory
|
|
136
|
+
if [[ ! -d "$REPO_DIR/LICENSES" ]]; then
|
|
137
|
+
add_finding "LOW" "licenses" "Missing LICENSES directory" \
|
|
138
|
+
"No LICENSES directory found for SPDX/license documentation" \
|
|
139
|
+
"Create LICENSES/ directory. Document all third-party licenses used. Generate with license scanner tools."
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
# Detect MIT project using GPL
|
|
143
|
+
if [[ -f "$REPO_DIR/LICENSE" ]]; then
|
|
144
|
+
if grep -qi "MIT\|Apache" "$REPO_DIR/LICENSE" 2>/dev/null; then
|
|
145
|
+
# MIT/Apache project — flag GPL dependencies
|
|
146
|
+
while IFS= read -r line; do
|
|
147
|
+
[[ "$line" =~ GPL|AGPL ]] && \
|
|
148
|
+
add_finding "HIGH" "licenses" "GPL/AGPL in permissive project" \
|
|
149
|
+
"MIT/Apache project using GPL/AGPL dependency: $line" \
|
|
150
|
+
"Replace GPL dependencies with permissive alternatives. Update LICENSE file if needed."
|
|
151
|
+
done < <(npm list 2>/dev/null | grep -i "gpl\|agpl" || true)
|
|
152
|
+
fi
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
success "License compliance check complete"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# ─── Vulnerability Scanning ────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
scan_vulnerabilities() {
|
|
161
|
+
info "Scanning for known vulnerabilities..."
|
|
162
|
+
|
|
163
|
+
local vuln_count=0
|
|
164
|
+
|
|
165
|
+
# Check npm vulnerabilities
|
|
166
|
+
if [[ -f "$REPO_DIR/package.json" ]] && command -v npm &>/dev/null; then
|
|
167
|
+
while IFS= read -r line; do
|
|
168
|
+
[[ -z "$line" ]] && continue
|
|
169
|
+
((vuln_count++))
|
|
170
|
+
add_finding "HIGH" "vulnerabilities" "npm security vulnerability" \
|
|
171
|
+
"Found npm audit issue: $line" \
|
|
172
|
+
"Run 'npm audit fix' to remediate. Update vulnerable dependencies. Re-test after updates."
|
|
173
|
+
done < <(npm audit 2>/dev/null | grep -i "vulnerability\|found" || true)
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Check pip vulnerabilities
|
|
177
|
+
if [[ -f "$REPO_DIR/requirements.txt" ]] && command -v pip &>/dev/null; then
|
|
178
|
+
if command -v safety &>/dev/null; then
|
|
179
|
+
while IFS= read -r line; do
|
|
180
|
+
[[ -z "$line" ]] && continue
|
|
181
|
+
((vuln_count++))
|
|
182
|
+
add_finding "HIGH" "vulnerabilities" "Python package vulnerability" \
|
|
183
|
+
"Found via safety: $line" \
|
|
184
|
+
"Update vulnerable package. Test compatibility. Run safety check after updates."
|
|
185
|
+
done < <(safety check 2>/dev/null || true)
|
|
186
|
+
fi
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
[[ $vuln_count -eq 0 ]] && success "No known vulnerabilities detected" || warn "Found $vuln_count vulnerabilities"
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# ─── SBOM Generation ───────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
generate_sbom() {
|
|
195
|
+
info "Generating Software Bill of Materials..."
|
|
196
|
+
|
|
197
|
+
local sbom_file="${REPO_DIR}/.claude/pipeline-artifacts/sbom.json"
|
|
198
|
+
mkdir -p "$(dirname "$sbom_file")"
|
|
199
|
+
|
|
200
|
+
local sbom='{"bomFormat":"CycloneDX","specVersion":"1.4","version":1,"components":[]}'
|
|
201
|
+
|
|
202
|
+
# Add npm packages
|
|
203
|
+
if [[ -f "$REPO_DIR/package.json" ]] && command -v npm &>/dev/null; then
|
|
204
|
+
local npm_list
|
|
205
|
+
npm_list=$(npm list --json 2>/dev/null || echo '{"dependencies":{}}')
|
|
206
|
+
while IFS='=' read -r name version; do
|
|
207
|
+
[[ -z "$name" || -z "$version" ]] && continue
|
|
208
|
+
sbom=$(echo "$sbom" | jq --arg n "$name" --arg v "$version" \
|
|
209
|
+
'.components += [{"type":"library","name":$n,"version":$v,"purl":"pkg:npm/\($n)@\($v)"}]')
|
|
210
|
+
done < <(npm list --depth=0 --json 2>/dev/null | jq -r '.dependencies | to_entries[] | "\(.key)=\(.value.version)"' || true)
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# Add git commit info
|
|
214
|
+
local commit=""
|
|
215
|
+
[[ -d "$REPO_DIR/.git" ]] && commit=$(cd "$REPO_DIR" && git rev-parse HEAD 2>/dev/null || echo "unknown")
|
|
216
|
+
sbom=$(echo "$sbom" | jq --arg c "$commit" '.metadata.component.commit = $c')
|
|
217
|
+
|
|
218
|
+
# Write SBOM
|
|
219
|
+
echo "$sbom" | jq . > "$sbom_file" 2>/dev/null || true
|
|
220
|
+
|
|
221
|
+
success "SBOM generated: $sbom_file"
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# ─── Permissions Audit ──────────────────────────────────────────────────────
|
|
225
|
+
|
|
226
|
+
audit_permissions() {
|
|
227
|
+
info "Auditing file permissions..."
|
|
228
|
+
|
|
229
|
+
# Check for world-writable files
|
|
230
|
+
while IFS= read -r file; do
|
|
231
|
+
[[ -z "$file" ]] && continue
|
|
232
|
+
add_finding "MEDIUM" "permissions" "World-writable file: $file" \
|
|
233
|
+
"File has overly permissive permissions (mode ending in 2 or 7)" \
|
|
234
|
+
"Run: chmod o-w \"$file\" to remove world-writable bit"
|
|
235
|
+
done < <(find "$REPO_DIR" -type f -perm -002 ! -path "*/.git/*" ! -path "*/.worktree/*" 2>/dev/null || true)
|
|
236
|
+
|
|
237
|
+
# Check for setuid/setgid binaries
|
|
238
|
+
while IFS= read -r file; do
|
|
239
|
+
[[ -z "$file" ]] && continue
|
|
240
|
+
add_finding "HIGH" "permissions" "setuid/setgid binary: $file" \
|
|
241
|
+
"Binary has setuid or setgid bit set" \
|
|
242
|
+
"Review necessity. Remove if not essential. Audit access controls."
|
|
243
|
+
done < <(find "$REPO_DIR" -type f \( -perm -4000 -o -perm -2000 \) ! -path "*/.git/*" 2>/dev/null || true)
|
|
244
|
+
|
|
245
|
+
# Check for readable private keys
|
|
246
|
+
while IFS= read -r file; do
|
|
247
|
+
[[ -z "$file" ]] && continue
|
|
248
|
+
add_finding "CRITICAL" "permissions" "Readable private key: $file" \
|
|
249
|
+
"Private key file has permissive read permissions" \
|
|
250
|
+
"Run: chmod 600 \"$file\" immediately. Rotate the key. Audit access logs."
|
|
251
|
+
done < <(find "$REPO_DIR" -type f \( -name "*.pem" -o -name "*.key" -o -name "id_rsa" \) ! -path "*/.git/*" 2>/dev/null | while read -r f; do
|
|
252
|
+
[[ $(stat -f%A "$f" 2>/dev/null || stat -c%a "$f" 2>/dev/null) =~ [^0].. ]] && echo "$f"
|
|
253
|
+
done || true)
|
|
254
|
+
|
|
255
|
+
success "Permissions audit complete"
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
# ─── Network Exposure Analysis ─────────────────────────────────────────────
|
|
259
|
+
|
|
260
|
+
analyze_network() {
|
|
261
|
+
info "Analyzing network exposure..."
|
|
262
|
+
|
|
263
|
+
local urls_found=()
|
|
264
|
+
|
|
265
|
+
# Find external network calls
|
|
266
|
+
while IFS= read -r line; do
|
|
267
|
+
[[ -z "$line" ]] && continue
|
|
268
|
+
if [[ "$line" =~ http://|https://|curl|wget ]]; then
|
|
269
|
+
urls_found+=("$line")
|
|
270
|
+
fi
|
|
271
|
+
done < <(grep -r "http\|curl\|wget\|socket\|fetch\|request" "$REPO_DIR/scripts/" "$REPO_DIR/src/" 2>/dev/null | grep -v ".git\|.worktree\|Binary" || true)
|
|
272
|
+
|
|
273
|
+
if [[ ${#urls_found[@]} -gt 0 ]]; then
|
|
274
|
+
info "Found ${#urls_found[@]} network-related operations"
|
|
275
|
+
for line in "${urls_found[@]}"; do
|
|
276
|
+
warn " $line"
|
|
277
|
+
done
|
|
278
|
+
|
|
279
|
+
add_finding "MEDIUM" "network" "External network calls detected" \
|
|
280
|
+
"Script makes external API/network calls. Found ${#urls_found[@]} references." \
|
|
281
|
+
"Audit all network calls. Ensure TLS/HTTPS. Validate certificates. Log network activity."
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
success "Network exposure analysis complete"
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
# ─── Compliance Report ──────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
generate_compliance_report() {
|
|
290
|
+
info "Generating compliance report..."
|
|
291
|
+
|
|
292
|
+
local report_file="${REPO_DIR}/.claude/pipeline-artifacts/security-compliance-report.md"
|
|
293
|
+
mkdir -p "$(dirname "$report_file")"
|
|
294
|
+
|
|
295
|
+
cat > "$report_file" <<'EOF'
|
|
296
|
+
# Security Compliance Report
|
|
297
|
+
|
|
298
|
+
## SOC2 Checklist
|
|
299
|
+
|
|
300
|
+
### CC (Common Criteria)
|
|
301
|
+
- [ ] CC1: Risk Assessment completed
|
|
302
|
+
- [ ] CC2: Management objectives and responsibilities defined
|
|
303
|
+
- [ ] CC3: Communication of objectives and responsibilities
|
|
304
|
+
- [ ] CC4: Information security culture established
|
|
305
|
+
- [ ] CC5: Roles and responsibilities assigned
|
|
306
|
+
- [ ] CC6: Segregation of duties enforced
|
|
307
|
+
- [ ] CC7: Human resources policies and procedures
|
|
308
|
+
- [ ] CC8: Competence of personnel
|
|
309
|
+
- [ ] CC9: Accountability assigned
|
|
310
|
+
|
|
311
|
+
### C (Criteria)
|
|
312
|
+
- [ ] C1.1: Authorization and access controls
|
|
313
|
+
- [ ] C1.2: Change management procedures
|
|
314
|
+
- [ ] C2.1: System monitoring
|
|
315
|
+
- [ ] C2.2: Monitoring of systems and applications
|
|
316
|
+
- [ ] C3.1: Logical access controls
|
|
317
|
+
- [ ] C3.2: Physical access controls
|
|
318
|
+
- [ ] C4.1: Risk assessment documentation
|
|
319
|
+
- [ ] C5.1: Incident identification and reporting
|
|
320
|
+
- [ ] C6.1: Vulnerability identification and remediation
|
|
321
|
+
- [ ] C7.1: Availability and performance monitoring
|
|
322
|
+
|
|
323
|
+
## ISO 27001 Controls
|
|
324
|
+
|
|
325
|
+
### A.5 - Organizational Controls
|
|
326
|
+
- [ ] A.5.1: Management commitment to security
|
|
327
|
+
- [ ] A.5.2: Security policy established
|
|
328
|
+
- [ ] A.5.3: Allocation of information security responsibilities
|
|
329
|
+
|
|
330
|
+
### A.6 - Personnel Controls
|
|
331
|
+
- [ ] A.6.1: Confidentiality or non-disclosure agreements
|
|
332
|
+
- [ ] A.6.2: Information security awareness training
|
|
333
|
+
- [ ] A.6.3: Procedures for third-party access
|
|
334
|
+
|
|
335
|
+
### A.7 - Physical and Environmental Controls
|
|
336
|
+
- [ ] A.7.1: Perimeter security
|
|
337
|
+
- [ ] A.7.2: Entry controls
|
|
338
|
+
- [ ] A.7.3: Workspace security
|
|
339
|
+
|
|
340
|
+
### A.8 - Technical Controls
|
|
341
|
+
- [ ] A.8.1: Access control policies
|
|
342
|
+
- [ ] A.8.2: Cryptography usage
|
|
343
|
+
- [ ] A.8.3: Malware protection
|
|
344
|
+
|
|
345
|
+
## GDPR Compliance
|
|
346
|
+
|
|
347
|
+
- [ ] Data inventory completed
|
|
348
|
+
- [ ] Data processing agreements in place
|
|
349
|
+
- [ ] Data subject rights procedures
|
|
350
|
+
- [ ] Data breach notification plan
|
|
351
|
+
- [ ] Privacy by design implemented
|
|
352
|
+
- [ ] Data retention policy defined
|
|
353
|
+
|
|
354
|
+
## Findings Summary
|
|
355
|
+
|
|
356
|
+
| Priority | Count |
|
|
357
|
+
|----------|-------|
|
|
358
|
+
| CRITICAL | 0 |
|
|
359
|
+
| HIGH | 0 |
|
|
360
|
+
| MEDIUM | 0 |
|
|
361
|
+
| LOW | 0 |
|
|
362
|
+
|
|
363
|
+
EOF
|
|
364
|
+
|
|
365
|
+
success "Compliance report generated: $report_file"
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
# ─── Unified Full Scan ──────────────────────────────────────────────────────
|
|
369
|
+
|
|
370
|
+
run_full_scan() {
|
|
371
|
+
echo ""
|
|
372
|
+
echo -e "${CYAN}${BOLD}╔═════════════════════════════════════════════════════════════╗${RESET}"
|
|
373
|
+
echo -e "${CYAN}${BOLD}║ SHIPWRIGHT SECURITY AUDIT${RESET}"
|
|
374
|
+
echo -e "${CYAN}${BOLD}║ Repo: $(basename "$REPO_DIR")${RESET}"
|
|
375
|
+
echo -e "${CYAN}${BOLD}╚═════════════════════════════════════════════════════════════╝${RESET}"
|
|
376
|
+
echo ""
|
|
377
|
+
|
|
378
|
+
scan_secrets
|
|
379
|
+
echo ""
|
|
380
|
+
scan_licenses
|
|
381
|
+
echo ""
|
|
382
|
+
scan_vulnerabilities
|
|
383
|
+
echo ""
|
|
384
|
+
generate_sbom
|
|
385
|
+
echo ""
|
|
386
|
+
audit_permissions
|
|
387
|
+
echo ""
|
|
388
|
+
analyze_network
|
|
389
|
+
echo ""
|
|
390
|
+
generate_compliance_report
|
|
391
|
+
echo ""
|
|
392
|
+
|
|
393
|
+
# Print findings summary
|
|
394
|
+
print_findings_summary
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
# ─── Print Findings ────────────────────────────────────────────────────────
|
|
398
|
+
|
|
399
|
+
print_findings_summary() {
|
|
400
|
+
echo -e "${CYAN}${BOLD}╔═════════════════════════════════════════════════════════════╗${RESET}"
|
|
401
|
+
echo -e "${CYAN}${BOLD}║ FINDINGS SUMMARY${RESET}"
|
|
402
|
+
echo -e "${CYAN}${BOLD}╚═════════════════════════════════════════════════════════════╝${RESET}"
|
|
403
|
+
echo ""
|
|
404
|
+
|
|
405
|
+
echo -e " ${RED}${BOLD}CRITICAL:${RESET} $CRITICAL_COUNT"
|
|
406
|
+
echo -e " ${RED}${BOLD}HIGH:${RESET} $HIGH_COUNT"
|
|
407
|
+
echo -e " ${YELLOW}${BOLD}MEDIUM:${RESET} $MEDIUM_COUNT"
|
|
408
|
+
echo -e " ${BLUE}${BOLD}LOW:${RESET} $LOW_COUNT"
|
|
409
|
+
echo ""
|
|
410
|
+
|
|
411
|
+
if [[ ${#FINDINGS[@]} -eq 0 ]]; then
|
|
412
|
+
success "No security findings detected!"
|
|
413
|
+
return 0
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
# Sort and display findings
|
|
417
|
+
for finding in "${FINDINGS[@]}"; do
|
|
418
|
+
IFS='|' read -r priority category title description remediation <<< "$finding"
|
|
419
|
+
|
|
420
|
+
local color=""
|
|
421
|
+
case "$priority" in
|
|
422
|
+
CRITICAL) color="$RED" ;;
|
|
423
|
+
HIGH) color="$RED" ;;
|
|
424
|
+
MEDIUM) color="$YELLOW" ;;
|
|
425
|
+
LOW) color="$BLUE" ;;
|
|
426
|
+
esac
|
|
427
|
+
|
|
428
|
+
echo -e "${color}${BOLD}[$priority]${RESET} $title"
|
|
429
|
+
echo -e " ${DIM}Category: $category${RESET}"
|
|
430
|
+
echo -e " ${DIM}Issue: $description${RESET}"
|
|
431
|
+
echo -e " ${GREEN}Remediation: $remediation${RESET}"
|
|
432
|
+
echo ""
|
|
433
|
+
done
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
# ─── Help ───────────────────────────────────────────────────────────────────
|
|
437
|
+
|
|
438
|
+
show_help() {
|
|
439
|
+
echo -e "${CYAN}${BOLD}shipwright security-audit${RESET} ${DIM}v${VERSION}${RESET} — Comprehensive Security Auditing"
|
|
440
|
+
echo ""
|
|
441
|
+
echo -e "${BOLD}USAGE${RESET}"
|
|
442
|
+
echo -e " ${CYAN}shipwright security-audit${RESET} [command]"
|
|
443
|
+
echo ""
|
|
444
|
+
echo -e "${BOLD}COMMANDS${RESET}"
|
|
445
|
+
echo -e " ${CYAN}scan${RESET} Full security scan (all checks)"
|
|
446
|
+
echo -e " ${CYAN}secrets${RESET} Secret detection scan"
|
|
447
|
+
echo -e " ${CYAN}licenses${RESET} License compliance check"
|
|
448
|
+
echo -e " ${CYAN}vulnerabilities${RESET} Vulnerability scan"
|
|
449
|
+
echo -e " ${CYAN}sbom${RESET} Generate Software Bill of Materials"
|
|
450
|
+
echo -e " ${CYAN}permissions${RESET} File permissions audit"
|
|
451
|
+
echo -e " ${CYAN}network${RESET} Network exposure analysis"
|
|
452
|
+
echo -e " ${CYAN}report${RESET} Generate compliance report"
|
|
453
|
+
echo -e " ${CYAN}help${RESET} Show this help message"
|
|
454
|
+
echo ""
|
|
455
|
+
echo -e "${BOLD}EXAMPLES${RESET}"
|
|
456
|
+
echo -e " ${DIM}shipwright security-audit scan${RESET}"
|
|
457
|
+
echo -e " ${DIM}shipwright security-audit secrets${RESET}"
|
|
458
|
+
echo -e " ${DIM}shipwright security-audit licenses --json${RESET}"
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
# ─── Source Guard ──────────────────────────────────────────────────────────
|
|
462
|
+
|
|
463
|
+
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
464
|
+
cmd="${1:-help}"
|
|
465
|
+
|
|
466
|
+
case "$cmd" in
|
|
467
|
+
scan)
|
|
468
|
+
run_full_scan
|
|
469
|
+
;;
|
|
470
|
+
secrets)
|
|
471
|
+
scan_secrets
|
|
472
|
+
print_findings_summary
|
|
473
|
+
;;
|
|
474
|
+
licenses)
|
|
475
|
+
scan_licenses
|
|
476
|
+
print_findings_summary
|
|
477
|
+
;;
|
|
478
|
+
vulnerabilities)
|
|
479
|
+
scan_vulnerabilities
|
|
480
|
+
print_findings_summary
|
|
481
|
+
;;
|
|
482
|
+
sbom)
|
|
483
|
+
generate_sbom
|
|
484
|
+
;;
|
|
485
|
+
permissions)
|
|
486
|
+
audit_permissions
|
|
487
|
+
print_findings_summary
|
|
488
|
+
;;
|
|
489
|
+
network)
|
|
490
|
+
analyze_network
|
|
491
|
+
print_findings_summary
|
|
492
|
+
;;
|
|
493
|
+
report)
|
|
494
|
+
generate_compliance_report
|
|
495
|
+
;;
|
|
496
|
+
help|--help|-h)
|
|
497
|
+
show_help
|
|
498
|
+
;;
|
|
499
|
+
*)
|
|
500
|
+
error "Unknown command: $cmd"
|
|
501
|
+
show_help
|
|
502
|
+
exit 1
|
|
503
|
+
;;
|
|
504
|
+
esac
|
|
505
|
+
fi
|
package/scripts/sw-session.sh
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# ║ Supports --template to scaffold from a team template and --terminal ║
|
|
9
9
|
# ║ to select a terminal adapter (tmux, iterm2, wezterm). ║
|
|
10
10
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
11
|
-
VERSION="
|
|
11
|
+
VERSION="2.0.0"
|
|
12
12
|
set -euo pipefail
|
|
13
13
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
14
14
|
|