Skip to content

Commit 1a30844

Browse files
Merge branch 'master' into feat/azure-entra-recent-signin-check
2 parents 39995b2 + 48acb3b commit 1a30844

2,504 files changed

Lines changed: 175454 additions & 77583 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "prowler-plugins",
3+
"description": "Prowler Cloud Security for Claude Code",
4+
"owner": {
5+
"name": "Prowler",
6+
"email": "support@prowler.com"
7+
},
8+
"plugins": [
9+
{
10+
"name": "prowler",
11+
"source": "./claude_plugins/prowler",
12+
"description": "Prowler for Claude Code — cloud security and compliance skills powered by the Prowler MCP server. Bundles compliance triage and remediation; more skills coming.",
13+
"category": "security",
14+
"homepage": "https://prowler.com"
15+
}
16+
]
17+
}

.config/wt.toml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@
22
# Runs automatically on `wt switch --create`.
33

44
# Block 1: setup + copy gitignored env files (.envrc, ui/.env.local)
5-
# from the primary worktree patterns selected via .worktreeinclude.
5+
# from the primary worktree - patterns selected via .worktreeinclude.
66
[[pre-start]]
77
skills = "./skills/setup.sh --claude"
8-
python = "poetry env use python3.12"
98
envs = "wt step copy-ignored"
109

11-
# Block 2: install Python deps (requires `poetry env use` from block 1).
10+
# Block 2: install Python deps (uv manages the venv on `uv sync`).
1211
[[pre-start]]
13-
deps = "poetry install --with dev"
12+
deps = "uv sync"
1413

15-
# Block 3: reminder — last visible output before `wt switch` returns.
14+
# Block 3: prepare pnpm via corepack.
15+
[[pre-start]]
16+
corepack-enable = "corepack enable"
17+
18+
[[pre-start]]
19+
corepack-install = "cd ui && corepack install"
20+
21+
# Block 4: reminder - last visible output before `wt switch` returns.
1622
# Hooks can't mutate the parent shell, so venv activation is manual.
1723
[[pre-start]]
18-
reminder = "echo '>> Reminder: activate the venv in this shell with: eval $(poetry env activate)'"
24+
reminder = "echo '>> Reminder: activate the venv in this shell with: source .venv/bin/activate'"
1925

2026
# Background: pnpm install runs while you start working.
2127
# Tail logs via `wt config state logs`.

.env

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,20 @@
66
PROWLER_UI_VERSION="stable"
77
AUTH_URL=http://localhost:3000
88
API_BASE_URL=http://prowler-api:8080/api/v1
9+
# deprecated, use UI_API_BASE_URL
910
NEXT_PUBLIC_API_BASE_URL=${API_BASE_URL}
11+
UI_API_BASE_URL=${API_BASE_URL}
12+
# deprecated, use UI_API_DOCS_URL
1013
NEXT_PUBLIC_API_DOCS_URL=http://prowler-api:8080/api/v1/docs
14+
UI_API_DOCS_URL=http://prowler-api:8080/api/v1/docs
1115
AUTH_TRUST_HOST=true
1216
UI_PORT=3000
1317
# openssl rand -base64 32
1418
AUTH_SECRET="N/c6mnaS5+SWq81+819OrzQZlmx1Vxtp/orjttJSmw8="
15-
# Google Tag Manager ID
19+
# Google Tag Manager ID (empty/unset ⇒ GTM not loaded, zero egress)
20+
# deprecated, use UI_GOOGLE_TAG_MANAGER_ID
1621
NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID=""
22+
UI_GOOGLE_TAG_MANAGER_ID=""
1723

1824
#### MCP Server ####
1925
PROWLER_MCP_VERSION=stable
@@ -139,13 +145,19 @@ DJANGO_BROKER_VISIBILITY_TIMEOUT=86400
139145
DJANGO_SENTRY_DSN=
140146
DJANGO_THROTTLE_TOKEN_OBTAIN=50/minute
141147

142-
# Sentry settings
143-
SENTRY_ENVIRONMENT=local
148+
# Sentry for the web app (server + browser). Empty/unset UI_SENTRY_DSN ⇒
149+
# Sentry disabled, zero egress. SENTRY_RELEASE (unprefixed) feeds the web app's
150+
# server/edge SDKs.
151+
UI_SENTRY_DSN=
152+
UI_SENTRY_ENVIRONMENT=local
144153
SENTRY_RELEASE=local
145-
NEXT_PUBLIC_SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT}
154+
# Reserved runtime public config (registered now; no UI consumer yet)
155+
# POSTHOG_KEY=
156+
# POSTHOG_HOST=
157+
# REO_DEV_CLIENT_ID=
146158

147159
#### Prowler release version ####
148-
NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v5.26.0
160+
NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v5.31.0
149161

150162
# Social login credentials
151163
SOCIAL_GOOGLE_OAUTH_CALLBACK_URL="${AUTH_URL}/api/auth/callback/google"

.github/CODEOWNERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# SDK
22
/* @prowler-cloud/detection-remediation
33
/prowler/ @prowler-cloud/detection-remediation
4-
/prowler/compliance/ @prowler-cloud/compliance
54
/tests/ @prowler-cloud/detection-remediation
65
/dashboard/ @prowler-cloud/detection-remediation
76
/docs/ @prowler-cloud/detection-remediation

.github/FUNDING.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# These are supported funding model platforms
2+
3+
github: [prowler-cloud]
4+
# patreon: # Replace with a single Patreon username
5+
# open_collective: # Replace with a single Open Collective username
6+
# ko_fi: # Replace with a single Ko-fi username
7+
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8+
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9+
# liberapay: # Replace with a single Liberapay username
10+
# issuehunt: # Replace with a single IssueHunt username
11+
# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12+
# polar: # Replace with a single Polar username
13+
# buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
14+
# thanks_dev: # Replace with a single thanks.dev username
15+
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
name: 'OSV-Scanner'
2+
description: 'Install osv-scanner and scan a lockfile, failing on CRITICAL severity findings. Posts/updates a PR comment with findings on pull_request events (requires pull-requests: write).'
3+
author: 'Prowler'
4+
5+
inputs:
6+
lockfile:
7+
description: 'Path to the lockfile to scan, relative to the repository root (e.g. uv.lock, api/uv.lock, ui/pnpm-lock.yaml).'
8+
required: true
9+
severity-levels:
10+
description: 'Comma-separated severity levels that fail the scan. Default: CRITICAL.'
11+
required: false
12+
default: 'CRITICAL'
13+
version:
14+
description: 'osv-scanner release tag to install. When overriding, you MUST also override binary-sha256.'
15+
required: false
16+
default: 'v2.3.8'
17+
binary-sha256:
18+
description: 'Expected SHA256 of osv-scanner_linux_amd64 for the given version. Default tracks v2.3.8. See https://github.com/google/osv-scanner/releases/download/<version>/osv-scanner_SHA256SUMS.'
19+
required: false
20+
default: 'bc98e15319ed0d515e3f9235287ba53cdc5535d576d24fd573978ecfe9ab92dc'
21+
post-pr-comment:
22+
description: 'Post or update a PR comment with the scan report. Only effective on pull_request events. Requires pull-requests: write permission on the caller job.'
23+
required: false
24+
default: 'true'
25+
26+
runs:
27+
using: 'composite'
28+
steps:
29+
- name: Install osv-scanner
30+
shell: bash
31+
env:
32+
OSV_SCANNER_VERSION: ${{ inputs.version }}
33+
# Download the binary AND the published SHA256SUMS file, then verify the
34+
# binary checksum against the upstream-signed manifest. Aborts on mismatch.
35+
run: |
36+
set -euo pipefail
37+
if command -v osv-scanner >/dev/null 2>&1; then
38+
INSTALLED="$(osv-scanner --version 2>&1 | awk '/scanner version/ {print $NF; exit}')"
39+
if [ "v${INSTALLED}" = "${OSV_SCANNER_VERSION}" ]; then
40+
echo "osv-scanner ${OSV_SCANNER_VERSION} already installed."
41+
exit 0
42+
fi
43+
fi
44+
BASE="https://github.com/google/osv-scanner/releases/download/${OSV_SCANNER_VERSION}"
45+
BIN_NAME="osv-scanner_linux_amd64"
46+
curl -fSL --retry 3 "${BASE}/${BIN_NAME}" -o "${RUNNER_TEMP}/${BIN_NAME}"
47+
curl -fSL --retry 3 "${BASE}/osv-scanner_SHA256SUMS" -o "${RUNNER_TEMP}/osv-scanner_SHA256SUMS"
48+
(cd "${RUNNER_TEMP}" && sha256sum --check --ignore-missing osv-scanner_SHA256SUMS)
49+
chmod +x "${RUNNER_TEMP}/${BIN_NAME}"
50+
sudo mv "${RUNNER_TEMP}/${BIN_NAME}" /usr/local/bin/osv-scanner
51+
rm -f "${RUNNER_TEMP}/osv-scanner_SHA256SUMS"
52+
osv-scanner --version
53+
54+
- name: Run osv-scanner
55+
id: scan
56+
shell: bash
57+
working-directory: ${{ github.workspace }}
58+
env:
59+
OSV_LOCKFILE: ${{ inputs.lockfile }}
60+
OSV_SEVERITY_LEVELS: ${{ inputs.severity-levels }}
61+
OSV_REPORT_FILE: ${{ runner.temp }}/osv-scanner-findings.json
62+
# Per-vulnerability ignores (reason + expiry) live in osv-scanner.toml at the repo root, if present.
63+
# Severity filter is enforced in the wrapper via OSV_SEVERITY_LEVELS.
64+
# `continue-on-error: true` lets the PR-comment step run even when findings exist;
65+
# the gate step below re-fails the job from the wrapper exit code.
66+
continue-on-error: true
67+
run: ./.github/scripts/osv-scan.sh --lockfile="${OSV_LOCKFILE}"
68+
69+
- name: Post osv-scanner report on PR
70+
if: >-
71+
always()
72+
&& inputs.post-pr-comment == 'true'
73+
&& github.event_name == 'pull_request'
74+
&& github.event.pull_request.head.repo.full_name == github.repository
75+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
76+
env:
77+
OSV_REPORT_FILE: ${{ runner.temp }}/osv-scanner-findings.json
78+
OSV_LOCKFILE: ${{ inputs.lockfile }}
79+
OSV_SEVERITY_LEVELS: ${{ inputs.severity-levels }}
80+
with:
81+
script: |
82+
const fs = require('fs');
83+
const lockfile = process.env.OSV_LOCKFILE;
84+
const severityLevels = process.env.OSV_SEVERITY_LEVELS;
85+
const reportFile = process.env.OSV_REPORT_FILE;
86+
const marker = `<!-- osv-scanner-report:${lockfile} -->`;
87+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
88+
89+
let findings = [];
90+
if (fs.existsSync(reportFile)) {
91+
try {
92+
findings = JSON.parse(fs.readFileSync(reportFile, 'utf8'));
93+
} catch (err) {
94+
core.warning(`Could not parse ${reportFile}: ${err.message}`);
95+
return;
96+
}
97+
}
98+
99+
const { data: comments } = await github.rest.issues.listComments({
100+
owner: context.repo.owner,
101+
repo: context.repo.repo,
102+
issue_number: context.issue.number,
103+
});
104+
const existing = comments.find(c => c.body?.includes(marker));
105+
106+
if (findings.length === 0) {
107+
if (existing) {
108+
await github.rest.issues.deleteComment({
109+
owner: context.repo.owner,
110+
repo: context.repo.repo,
111+
comment_id: existing.id,
112+
});
113+
core.info(`Deleted stale osv-scanner comment for ${lockfile}.`);
114+
} else {
115+
core.info(`No findings and no stale comment for ${lockfile}.`);
116+
}
117+
return;
118+
}
119+
120+
const sevIcon = (s) => ({
121+
CRITICAL: '🔴', HIGH: '🟠', MEDIUM: '🟡', LOW: '🟢', UNKNOWN: '⚪',
122+
}[s] || '⚪');
123+
const escape = (s) => String(s ?? '').replace(/\|/g, '\\|').replace(/\n/g, ' ');
124+
const rows = findings.map(f =>
125+
`| ${sevIcon(f.severity)} ${f.severity}${f.score ? ` (${f.score})` : ''} | \`${escape(f.id)}\` | \`${escape(f.ecosystem)}/${escape(f.package)}\` | \`${escape(f.version)}\` | ${escape(f.summary || '(no summary)')} |`
126+
);
127+
128+
const body = [
129+
marker,
130+
`## 🔒 osv-scanner: ${findings.length} finding(s) in \`${lockfile}\``,
131+
'',
132+
`Severity gate: \`${severityLevels}\``,
133+
'',
134+
'| Severity | ID | Package | Version | Summary |',
135+
'|----------|----|---------|---------|---------|',
136+
...rows,
137+
'',
138+
`To accept a finding, add an \`[[IgnoredVulns]]\` entry to \`osv-scanner.toml\` at the repo root with a reason and \`ignoreUntil\`.`,
139+
'',
140+
`<sub>[View run](${runUrl})</sub>`,
141+
].join('\n');
142+
143+
if (existing) {
144+
await github.rest.issues.updateComment({
145+
owner: context.repo.owner,
146+
repo: context.repo.repo,
147+
comment_id: existing.id,
148+
body,
149+
});
150+
core.info(`Updated osv-scanner comment for ${lockfile}.`);
151+
} else {
152+
await github.rest.issues.createComment({
153+
owner: context.repo.owner,
154+
repo: context.repo.repo,
155+
issue_number: context.issue.number,
156+
body,
157+
});
158+
core.info(`Posted new osv-scanner comment for ${lockfile}.`);
159+
}
160+
161+
- name: Enforce osv-scanner severity gate
162+
shell: bash
163+
env:
164+
SCAN_OUTCOME: ${{ steps.scan.outcome }}
165+
run: |
166+
if [ "${SCAN_OUTCOME}" != "success" ]; then
167+
echo "osv-scanner gate: scan reported findings (outcome=${SCAN_OUTCOME})" >&2
168+
exit 1
169+
fi

.github/actions/setup-python-poetry/action.yml

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)