@northbridge-security/secureai 0.1.13

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.
Files changed (50) hide show
  1. package/.claude/README.md +122 -0
  2. package/.claude/commands/architect/clean.md +978 -0
  3. package/.claude/commands/architect/kiss.md +762 -0
  4. package/.claude/commands/architect/review.md +704 -0
  5. package/.claude/commands/catchup.md +90 -0
  6. package/.claude/commands/code.md +115 -0
  7. package/.claude/commands/commit.md +1218 -0
  8. package/.claude/commands/cover.md +1298 -0
  9. package/.claude/commands/fmea.md +275 -0
  10. package/.claude/commands/kaizen.md +312 -0
  11. package/.claude/commands/pr.md +503 -0
  12. package/.claude/commands/todo.md +99 -0
  13. package/.claude/commands/worktree.md +738 -0
  14. package/.claude/commands/wrapup.md +103 -0
  15. package/LICENSE +183 -0
  16. package/README.md +108 -0
  17. package/dist/cli.js +75634 -0
  18. package/docs/agents/devops-reviewer.md +889 -0
  19. package/docs/agents/kiss-simplifier.md +1088 -0
  20. package/docs/agents/typescript.md +8 -0
  21. package/docs/guides/README.md +109 -0
  22. package/docs/guides/agents.clean.arch.md +244 -0
  23. package/docs/guides/agents.clean.arch.ts.md +1314 -0
  24. package/docs/guides/agents.gotask.md +1037 -0
  25. package/docs/guides/agents.markdown.md +1209 -0
  26. package/docs/guides/agents.onepassword.md +285 -0
  27. package/docs/guides/agents.sonar.md +857 -0
  28. package/docs/guides/agents.tdd.md +838 -0
  29. package/docs/guides/agents.tdd.ts.md +1062 -0
  30. package/docs/guides/agents.typesript.md +1389 -0
  31. package/docs/guides/github-mcp.md +1075 -0
  32. package/package.json +130 -0
  33. package/packages/secureai-cli/src/cli.ts +21 -0
  34. package/tasks/README.md +880 -0
  35. package/tasks/aws.yml +64 -0
  36. package/tasks/bash.yml +118 -0
  37. package/tasks/bun.yml +738 -0
  38. package/tasks/claude.yml +183 -0
  39. package/tasks/docker.yml +420 -0
  40. package/tasks/docs.yml +127 -0
  41. package/tasks/git.yml +1336 -0
  42. package/tasks/gotask.yml +132 -0
  43. package/tasks/json.yml +77 -0
  44. package/tasks/markdown.yml +95 -0
  45. package/tasks/onepassword.yml +350 -0
  46. package/tasks/security.yml +102 -0
  47. package/tasks/sonar.yml +437 -0
  48. package/tasks/template.yml +74 -0
  49. package/tasks/vscode.yml +103 -0
  50. package/tasks/yaml.yml +121 -0
@@ -0,0 +1,183 @@
1
+ # Claude Code & MCP Task Library
2
+ # Tasks for managing Claude Code integration and MCP servers
3
+
4
+ version: "3"
5
+
6
+ tasks:
7
+ default:
8
+ desc: "Show available Claude Code tasks"
9
+ aliases: [help, h]
10
+ silent: true
11
+ cmds:
12
+ - |
13
+ # Color codes
14
+ GREEN='\033[0;32m'
15
+ YELLOW='\033[0;33m'
16
+ BOLD='\033[1m'
17
+ NC='\033[0m'
18
+
19
+ echo -e "${BOLD}Claude Code & MCP Operations${NC}"
20
+ echo ""
21
+ echo "Command Alias Description Examples"
22
+ echo "───────────────────────────────────────────────────────────────────────────────────────────────────"
23
+ echo -e "${BOLD}Settings Management:${NC}"
24
+ echo -e " ${GREEN}task claude:settings:open${NC} ${YELLOW}so${NC} Open Claude settings.json in IDE"
25
+ echo -e " ${GREEN}task claude:settings:show${NC} ${YELLOW}ss${NC} Show current Claude settings"
26
+ echo -e " ${GREEN}task claude:settings:path${NC} ${YELLOW}sp${NC} Print Claude settings file path"
27
+ echo ""
28
+ echo -e "${BOLD}MCP Server Management:${NC}"
29
+ echo -e " ${GREEN}task claude:mcp:install${NC} ${YELLOW}mi${NC} Install MCP server globally"
30
+ echo -e " ${GREEN}task claude:mcp:verify${NC} ${YELLOW}mv${NC} Verify MCP server installation"
31
+ echo -e " ${GREEN}task claude:mcp:status${NC} ${YELLOW}ms${NC} Show MCP server status"
32
+ echo -e " ${GREEN}task claude:mcp:remove${NC} ${YELLOW}mr${NC} Remove MCP server"
33
+ echo ""
34
+ echo -e "${BOLD}Installer Testing:${NC}"
35
+ echo -e " ${GREEN}task claude:installer:test${NC} ${YELLOW}it${NC} Run complete installer test suite"
36
+ echo -e " ${GREEN}task claude:installer:test:force${NC} ${YELLOW}itf${NC} Test force reinstall"
37
+ echo -e " ${GREEN}task claude:installer:test:clean${NC} ${YELLOW}itc${NC} Clean up test installations"
38
+
39
+ mcp:install:
40
+ desc: Install MCP server globally
41
+ aliases: [mi]
42
+ silent: true
43
+ cmds:
44
+ - |
45
+ # Source secrets if .env has 1Password references
46
+ if [ -f .env ] && grep -q "op://" .env 2>/dev/null; then
47
+ TEMP_ENV=$(task op:export)
48
+ source "$TEMP_ENV"
49
+ fi
50
+ bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-install.ts
51
+
52
+ mcp:verify:
53
+ desc: Verify MCP server installation
54
+ aliases: [mv]
55
+ silent: true
56
+ cmds:
57
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-verify.ts
58
+
59
+ mcp:remove:
60
+ desc: Remove MCP server
61
+ aliases: [mr]
62
+ silent: true
63
+ cmds:
64
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-remove.ts
65
+
66
+ mcp:status:
67
+ desc: Show MCP server status
68
+ aliases: [ms]
69
+ silent: true
70
+ cmds:
71
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/claude/mcp-status.ts
72
+
73
+ installer:test:
74
+ desc: Run complete installer test suite
75
+ aliases: [it]
76
+ silent: true
77
+ cmds:
78
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/claude/test-installer.ts
79
+
80
+ installer:test:force:
81
+ desc: Test force reinstall
82
+ aliases: [itf]
83
+ silent: true
84
+ cmds:
85
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/claude/test-installer.ts --force
86
+
87
+ installer:test:clean:
88
+ desc: Clean up test installations
89
+ aliases: [itc]
90
+ silent: true
91
+ cmds:
92
+ - bun run {{.TASKFILE_DIR}}/../src/tasks/claude/clean-test.ts
93
+
94
+ # Settings Management
95
+ settings:open:
96
+ desc: Open Claude settings.json in detected IDE
97
+ aliases: [so]
98
+ silent: true
99
+ cmds:
100
+ - |
101
+ # Get Claude settings path (cross-platform)
102
+ case "$(uname -s)" in
103
+ Darwin|Linux)
104
+ SETTINGS_PATH="$HOME/.claude/settings.json"
105
+ ;;
106
+ MINGW*|MSYS*|CYGWIN*)
107
+ SETTINGS_PATH="$USERPROFILE/.claude/settings.json"
108
+ ;;
109
+ *)
110
+ SETTINGS_PATH="$HOME/.claude/settings.json"
111
+ ;;
112
+ esac
113
+
114
+ # Create settings file if it doesn't exist
115
+ if [ ! -f "$SETTINGS_PATH" ]; then
116
+ mkdir -p "$(dirname "$SETTINGS_PATH")"
117
+ echo '{}' > "$SETTINGS_PATH"
118
+ echo "Created new settings file: $SETTINGS_PATH"
119
+ fi
120
+
121
+ # Use core ide:open utility
122
+ task ide:open FILE="$SETTINGS_PATH"
123
+
124
+ settings:show:
125
+ desc: Show current Claude settings
126
+ aliases: [ss]
127
+ silent: true
128
+ cmds:
129
+ - |
130
+ GREEN='\033[0;32m'
131
+ YELLOW='\033[0;33m'
132
+ CYAN='\033[0;36m'
133
+ BOLD='\033[1m'
134
+ NC='\033[0m'
135
+
136
+ # Get Claude settings path (cross-platform)
137
+ case "$(uname -s)" in
138
+ Darwin|Linux)
139
+ SETTINGS_PATH="$HOME/.claude/settings.json"
140
+ ;;
141
+ MINGW*|MSYS*|CYGWIN*)
142
+ SETTINGS_PATH="$USERPROFILE/.claude/settings.json"
143
+ ;;
144
+ *)
145
+ SETTINGS_PATH="$HOME/.claude/settings.json"
146
+ ;;
147
+ esac
148
+
149
+ echo -e "${BOLD}Claude Settings${NC}"
150
+ echo -e "${CYAN}Path:${NC} $SETTINGS_PATH"
151
+ echo ""
152
+
153
+ if [ -f "$SETTINGS_PATH" ]; then
154
+ # Pretty print JSON with jq if available, otherwise cat
155
+ if command -v jq &> /dev/null; then
156
+ jq '.' "$SETTINGS_PATH"
157
+ else
158
+ cat "$SETTINGS_PATH"
159
+ fi
160
+ else
161
+ echo -e "${YELLOW}Settings file does not exist${NC}"
162
+ echo "Run 'task claude:settings:open' to create it"
163
+ fi
164
+
165
+ settings:path:
166
+ desc: Print Claude settings file path
167
+ aliases: [sp]
168
+ silent: true
169
+ cmds:
170
+ - |
171
+ # Get Claude settings path (cross-platform)
172
+ case "$(uname -s)" in
173
+ Darwin|Linux)
174
+ SETTINGS_PATH="$HOME/.claude/settings.json"
175
+ ;;
176
+ MINGW*|MSYS*|CYGWIN*)
177
+ SETTINGS_PATH="$USERPROFILE/.claude/settings.json"
178
+ ;;
179
+ *)
180
+ SETTINGS_PATH="$HOME/.claude/settings.json"
181
+ ;;
182
+ esac
183
+ echo "$SETTINGS_PATH"
@@ -0,0 +1,420 @@
1
+ version: "3"
2
+
3
+ vars:
4
+ CONTAINER_NAME: ai-toolkit-linux-debug
5
+ COMPOSE_FILE: docker/linux-debug/docker-compose.yml
6
+ DOCKER_SOCKET: /var/run/docker.sock
7
+ TRIVY_IMAGE: aquasec/trivy:latest
8
+ DEFAULT_SEVERITY: HIGH,CRITICAL
9
+
10
+ includes:
11
+ linux:
12
+ taskfile: ../docker/linux-debug/linux.yml
13
+ dir: docker/linux-debug
14
+
15
+ tasks:
16
+ default:
17
+ desc: "Show available Docker tasks"
18
+ silent: true
19
+ cmds:
20
+ - |
21
+ GREEN='\033[0;32m'
22
+ YELLOW='\033[0;33m'
23
+ BOLD='\033[1m'
24
+ NC='\033[0m'
25
+
26
+ echo -e "${BOLD}Docker Environment Tasks${NC}"
27
+ echo ""
28
+ echo "Command Alias Description Example"
29
+ echo "─────────────────────────────────────────────────────────────────────────────────────-----------------------------"
30
+
31
+ - task: linux:help:info
32
+
33
+ - |
34
+ GREEN='\033[0;32m'
35
+ YELLOW='\033[0;33m'
36
+ BOLD='\033[1m'
37
+ NC='\033[0m'
38
+ echo ""
39
+ echo -e "${BOLD}Image Operations:${NC}"
40
+ echo -e " ${GREEN}task docker:build${NC} Build with buildx (multi-arch) IMAGE=... PATH=... [PUSH=true]"
41
+ echo -e " ${GREEN}task docker:tag${NC} Tag Docker image SOURCE=... TARGET=..."
42
+ echo -e " ${GREEN}task docker:push${NC} Push image to registry IMAGE=... TAG=..."
43
+ echo ""
44
+ echo -e "${BOLD}GitHub Container Registry:${NC}"
45
+ echo -e " ${GREEN}task docker:git:login${NC} Login to ghcr.io USER=... TOKEN=..."
46
+ echo -e " ${GREEN}task docker:git:push${NC} Push to ghcr.io IMAGE=... TAG=... USER=..."
47
+ echo ""
48
+ echo -e "${BOLD}Security Scanning:${NC}"
49
+ echo -e " ${GREEN}task docker:scan${NC} Scan image or Dockerfile IMAGE=... or FILE=..."
50
+ echo -e " ${GREEN}task docker:scan:init${NC} Initialize Trivy cache"
51
+ echo ""
52
+ echo -e "${BOLD}Examples:${NC}"
53
+ echo -e " # Test with local code (recommended)"
54
+ echo -e " task docker:linux:build && task docker:linux:test"
55
+ echo ""
56
+ echo -e " # Interactive debugging with SSH"
57
+ echo -e " task docker:linux:up"
58
+ echo -e " ssh -p 2222 developer@localhost"
59
+ echo -e " task docker:linux:down"
60
+ echo ""
61
+ echo -e " # Scan existing image by name"
62
+ echo -e " task docker:scan IMAGE=myapp TAG=v1.0.0"
63
+ echo ""
64
+ echo -e " # Build from Dockerfile and scan (config + vulnerabilities)"
65
+ echo -e " task docker:scan FILE=Dockerfile"
66
+ echo -e " task docker:scan FILE=/absolute/path/to/Dockerfile"
67
+ echo ""
68
+ echo -e " # Build and push Docker image"
69
+ echo -e " task docker:build IMAGE=myapp TAG=v1.0.0 PATH=."
70
+ echo -e " task docker:git:push IMAGE=myapp TAG=v1.0.0 USER=username TOKEN=ghp_xxx"
71
+
72
+ # Build Docker image with buildx (multi-arch support)
73
+ build:
74
+ desc: "Build Docker image with buildx (multi-arch)"
75
+ silent: true
76
+ vars:
77
+ IMAGE_NAME: '{{.IMAGE | default ""}}'
78
+ IMAGE_TAG: '{{.TAG | default "latest"}}'
79
+ DOCKER_PATH: '{{.PATH | default "."}}'
80
+ DOCKERFILE: '{{.FILE | default "Dockerfile"}}'
81
+ PLATFORM: '{{.PLATFORM | default "linux/amd64,linux/arm64"}}'
82
+ PUSH_FLAG: '{{if eq .PUSH "true"}}--push{{else}}--load{{end}}'
83
+ cmds:
84
+ - |
85
+ GREEN='\033[0;32m'
86
+ RED='\033[0;31m'
87
+ YELLOW='\033[0;33m'
88
+ NC='\033[0m'
89
+
90
+ IMAGE="{{.IMAGE_NAME}}"
91
+ TAG="{{.IMAGE_TAG}}"
92
+ CONTEXT="{{.DOCKER_PATH}}"
93
+ DOCKERFILE="{{.DOCKERFILE}}"
94
+ PLATFORM="{{.PLATFORM}}"
95
+ PUSH="{{.PUSH_FLAG}}"
96
+
97
+ # Validate parameters
98
+ if [ -z "$IMAGE" ]; then
99
+ echo -e "${RED}✗${NC} Missing IMAGE parameter" >&2
100
+ echo "Usage: task docker:build IMAGE=myapp TAG=v1.0.0 PATH=. [PLATFORM=linux/amd64,linux/arm64] [PUSH=true]" >&2
101
+ exit 1
102
+ fi
103
+
104
+ # Check Docker is running
105
+ if ! docker info &>/dev/null; then
106
+ echo -e "${RED}✗${NC} Docker is not running" >&2
107
+ exit 1
108
+ fi
109
+
110
+ # Ensure buildx builder exists
111
+ if ! docker buildx inspect multiarch-builder &>/dev/null; then
112
+ echo -e "${GREEN}▶${NC} Creating buildx builder"
113
+ docker buildx create --name multiarch-builder --use &>/dev/null
114
+ fi
115
+
116
+ # Determine output mode
117
+ # --load only works with single platform, --push works with multi-arch
118
+ if [ "$PUSH" = "--load" ]; then
119
+ # For local loading, build for current platform only
120
+ CURRENT_ARCH=$(uname -m)
121
+ case "$CURRENT_ARCH" in
122
+ x86_64) BUILD_PLATFORM="linux/amd64" ;;
123
+ arm64|aarch64) BUILD_PLATFORM="linux/arm64" ;;
124
+ *) BUILD_PLATFORM="linux/amd64" ;;
125
+ esac
126
+ echo -e "${GREEN}▶${NC} Building ${IMAGE}:${TAG} for ${BUILD_PLATFORM} (local)"
127
+ else
128
+ # For push, use full platform list
129
+ BUILD_PLATFORM="$PLATFORM"
130
+ echo -e "${GREEN}▶${NC} Building ${IMAGE}:${TAG} for ${BUILD_PLATFORM} (push)"
131
+ fi
132
+
133
+ # Build with buildx
134
+ docker buildx build \
135
+ --builder multiarch-builder \
136
+ --platform "$BUILD_PLATFORM" \
137
+ $PUSH \
138
+ -t "${IMAGE}:${TAG}" \
139
+ -f "${CONTEXT}/${DOCKERFILE}" \
140
+ "$CONTEXT"
141
+
142
+ if [ $? -eq 0 ]; then
143
+ echo -e "${GREEN}✓${NC} Built: ${IMAGE}:${TAG}"
144
+ else
145
+ echo -e "${RED}✗${NC} Build failed" >&2
146
+ exit 1
147
+ fi
148
+
149
+ # Tag Docker image
150
+ tag:
151
+ desc: "Tag Docker image"
152
+ vars:
153
+ SOURCE_IMAGE: '{{.SOURCE | default ""}}'
154
+ TARGET_IMAGE: '{{.TARGET | default ""}}'
155
+ cmds:
156
+ - |
157
+ GREEN='\033[0;32m'
158
+ RED='\033[0;31m'
159
+ NC='\033[0m'
160
+
161
+ # Validate parameters
162
+ if [ -z "{{.SOURCE_IMAGE}}" ] || [ -z "{{.TARGET_IMAGE}}" ]; then
163
+ echo -e "${RED}✗${NC} Missing SOURCE or TARGET parameter" >&2
164
+ echo "Usage: task docker:tag SOURCE=myapp:v1.0.0 TARGET=myapp:latest" >&2
165
+ exit 1
166
+ fi
167
+
168
+ # Tag image
169
+ docker tag {{.SOURCE_IMAGE}} {{.TARGET_IMAGE}}
170
+ echo -e "${GREEN}✓${NC} Tagged: {{.SOURCE_IMAGE}} → {{.TARGET_IMAGE}}"
171
+
172
+ # Push Docker image to registry
173
+ push:
174
+ desc: "Push Docker image to registry"
175
+ vars:
176
+ IMAGE_NAME: '{{.IMAGE | default ""}}'
177
+ IMAGE_TAG: '{{.TAG | default "latest"}}'
178
+ cmds:
179
+ - |
180
+ GREEN='\033[0;32m'
181
+ RED='\033[0;31m'
182
+ NC='\033[0m'
183
+
184
+ # Validate parameters
185
+ if [ -z "{{.IMAGE_NAME}}" ]; then
186
+ echo -e "${RED}✗${NC} Missing IMAGE parameter" >&2
187
+ echo "Usage: task docker:push IMAGE=myapp TAG=v1.0.0" >&2
188
+ exit 1
189
+ fi
190
+
191
+ # Push image
192
+ echo -e "${GREEN}▶${NC} Pushing {{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
193
+ docker push {{.IMAGE_NAME}}:{{.IMAGE_TAG}}
194
+ echo -e "${GREEN}✓${NC} Pushed: {{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
195
+
196
+ # Login to GitHub Container Registry
197
+ git:login:
198
+ desc: "Login to GitHub Container Registry (ghcr.io)"
199
+ vars:
200
+ GITHUB_USER: '{{.USER | default ""}}'
201
+ GITHUB_TOKEN: '{{.TOKEN | default ""}}'
202
+ cmds:
203
+ - |
204
+ GREEN='\033[0;32m'
205
+ RED='\033[0;31m'
206
+ NC='\033[0m'
207
+
208
+ # Validate parameters
209
+ if [ -z "{{.GITHUB_USER}}" ] || [ -z "{{.GITHUB_TOKEN}}" ]; then
210
+ echo -e "${RED}✗${NC} Missing USER or TOKEN parameter" >&2
211
+ echo "Usage: task docker:git:login USER=username TOKEN=ghp_xxx" >&2
212
+ exit 1
213
+ fi
214
+
215
+ # Login to ghcr.io
216
+ echo {{.GITHUB_TOKEN}} | docker login ghcr.io -u {{.GITHUB_USER}} --password-stdin &>/dev/null
217
+ echo -e "${GREEN}✓${NC} Logged in to ghcr.io as {{.GITHUB_USER}}"
218
+
219
+ # Push image to GitHub Container Registry
220
+ git:push:
221
+ desc: "Push Docker image to GitHub Container Registry"
222
+ vars:
223
+ IMAGE_NAME: '{{.IMAGE | default ""}}'
224
+ IMAGE_TAG: '{{.TAG | default "latest"}}'
225
+ GITHUB_USER: '{{.USER | default ""}}'
226
+ GITHUB_TOKEN: '{{.TOKEN | default ""}}'
227
+ PUSH_LATEST: '{{.LATEST | default "false"}}'
228
+ cmds:
229
+ - |
230
+ GREEN='\033[0;32m'
231
+ RED='\033[0;31m'
232
+ NC='\033[0m'
233
+
234
+ # Validate parameters
235
+ if [ -z "{{.IMAGE_NAME}}" ] || [ -z "{{.GITHUB_USER}}" ] || [ -z "{{.GITHUB_TOKEN}}" ]; then
236
+ echo -e "${RED}✗${NC} Missing IMAGE, USER, or TOKEN parameter" >&2
237
+ echo "Usage: task docker:git:push IMAGE=myapp TAG=v1.0.0 USER=username TOKEN=ghp_xxx" >&2
238
+ exit 1
239
+ fi
240
+
241
+ # Login to GHCR
242
+ - task: git:login
243
+ vars:
244
+ USER: "{{.GITHUB_USER}}"
245
+ TOKEN: "{{.GITHUB_TOKEN}}"
246
+
247
+ # Tag for GHCR
248
+ - task: tag
249
+ vars:
250
+ SOURCE: "{{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
251
+ TARGET: "ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:{{.IMAGE_TAG}}"
252
+
253
+ # Push tagged image
254
+ - task: push
255
+ vars:
256
+ IMAGE: "ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}"
257
+ TAG: "{{.IMAGE_TAG}}"
258
+
259
+ # Optionally push latest tag
260
+ - |
261
+ if [ '{{.PUSH_LATEST}}' = 'true' ]; then
262
+ GREEN='\033[0;32m'
263
+ NC='\033[0m'
264
+
265
+ docker tag {{.IMAGE_NAME}}:{{.IMAGE_TAG}} ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:latest
266
+ docker push ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:latest &>/dev/null
267
+ echo -e "${GREEN}✓${NC} Also pushed: ghcr.io/{{.GITHUB_USER}}/{{.IMAGE_NAME}}:latest"
268
+ fi
269
+
270
+ # Initialize Trivy cache volume
271
+ scan:init:
272
+ desc: "Initialize Trivy cache volume for vulnerability scanning"
273
+ silent: true
274
+ cmds:
275
+ - |
276
+ GREEN='\033[0;32m'
277
+ NC='\033[0m'
278
+
279
+ if ! docker volume ls --format "{{.Name}}" | grep -q "^trivy-cache$"; then
280
+ docker volume create trivy-cache &>/dev/null
281
+ echo -e "${GREEN}✓${NC} Created Trivy cache volume"
282
+ fi
283
+
284
+ # Unified security scanner - scans image by name or builds from Dockerfile
285
+ scan:
286
+ desc: "Scan Docker image or Dockerfile for vulnerabilities and misconfigurations"
287
+ silent: true
288
+ deps: [scan:init]
289
+ vars:
290
+ # Accept either IMAGE (existing image) or FILE (Dockerfile path)
291
+ IMAGE_REF: '{{.IMAGE | default ""}}'
292
+ IMAGE_TAG: '{{.TAG | default "latest"}}'
293
+ DOCKERFILE: '{{.FILE | default ""}}'
294
+ SEVERITY: "{{.SEVERITY | default .DEFAULT_SEVERITY}}"
295
+ cmds:
296
+ - |
297
+ GREEN='\033[0;32m'
298
+ RED='\033[0;31m'
299
+ YELLOW='\033[0;33m'
300
+ NC='\033[0m'
301
+
302
+ IMAGE_REF="{{.IMAGE_REF}}"
303
+ DOCKERFILE="{{.DOCKERFILE}}"
304
+ SEVERITY="{{.SEVERITY}}"
305
+ TAG="{{.IMAGE_TAG}}"
306
+
307
+ # Check Docker is running
308
+ if ! docker info &>/dev/null; then
309
+ echo -e "${RED}✗${NC} Docker is not running" >&2
310
+ exit 1
311
+ fi
312
+
313
+ # Determine scan mode
314
+ if [ -n "$IMAGE_REF" ]; then
315
+ # Mode 1: Scan existing image by name
316
+ SCAN_TARGET="${IMAGE_REF}:${TAG}"
317
+ echo -e "${GREEN}▶${NC} Scanning image ${SCAN_TARGET} for ${SEVERITY} vulnerabilities"
318
+
319
+ docker run --rm \
320
+ -v {{.DOCKER_SOCKET}}:{{.DOCKER_SOCKET}} \
321
+ -v trivy-cache:/root/.cache/trivy \
322
+ {{.TRIVY_IMAGE}} image \
323
+ --severity "$SEVERITY" \
324
+ --exit-code 1 \
325
+ "$SCAN_TARGET"
326
+
327
+ RESULT=$?
328
+
329
+ if [ $RESULT -eq 0 ]; then
330
+ echo -e "${GREEN}✓${NC} No ${SEVERITY} issues found"
331
+ else
332
+ echo -e "${YELLOW}⚠${NC} Issues found (exit code: $RESULT)"
333
+ exit $RESULT
334
+ fi
335
+
336
+ elif [ -n "$DOCKERFILE" ]; then
337
+ # Mode 2: Build from Dockerfile and scan
338
+
339
+ # Resolve to absolute path
340
+ DOCKERFILE_PATH="$DOCKERFILE"
341
+ if [[ "$DOCKERFILE_PATH" != /* ]]; then
342
+ DOCKERFILE_PATH="$(pwd)/$DOCKERFILE_PATH"
343
+ fi
344
+
345
+ # Check Dockerfile exists
346
+ if [ ! -f "$DOCKERFILE_PATH" ]; then
347
+ echo -e "${RED}✗${NC} Dockerfile not found: $DOCKERFILE_PATH" >&2
348
+ echo "Usage: task docker:scan FILE=path/to/Dockerfile" >&2
349
+ exit 1
350
+ fi
351
+
352
+ DOCKERFILE_DIR=$(dirname "$DOCKERFILE_PATH")
353
+ DOCKERFILE_NAME=$(basename "$DOCKERFILE_PATH")
354
+ TEMP_IMAGE="trivy-scan-$(date +%s)"
355
+
356
+ # Step 1: Scan Dockerfile for misconfigurations
357
+ echo -e "${GREEN}▶${NC} Scanning Dockerfile for ${SEVERITY} misconfigurations"
358
+
359
+ docker run --rm \
360
+ -v "$DOCKERFILE_DIR:/workspace:ro" \
361
+ -v trivy-cache:/root/.cache/trivy \
362
+ -w /workspace \
363
+ {{.TRIVY_IMAGE}} config \
364
+ --severity "$SEVERITY" \
365
+ --exit-code 1 \
366
+ "/workspace/$DOCKERFILE_NAME"
367
+
368
+ CONFIG_RESULT=$?
369
+ if [ $CONFIG_RESULT -ne 0 ]; then
370
+ echo -e "${YELLOW}⚠${NC} Dockerfile misconfigurations found"
371
+ fi
372
+
373
+ # Step 2: Build image for scanning
374
+ echo -e "${GREEN}▶${NC} Building image for scanning"
375
+
376
+ docker build \
377
+ -t "$TEMP_IMAGE" \
378
+ -f "$DOCKERFILE_PATH" \
379
+ "$DOCKERFILE_DIR"
380
+
381
+ BUILD_RESULT=$?
382
+ if [ $BUILD_RESULT -ne 0 ]; then
383
+ echo -e "${RED}✗${NC} Build failed" >&2
384
+ exit 1
385
+ fi
386
+
387
+ echo -e "${GREEN}✓${NC} Built image: ${TEMP_IMAGE}"
388
+
389
+ # Step 3: Scan built image for vulnerabilities
390
+ echo -e "${GREEN}▶${NC} Scanning image layers for ${SEVERITY} vulnerabilities"
391
+
392
+ docker run --rm \
393
+ -v {{.DOCKER_SOCKET}}:{{.DOCKER_SOCKET}} \
394
+ -v trivy-cache:/root/.cache/trivy \
395
+ {{.TRIVY_IMAGE}} image \
396
+ --severity "$SEVERITY" \
397
+ --exit-code 1 \
398
+ "$TEMP_IMAGE"
399
+
400
+ IMAGE_RESULT=$?
401
+
402
+ # Cleanup temporary image
403
+ docker rmi "$TEMP_IMAGE" &>/dev/null
404
+
405
+ # Combine results
406
+ if [ $CONFIG_RESULT -ne 0 ] || [ $IMAGE_RESULT -ne 0 ]; then
407
+ echo -e "${YELLOW}⚠${NC} Issues found"
408
+ exit 1
409
+ else
410
+ echo -e "${GREEN}✓${NC} No ${SEVERITY} issues found"
411
+ fi
412
+
413
+ else
414
+ echo -e "${RED}✗${NC} Missing IMAGE or FILE parameter" >&2
415
+ echo "" >&2
416
+ echo "Usage:" >&2
417
+ echo " Scan existing image: task docker:scan IMAGE=myapp TAG=v1.0.0" >&2
418
+ echo " Build and scan: task docker:scan FILE=path/to/Dockerfile" >&2
419
+ exit 1
420
+ fi