Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,25 @@ pensar status <scan-id>

### Options

| Option | Description |
| ------------------- | ----------------------------------------------------- |
| `-p, --project` | Project ID (or set `PENSAR_PROJECT_ID`) |
| `-b, --branch` | Branch to pentest |
| `-l, --level` | Pentest level: `priority` or `full` |
| `-e, --environment` | Target environment: `dev`, `staging`, or `production` |
| `--no-wait` | Don't wait for pentest to complete |
| Option | Description |
| ------------------- | --------------------------------------------------------------------------- |
| `-p, --project` | Project ID (or set `PENSAR_PROJECT_ID`) |
| `-b, --branch` | Branch to pentest |
| `-l, --level` | Pentest level: `priority` or `full` |
| `-e, --environment` | Target environment: `dev`, `staging`, or `production` |
| `-c, --commit` | Commit SHA (auto-detected from CI env vars, or set `PENSAR_COMMIT_SHA`) |
| `-s, --severity` | Minimum severity threshold to error on (or set `PENSAR_ERROR_SEVERITY_THRESHOLD`) |
| `--no-wait` | Don't wait for pentest to complete |

## Environment Variables

| Variable | Description |
| -------------------- | ------------------------------------------------------ |
| `PENSAR_API_KEY` | Your Pensar API key |
| `PENSAR_PROJECT_ID` | Your Pensar project ID |
| `PENSAR_ENVIRONMENT` | Target environment (`dev`, `staging`, or `production`) |
| Variable | Description |
| -------------------------------- | ------------------------------------------------------ |
| `PENSAR_API_KEY` | Your Pensar API key |
| `PENSAR_PROJECT_ID` | Your Pensar project ID |
| `PENSAR_ENVIRONMENT` | Target environment (`dev`, `staging`, or `production`) |
| `PENSAR_COMMIT_SHA` | Commit SHA override (auto-detected from `GITHUB_SHA`, `CI_COMMIT_SHA`, `BITBUCKET_COMMIT`) |
| `PENSAR_ERROR_SEVERITY_THRESHOLD`| Minimum severity to trigger a non-zero exit (`critical`, `high`, `medium`, `low`, `info`) |

## CI/CD Integration

Expand Down
5 changes: 5 additions & 0 deletions src/bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ program
.option("-l, --level <level>", "Pentest level: priority or full", "full")
.option("--no-wait", "Don't wait for pentest to complete")
.option("-e, --environment <env>", "Environment: dev, staging, or production")
.option(
"-c, --commit <sha>",
"Commit SHA (auto-detected from GITHUB_SHA, CI_COMMIT_SHA, BITBUCKET_COMMIT, or PENSAR_COMMIT_SHA)"
)
.option(
"-s, --severity <severity>",
"Minimum severity threshold to trigger error (critical, high, medium, low, info). Or set PENSAR_ERROR_SEVERITY_THRESHOLD env var.",
Expand Down Expand Up @@ -48,6 +52,7 @@ program
wait: options.wait,
environment: options.environment as Environment | undefined,
errorSeverityThreshold: severityThreshold,
commitSha: options.commit,
});

if (result.status === "completed") {
Expand Down
15 changes: 15 additions & 0 deletions src/lib/ci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ export function getEnvironmentEnvVar(): Environment {
return (process.env.PENSAR_ENVIRONMENT as Environment) ?? null;
}

export function getCommitShaEnvVar(): string | undefined {
return (
process.env.GITHUB_SHA ??
process.env.CI_COMMIT_SHA ??
process.env.BITBUCKET_COMMIT ??
process.env.PENSAR_COMMIT_SHA ??
undefined
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PENSAR_COMMIT_SHA override has lowest priority instead of highest

High Severity

PENSAR_COMMIT_SHA is documented as a "Commit SHA override" in the README, but in getCommitShaEnvVar() it's checked last in the ?? chain — after GITHUB_SHA, CI_COMMIT_SHA, and BITBUCKET_COMMIT. Since those CI-specific env vars are always set automatically in their respective CI platforms, PENSAR_COMMIT_SHA can never take effect, making it impossible for users to override the commit SHA via env var.

Additional Locations (1)

Fix in Cursor Fix in Web


export function getErrorSeverityThresholdEnvVar(): SeverityLevel {
const value = process.env.PENSAR_ERROR_SEVERITY_THRESHOLD;
if (!value) return 'critical'; // Default to critical
Expand Down Expand Up @@ -123,6 +133,7 @@ export interface DispatchScanParams {
branch?: string;
scanLevel?: "priority" | "full";
environment?: Environment;
commitSha?: string;
}

export async function dispatchScan(
Expand All @@ -148,6 +159,7 @@ export async function dispatchScan(
: { repoId: params.repoId }),
branch: params.branch,
scanLevel: params.scanLevel,
commitSha: params.commitSha,
}),
});

Expand Down Expand Up @@ -249,6 +261,7 @@ export interface RunScanParams {
wait?: boolean;
pollIntervalMs?: number;
errorSeverityThreshold?: SeverityLevel;
commitSha?: string;
}

export async function runScan(params: RunScanParams = {}): Promise<ScanStatus> {
Expand All @@ -257,6 +270,7 @@ export async function runScan(params: RunScanParams = {}): Promise<ScanStatus> {
const repoId = params.repoId ?? getRepoIdEnvVar();
const environment = params.environment ?? getEnvironmentEnvVar();
const wait = params.wait ?? true;
const commitSha = params.commitSha ?? getCommitShaEnvVar();

if (!projectId && !repoId) {
throw new Error(
Expand All @@ -274,6 +288,7 @@ export async function runScan(params: RunScanParams = {}): Promise<ScanStatus> {
branch: params.branch,
scanLevel: params.scanLevel,
environment,
commitSha,
});

console.log(`Pentest ${label} dispatched (ID: ${scanId})`);
Expand Down
7 changes: 6 additions & 1 deletion src/lib/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ function getGitLabEnvVars() {
// GitLab CI provides the branch name in CI_COMMIT_REF_NAME
const branch = process.env.CI_COMMIT_REF_NAME ?? undefined;

// GitLab CI provides the commit SHA in CI_COMMIT_SHA
const commitSha = process.env.CI_COMMIT_SHA ?? undefined;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitLab bypasses centralized commit SHA resolution

Medium Severity

The GitLab integration reads CI_COMMIT_SHA directly and passes it explicitly as commitSha to CI.runScan(). Since runScan() uses params.commitSha ?? getCommitShaEnvVar(), the explicitly-passed value always takes precedence and getCommitShaEnvVar() is never called. This means the documented PENSAR_COMMIT_SHA override can never work for GitLab users, even after fixing the priority order in getCommitShaEnvVar(). The reading is also redundant since getCommitShaEnvVar() already checks CI_COMMIT_SHA.

Additional Locations (1)

Fix in Cursor Fix in Web


// Check if we should wait for completion
const wait = process.env.PENSAR_WAIT !== "false";

Expand All @@ -27,6 +30,7 @@ function getGitLabEnvVars() {
environment,
wait,
scanLevel,
commitSha,
};
}

Expand All @@ -35,7 +39,7 @@ function getGitLabEnvVars() {
*/
export async function runScan(): Promise<void> {
try {
const { apiKey, projectId, branch, environment, wait, scanLevel } =
const { apiKey, projectId, branch, environment, wait, scanLevel, commitSha } =
getGitLabEnvVars();

console.log("Starting Pensar security pentest from GitLab CI...");
Expand All @@ -47,6 +51,7 @@ export async function runScan(): Promise<void> {
scanLevel,
environment,
wait,
commitSha,
});

if (result.status === "completed") {
Expand Down