Must be reachable from the scanner - localhost and private IPs are rejected.
+ External, unauthenticated scan — we don't log in.
diff --git a/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/EmptyState.tsx b/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/EmptyState.tsx
index b270f32858..6a25f8a3a0 100644
--- a/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/EmptyState.tsx
+++ b/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/EmptyState.tsx
@@ -18,8 +18,9 @@ const STEPS = [
Icon: Link,
},
{
- title: 'Configure scope',
- description: 'Optionally attach a public repository for deeper, code-aware coverage.',
+ title: 'Add code context',
+ description:
+ 'Optionally attach a public repository — we use it to write better remediation steps.',
Icon: Settings,
},
{
diff --git a/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/ScanAdvancedOptions.tsx b/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/ScanAdvancedOptions.tsx
index b94ea4f319..74e9da6d8a 100644
--- a/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/ScanAdvancedOptions.tsx
+++ b/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/ScanAdvancedOptions.tsx
@@ -1,6 +1,21 @@
import type { EvidenceLevel, PentestCheck } from '@/lib/security/penetration-tests-client';
-import { Checkbox, RadioGroup, RadioGroupItem } from '@trycompai/design-system';
-import { allPentestChecks, checkLabels, evidenceLabels } from './scan-profiles';
+import {
+ Checkbox,
+ RadioGroup,
+ RadioGroupItem,
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from '@trycompai/design-system';
+import { Information } from '@trycompai/design-system/icons';
+import {
+ allPentestChecks,
+ checkDescriptions,
+ checkLabels,
+ evidenceDescriptions,
+ evidenceLabels,
+} from './scan-profiles';
interface ScanAdvancedOptionsProps {
open: boolean;
@@ -13,13 +28,6 @@ interface ScanAdvancedOptionsProps {
const evidenceOptions: EvidenceLevel[] = ['report_only', 'safe_proof', 'impact_proof'];
-const evidenceHelperText: Record = {
- report_only: 'Fastest and lowest risk. Some findings may need manual confirmation.',
- safe_proof: 'Balanced validation. Good default for production or staging targets.',
- impact_proof:
- 'Highest confidence, longer runtime, and stronger target interaction. Requires authorization.',
-};
-
export function ScanAdvancedOptions({
open,
evidenceLevel,
@@ -50,10 +58,10 @@ export function ScanAdvancedOptions({
>
- Customize scan
+ Scan coverage
- Evidence level and individual checks
+ What we'll check and how we'll validate it
@@ -62,66 +70,81 @@ export function ScanAdvancedOptions({
{open && (
-
-
+
+
+
-
+
+
+
)}
);
diff --git a/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/scan-profiles.ts b/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/scan-profiles.ts
index a44a71e987..ec4b03a09d 100644
--- a/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/scan-profiles.ts
+++ b/apps/app/src/app/(app)/[orgId]/security/penetration-tests/_components/scan-profiles.ts
@@ -63,12 +63,41 @@ export const checkLabels: Record = {
business_logic: 'Business logic',
};
+export const checkDescriptions: Record = {
+ discovery: 'Maps the target attack surface — endpoints, subdomains, and exposed services.',
+ secrets_info_disclosure:
+ 'Looks for leaked API keys, tokens, debug output, and exposed files like .git or .env.',
+ technology_config:
+ 'Checks for missing security headers, outdated libraries, and exposed admin panels.',
+ xss: 'Cross-site scripting — reflected, stored, and DOM-based variants.',
+ injection: 'SQL, NoSQL, command, and LDAP injection in user-controlled inputs.',
+ authentication:
+ 'Login flow weaknesses, weak password policies, and broken session handling.',
+ authorization: 'Privilege escalation and missing access controls between roles.',
+ idor_bola:
+ 'Insecure Direct Object References — whether one user can access another user\'s data by changing an ID.',
+ ssrf_xxe: 'Server-side request forgery and XML external-entity attacks.',
+ csrf: 'Cross-site request forgery — actions performed without user consent.',
+ race_conditions:
+ 'Concurrency bugs like double-spend and time-of-check vs time-of-use issues.',
+ business_logic: 'App-specific workflow abuse (e.g., skipping payment or approval steps).',
+};
+
export const evidenceLabels: Record = {
report_only: 'Report only',
safe_proof: 'Safe proof',
impact_proof: 'Impact proof',
};
+export const evidenceDescriptions: Record = {
+ report_only:
+ 'Findings are reported without exploitation. No active attack attempted. Fastest and safest — some findings may need manual confirmation.',
+ safe_proof:
+ 'Findings are validated with non-destructive proofs. Safe for production and staging. Recommended default.',
+ impact_proof:
+ 'Findings are validated with active exploitation attempts (no data destruction). May trigger WAF alerts or rate limits. Use on staging or with explicit owner approval.',
+};
+
const checkWeights: Record = {
discovery: 5,
secrets_info_disclosure: 5,