Skip to content

Commit cfb4159

Browse files
committed
Add Aikido pre-commit hook feature with installation and testing scripts
1 parent e500b11 commit cfb4159

5 files changed

Lines changed: 404 additions & 0 deletions

File tree

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,52 @@ Provides the Lazydocker TUI for managing Docker containers and docker-compose wo
7373

7474
- `version` (string): Lazydocker version to install. Default: `"0.24.2"`
7575

76+
### `aikido-precommit`
77+
78+
Installs [AikidoSec's pre-commit hook](https://github.com/AikidoSec/pre-commit) for scanning secrets, passwords, and API keys before commits. Prevents accidentally committing sensitive information to repositories.
79+
80+
**Features:**
81+
82+
- Scans staged files for secrets, API keys, passwords, and sensitive data
83+
- Runs automatically on `git commit` when global hooks are configured
84+
- Supports Linux (x86_64, ARM64) and macOS (ARM64)
85+
- Lightweight binary with no runtime dependencies
86+
87+
**Usage:**
88+
89+
```jsonc
90+
{
91+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
92+
"features": {
93+
"ghcr.io/proxayfox/devcontainer-features/aikido-precommit:1": {}
94+
}
95+
}
96+
```
97+
98+
**Options:**
99+
100+
- `version` (string): Version of the aikido-local-scanner to install. Default: `"v1.0.116"`
101+
- `setupGlobalHooks` (boolean): Configure git global hooks path. Default: `true`
102+
103+
**Example:**
104+
105+
```bash
106+
# Manual scan of a repository
107+
$ aikido-local-scanner pre-commit-scan /path/to/repo
108+
109+
# Scan current repository
110+
$ aikido-local-scanner pre-commit-scan "$(git rev-parse --show-toplevel)"
111+
```
112+
76113
## Repository Structure
77114

78115
This repository follows the standard dev container Features layout:
79116

80117
```text
81118
├── src
119+
│ ├── aikido-precommit
120+
│ │ ├── devcontainer-feature.json
121+
│ │ └── install.sh
82122
│ ├── clickhouse-local
83123
│ │ ├── devcontainer-feature.json
84124
│ │ └── install.sh
@@ -88,6 +128,8 @@ This repository follows the standard dev container Features layout:
88128
├── test
89129
│ ├── _global
90130
│ │ └── common-utils.sh
131+
│ ├── aikido-precommit
132+
│ │ └── test.sh
91133
│ ├── clickhouse-local
92134
│ │ └── test.sh
93135
│ └── lazydocker

src/aikido-precommit/README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Aikido Secrets Pre-commit Hook (aikido-precommit)
2+
3+
Installs [AikidoSec's pre-commit hook](https://github.com/AikidoSec/pre-commit) for scanning secrets, passwords, and API keys before commits. This helps prevent accidentally committing sensitive information to your repositories.
4+
5+
## Features
6+
7+
- Scans staged files for secrets, API keys, passwords, and other sensitive data
8+
- Runs automatically on `git commit` when global hooks are configured
9+
- Supports Linux (x86_64, ARM64) and macOS (ARM64)
10+
- Lightweight binary with no runtime dependencies
11+
- Configurable version selection
12+
13+
## Usage
14+
15+
Add this Feature to your `devcontainer.json`:
16+
17+
```jsonc
18+
{
19+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
20+
"features": {
21+
"ghcr.io/proxayfox/devcontainer-features/aikido-precommit:1": {}
22+
}
23+
}
24+
```
25+
26+
### With Custom Options
27+
28+
```jsonc
29+
{
30+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
31+
"features": {
32+
"ghcr.io/proxayfox/devcontainer-features/aikido-precommit:1": {
33+
"version": "v1.0.116",
34+
"setupGlobalHooks": true
35+
}
36+
}
37+
}
38+
```
39+
40+
## Options
41+
42+
Option | Type | Default | Description
43+
------------------ | ------- | ---------- | ------------------------------------------------------------------
44+
`version` | string | `v1.0.116` | Version of the aikido-local-scanner to install
45+
`setupGlobalHooks` | boolean | `true` | Configure git global hooks path (set to `false` for download-only)
46+
47+
## How It Works
48+
49+
When `setupGlobalHooks` is `true` (default), the Feature:
50+
51+
1. Installs the `aikido-local-scanner` binary to `/usr/local/bin/`
52+
2. Configures `git config --global core.hooksPath` to use `/etc/git-hooks/` (or respects an existing hooks path)
53+
3. Creates a `pre-commit` hook that runs the scanner on every commit
54+
55+
When you run `git commit`, the scanner will:
56+
57+
- Analyze staged files for potential secrets
58+
- Block the commit if secrets are detected
59+
- Allow the commit to proceed if no issues are found
60+
61+
## Manual Usage
62+
63+
You can also run the scanner manually:
64+
65+
```bash
66+
# Scan a repository
67+
aikido-local-scanner pre-commit-scan /path/to/repo
68+
69+
# Scan the current repository
70+
aikido-local-scanner pre-commit-scan "$(git rev-parse --show-toplevel)"
71+
```
72+
73+
## Download-Only Mode
74+
75+
If you prefer to manage git hooks yourself, set `setupGlobalHooks` to `false`:
76+
77+
```jsonc
78+
{
79+
"features": {
80+
"ghcr.io/proxayfox/devcontainer-features/aikido-precommit:1": {
81+
"setupGlobalHooks": false
82+
}
83+
}
84+
}
85+
```
86+
87+
This installs only the binary without modifying your git configuration.
88+
89+
## Supported Platforms
90+
91+
- Linux x86_64
92+
- Linux ARM64
93+
- macOS ARM64 (Apple Silicon)
94+
95+
## Resources
96+
97+
- [AikidoSec Pre-commit Repository](https://github.com/AikidoSec/pre-commit)
98+
- [Aikido Security](https://www.aikido.dev/)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "Aikido Secrets Pre-commit Hook",
3+
"id": "aikido-precommit",
4+
"version": "1.0.0",
5+
"description": "Installs AikidoSec's pre-commit hook for scanning secrets, passwords, and API keys before commits",
6+
"documentationURL": "https://github.com/AikidoSec/pre-commit",
7+
"options": {
8+
"version": {
9+
"type": "string",
10+
"default": "v1.0.116",
11+
"description": "Version of the aikido-local-scanner to install"
12+
},
13+
"setupGlobalHooks": {
14+
"type": "boolean",
15+
"default": true,
16+
"description": "Configure git global hooks path (set to false for download-only)"
17+
}
18+
},
19+
"installsAfter": [
20+
"ghcr.io/devcontainers/features/common-utils",
21+
"ghcr.io/devcontainers/features/git"
22+
]
23+
}

src/aikido-precommit/install.sh

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Get options from environment (feature options are uppercase)
6+
VERSION="${VERSION:-"v1.0.116"}"
7+
SETUP_GLOBAL_HOOKS="${SETUPGLOBALHOOKS:-"true"}"
8+
9+
# Normalize version format (ensure it starts with 'v')
10+
if [[ ! "$VERSION" =~ ^v ]]; then
11+
VERSION="v${VERSION}"
12+
fi
13+
14+
echo "Installing Aikido pre-commit scanner version ${VERSION}..."
15+
16+
# Ensure required tools are installed
17+
export DEBIAN_FRONTEND=noninteractive
18+
19+
install_if_missing() {
20+
if ! command -v "$1" >/dev/null 2>&1; then
21+
echo "Installing $1..."
22+
apt-get update -y
23+
apt-get install -y "$2"
24+
fi
25+
}
26+
27+
install_if_missing curl curl
28+
install_if_missing unzip unzip
29+
install_if_missing git git
30+
31+
# Detect platform and architecture
32+
OS=$(uname -s)
33+
ARCH=$(uname -m)
34+
35+
case "$OS" in
36+
Linux)
37+
PLATFORM="linux"
38+
;;
39+
Darwin)
40+
PLATFORM="darwin"
41+
;;
42+
MINGW*|MSYS*|CYGWIN*)
43+
PLATFORM="windows"
44+
;;
45+
*)
46+
echo "Error: Unsupported operating system: $OS"
47+
exit 1
48+
;;
49+
esac
50+
51+
case "$ARCH" in
52+
x86_64)
53+
ARCH_NAME="X86_64"
54+
;;
55+
aarch64|arm64)
56+
ARCH_NAME="ARM64"
57+
;;
58+
*)
59+
echo "Error: Unsupported architecture: $ARCH"
60+
exit 1
61+
;;
62+
esac
63+
64+
# Construct download URL
65+
BASE_URL="https://aikido-local-scanner.s3.eu-west-1.amazonaws.com/${VERSION}"
66+
BINARY_NAME="aikido-local-scanner"
67+
DOWNLOAD_FILE="${BINARY_NAME}.zip"
68+
DOWNLOAD_URL="${BASE_URL}/${PLATFORM}_${ARCH_NAME}/${DOWNLOAD_FILE}"
69+
70+
echo "Downloading from: $DOWNLOAD_URL"
71+
72+
# Create temp directory with cleanup trap
73+
TEMP_DIR=$(mktemp -d)
74+
trap 'rm -rf "$TEMP_DIR"' EXIT
75+
76+
# Download the archive
77+
if ! curl -fsSL -o "${TEMP_DIR}/${DOWNLOAD_FILE}" "$DOWNLOAD_URL"; then
78+
echo "Error: Failed to download aikido-local-scanner from $DOWNLOAD_URL"
79+
exit 1
80+
fi
81+
82+
# Extract and install
83+
echo "Extracting aikido-local-scanner..."
84+
unzip -q "${TEMP_DIR}/${DOWNLOAD_FILE}" -d "${TEMP_DIR}"
85+
86+
# Install to /usr/local/bin (system-wide for container)
87+
INSTALL_DIR="/usr/local/bin"
88+
install -m 755 "${TEMP_DIR}/${BINARY_NAME}" "${INSTALL_DIR}/${BINARY_NAME}"
89+
90+
echo "Installed ${BINARY_NAME} to ${INSTALL_DIR}/${BINARY_NAME}"
91+
92+
# Setup global git hooks if requested
93+
if [ "$SETUP_GLOBAL_HOOKS" = "true" ]; then
94+
echo "Configuring global git hooks..."
95+
96+
# Determine hooks directory
97+
GLOBAL_HOOKS_DIR="/etc/git-hooks"
98+
99+
# Check if core.hooksPath is already set
100+
EXISTING_HOOKS_PATH=$(git config --global core.hooksPath 2>/dev/null || echo "")
101+
102+
if [ -n "$EXISTING_HOOKS_PATH" ]; then
103+
echo "Using existing hooks path: $EXISTING_HOOKS_PATH"
104+
ACTUAL_HOOKS_DIR="$EXISTING_HOOKS_PATH"
105+
else
106+
echo "Setting global hooks path to: $GLOBAL_HOOKS_DIR"
107+
git config --global core.hooksPath "$GLOBAL_HOOKS_DIR"
108+
ACTUAL_HOOKS_DIR="$GLOBAL_HOOKS_DIR"
109+
fi
110+
111+
# Create hooks directory if it doesn't exist
112+
mkdir -p "$ACTUAL_HOOKS_DIR"
113+
114+
# Create/update pre-commit hook
115+
PRECOMMIT_HOOK="${ACTUAL_HOOKS_DIR}/pre-commit"
116+
117+
# Define the Aikido hook snippet
118+
AIKIDO_HOOK_START="# --- Aikido local scanner ---"
119+
AIKIDO_HOOK_END="# --- End Aikido local scanner ---"
120+
AIKIDO_HOOK_SNIPPET="${AIKIDO_HOOK_START}
121+
[ -x \"${INSTALL_DIR}/${BINARY_NAME}\" ] || { echo \"Aikido local scanner not found at ${INSTALL_DIR}/${BINARY_NAME}\"; exit 1; }
122+
REPO_ROOT=\"\$(git rev-parse --show-toplevel)\"
123+
\"${INSTALL_DIR}/${BINARY_NAME}\" pre-commit-scan \"\$REPO_ROOT\"
124+
${AIKIDO_HOOK_END}"
125+
126+
# Check if hook file exists and if Aikido snippet is already present
127+
if [ -f "$PRECOMMIT_HOOK" ]; then
128+
if grep -q "$AIKIDO_HOOK_START" "$PRECOMMIT_HOOK"; then
129+
echo "Aikido hook already present in pre-commit, skipping..."
130+
else
131+
echo "Appending Aikido hook to existing pre-commit..."
132+
echo "" >> "$PRECOMMIT_HOOK"
133+
echo "$AIKIDO_HOOK_SNIPPET" >> "$PRECOMMIT_HOOK"
134+
fi
135+
else
136+
echo "Creating new pre-commit hook..."
137+
echo "#!/bin/sh" > "$PRECOMMIT_HOOK"
138+
echo "" >> "$PRECOMMIT_HOOK"
139+
echo "$AIKIDO_HOOK_SNIPPET" >> "$PRECOMMIT_HOOK"
140+
fi
141+
142+
# Make hook executable
143+
chmod +x "$PRECOMMIT_HOOK"
144+
145+
echo "Global pre-commit hook configured successfully!"
146+
fi
147+
148+
# Verify installation
149+
if command -v aikido-local-scanner >/dev/null 2>&1; then
150+
echo ""
151+
echo "✅ aikido-local-scanner installed successfully!"
152+
echo " Location: $(which aikido-local-scanner)"
153+
if [ "$SETUP_GLOBAL_HOOKS" = "true" ]; then
154+
echo " Global hooks: $(git config --global core.hooksPath)"
155+
fi
156+
else
157+
echo "❌ Error: aikido-local-scanner installation failed"
158+
exit 1
159+
fi

0 commit comments

Comments
 (0)