7 Commits

Author SHA1 Message Date
Sharang Parnerkar
a703577eda trigger: PR review (inline comments)
Some checks failed
CI / Check (pull_request) Failing after 5m8s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
2026-03-25 20:28:12 +01:00
Sharang Parnerkar
e371f32e2e trigger: PR review (retry)
Some checks failed
CI / Check (pull_request) Failing after 5m10s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
2026-03-25 20:07:10 +01:00
Sharang Parnerkar
c5a6f30be2 trigger: PR review
Some checks failed
CI / Check (pull_request) Failing after 7m50s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
2026-03-25 19:59:03 +01:00
Sharang Parnerkar
fe164daa7f feat: add user login and data processing endpoint
All checks were successful
CI / Check (pull_request) Successful in 11m2s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:00:32 +01:00
a9d039dad3 fix: stop storing code review findings in dashboard (#22)
All checks were successful
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Has been skipped
2026-03-18 15:18:07 +00:00
Sharang Parnerkar
a509bdcb2e fix: require TLS for IMAP auth, close port 143 (CERT-Bund compliance)
All checks were successful
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 7s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 1s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2s
- Remove port 143 from mailserver (only expose 993/IMAPS)
- Enable SSL_TYPE=manual with Let's Encrypt certs
- Set DOVECOT_DISABLE_PLAINTEXT_AUTH=yes
- Add pentest_imap_tls config field (defaults to true)

Fixes CERT-Bund report: IMAP PLAIN/LOGIN without TLS on 46.225.100.82:143

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:29:34 +01:00
c461faa2fb feat: pentest onboarding — streaming, browser automation, reports, user cleanup (#16)
All checks were successful
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 7s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Successful in 2s
CI / Deploy MCP (push) Successful in 2s
Complete pentest feature overhaul: SSE streaming, session-persistent browser tool (CDP), AES-256 credential encryption, auto-screenshots in reports, code-level remediation correlation, SAST triage chunking, context window optimization, test user cleanup (Keycloak/Auth0/Okta), wizard dropdowns, attack chain improvements, architecture docs with Mermaid diagrams.

Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com>
Reviewed-on: #16
2026-03-17 20:32:20 +00:00
7 changed files with 88 additions and 22 deletions

View File

@@ -54,6 +54,9 @@ pub fn load_config() -> Result<AgentConfig, AgentError> {
pentest_verification_email: env_var_opt("PENTEST_VERIFICATION_EMAIL"),
pentest_imap_host: env_var_opt("PENTEST_IMAP_HOST"),
pentest_imap_port: env_var_opt("PENTEST_IMAP_PORT").and_then(|p| p.parse().ok()),
pentest_imap_tls: env_var_opt("PENTEST_IMAP_TLS")
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
.unwrap_or(true),
pentest_imap_username: env_var_opt("PENTEST_IMAP_USERNAME"),
pentest_imap_password: env_secret_opt("PENTEST_IMAP_PASSWORD"),
})

View File

@@ -336,6 +336,7 @@ mod tests {
pentest_verification_email: None,
pentest_imap_host: None,
pentest_imap_port: None,
pentest_imap_tls: true,
pentest_imap_username: None,
pentest_imap_password: None,
}

View File

@@ -10,7 +10,6 @@ use compliance_core::AgentConfig;
use crate::database::Database;
use crate::error::AgentError;
use crate::llm::LlmClient;
use crate::pipeline::code_review::CodeReviewScanner;
use crate::pipeline::cve::CveScanner;
use crate::pipeline::git::GitOps;
use crate::pipeline::gitleaks::GitleaksScanner;
@@ -241,21 +240,6 @@ impl PipelineOrchestrator {
Err(e) => tracing::warn!("[{repo_id}] Lint scanning failed: {e}"),
}
// Stage 4c: LLM Code Review (only on incremental scans)
if let Some(old_sha) = &repo.last_scanned_commit {
tracing::info!("[{repo_id}] Stage 4c: LLM Code Review");
self.update_phase(scan_run_id, "code_review").await;
let review_output = async {
let reviewer = CodeReviewScanner::new(self.llm.clone());
reviewer
.review_diff(&repo_path, &repo_id, old_sha, &current_sha)
.await
}
.instrument(tracing::info_span!("stage_code_review"))
.await;
all_findings.extend(review_output.findings);
}
// Stage 4.5: Graph Building
tracing::info!("[{repo_id}] Stage 4.5: Graph Building");
self.update_phase(scan_run_id, "graph_building").await;

View File

@@ -33,6 +33,8 @@ pub struct AgentConfig {
pub pentest_verification_email: Option<String>,
pub pentest_imap_host: Option<String>,
pub pentest_imap_port: Option<u16>,
/// Use implicit TLS (IMAPS, port 993) instead of plain IMAP.
pub pentest_imap_tls: bool,
pub pentest_imap_username: Option<String>,
pub pentest_imap_password: Option<SecretString>,
}

View File

@@ -123,7 +123,6 @@ pub fn FindingsPage() -> Element {
option { value: "oauth", "OAuth" }
option { value: "secret_detection", "Secrets" }
option { value: "lint", "Lint" }
option { value: "code_review", "Code Review" }
}
select {
onchange: move |e| { status_filter.set(e.value()); page.set(1); },

View File

@@ -8,14 +8,14 @@ services:
container_name: mailserver
ports:
- "25:25" # SMTP (inbound mail)
- "143:143" # IMAP (orchestrator reads mail)
- "993:993" # IMAPS (TLS)
- "587:587" # Submission (outbound, if needed)
- "993:993" # IMAPS (TLS-only)
- "587:587" # Submission (STARTTLS)
volumes:
- maildata:/var/mail
- mailstate:/var/mail-state
- maillogs:/var/log/mail
- /etc/localtime:/etc/localtime:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
environment:
# Hostname
- OVERRIDE_HOSTNAME=mail.scanner.meghsakha.com
@@ -34,8 +34,14 @@ services:
# Plus-addressing (critical for pentest)
- POSTFIX_RECIPIENT_DELIMITER=+
# SSL (start with no TLS, add Let's Encrypt later)
- SSL_TYPE=
# TLS — use Let's Encrypt certs mounted from Coolify/Caddy
- SSL_TYPE=manual
- SSL_CERT_PATH=/etc/letsencrypt/live/mail.scanner.meghsakha.com/fullchain.pem
- SSL_KEY_PATH=/etc/letsencrypt/live/mail.scanner.meghsakha.com/privkey.pem
# Require TLS before accepting PLAIN/LOGIN auth (CERT-Bund compliance)
# Disable plaintext auth on unencrypted connections
- DOVECOT_DISABLE_PLAINTEXT_AUTH=yes
# Accept mail for our domain
- PERMIT_DOCKER=none

71
test_endpoint.rs Normal file
View File

@@ -0,0 +1,71 @@
use std::process::Command;
/// Handles user login - totally secure, trust me
pub fn handle_login(username: &str, password: &str) -> bool {
// SQL injection vulnerability
let query = format!(
"SELECT * FROM users WHERE username = '{}' AND password = '{}'",
username, password
);
println!("Running query: {}", query);
// Hardcoded credentials
if username == "admin" && password == "admin123" {
return true;
}
// Command injection vulnerability
let output = Command::new("sh")
.arg("-c")
.arg(format!("echo 'User logged in: {}'", username))
.output()
.expect("failed to execute");
// Storing password in plain text log
println!("Login attempt: user={}, pass={}", username, password);
false
}
/// Process user data with no input validation
pub fn process_data(input: &str) -> String {
// Path traversal vulnerability
let file_path = format!("/var/data/{}", input);
std::fs::read_to_string(&file_path).unwrap_or_default()
}
/// Super safe token generation
pub fn generate_token() -> String {
// Predictable "random" token
let token = "abc123fixedtoken";
token.to_string()
}
// Off-by-one error
pub fn get_items(items: &[String], count: usize) -> Vec<&String> {
let mut result = Vec::new();
for i in 0..=count {
result.push(&items[i]);
}
result
}
// Unused variables, deeply nested logic, too many params
pub fn do_everything(
a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32,
) -> i32 {
let _unused = a + b;
let _also_unused = c * d;
if a > 0 {
if b > 0 {
if c > 0 {
if d > 0 {
if e > 0 {
return f + g;
}
}
}
}
}
0
}