Files
probo/SECURITY_NOTES.md
Bryan Frimin d03f6077dd Document disclosed IDOR and GraphQL DoS advisories
Add SECURITY_NOTES.md entries for GHSA-c74x-79w6-63jh (cross-tenant
IDOR via unvalidated Finding->Risk and ProcessingActivity->DPO
references) and GHSA-prh2-g8pv-m7p9 (GraphQL alias-flooding DoS),
ahead of public disclosure.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-03 12:11:22 +02:00

3.7 KiB

Security Notes

User-facing notes on security-relevant changes to Probo. For the vulnerability reporting process, see SECURITY.md.

Cross-tenant IDOR via unvalidated foreign-key references

2026-07-03, GraphQL

Two console GraphQL resolvers authorized the parent object and then resolved a related object with a tenant scope taken from that related object's own GID, instead of from the authorization result. An authenticated member of one organization could attach another organization's Risk or Data Protection Officer profile GID to their own Finding or Processing Activity, then read it back:

  • Finding.risk disclosed another organization's Risk (name, description, treatment, category, severity, owner).
  • ProcessingActivity.dataProtectionOfficer disclosed another organization's person profile PII (full name, email addresses, position).

FindingService and ProcessingActivityService now validate the referenced Risk and Data Protection Officer profile against the caller's scope before storing the reference, and the affected resolvers (along with every other resolver following the same pattern) now authorize the related object's own ID rather than the parent's.

Reported by Pig-Tail. (GHSA-c74x-79w6-63jh)

GraphQL alias-flooding denial of service

2026-06-29, GraphQL

The GraphQL endpoints (connect, console, and trust) built their server with no limits on query size or complexity. A single request containing thousands of aliased resolver calls (e.g. a1: viewer { id } repeated thousands of times) was parsed, executed, and marshalled in full, letting an attacker drive excessive CPU and memory use and degrade service for other tenants.

The shared GraphQL handler now enforces a parser token limit that rejects oversized queries before execution, a fixed query complexity limit, and an LRU query cache, with limits configurable per environment via PROBOD_API_GRAPHQL_* env vars and Helm values.

Reported by Muthu-Devarajan. (GHSA-prh2-g8pv-m7p9)

Open redirect bypass in saferedirect

2026-05-26, Auth

Relative redirect URLs are now normalized before validation. Paths containing backslashes (including percent-encoded %5c) are rejected, and the cleaned path is checked for protocol-relative and backslash prefixes.

Previously, Validate only inspected the second character of the raw input. A path like /../\evil.com passed validation because the second character is ., but Go's http.Redirect normalized it to /\evil.com, which browsers can treat as an external redirect.

Reported by Fushuling and RacerZ.

Password changes invalidate existing sessions

2026-04-29, IAM

Password changes and resets now revoke existing sessions for the identity.

Previously, rotating a password did not touch iam_sessions rows: a stolen session stayed valid until its idle TTL elapsed, so a user whose account was compromised on another device could not evict that device by changing the password.

Inside the same transaction as the password update:

  • A signed-in password change revokes every other active session for the identity and keeps the caller's current session.
  • A forgot-password reset revokes all active sessions for the identity. The caller is anonymous (authenticated only by the reset token), so there is no current session to preserve.

The session middleware already rejects rows with expire_reason set, so revoked sessions are kicked out on the next request without any middleware change.

Reported by emimoir.