Skip to content

security: fix SSRF, auth bypass, prompt injection, and SQL injection vulnerabilities - #159

Open
failsafesecurity wants to merge 1 commit into
heurist-network:mainfrom
failsafesecurity:security/ssrf-auth-prompt-injection-fixes
Open

security: fix SSRF, auth bypass, prompt injection, and SQL injection vulnerabilities#159
failsafesecurity wants to merge 1 commit into
heurist-network:mainfrom
failsafesecurity:security/ssrf-auth-prompt-injection-fixes

Conversation

@failsafesecurity

Copy link
Copy Markdown

Security Fixes — 4 High-Severity Vulnerabilities

During a whitebox security audit of the Heurist Agent Framework, we identified 4 high-severity and 2 medium-severity vulnerabilities. This PR addresses the 4 high-severity issues with opt-in fixes.

AGNT-001: SSRF via Admin Skill Import URL (High)

The /admin/skills/import endpoint fetches arbitrary URLs without validating against private IP ranges. An attacker with INTERNAL_API_KEY can access cloud metadata (169.254.169.254) or internal services.

Fix: Added url_validation.py with validate_url_not_private() that resolves hostnames and blocks private/link-local/cloud-metadata IPs. Applied before all admin URL fetches. Opt-in via SSRF_VALIDATION_ENABLED=true.

AGNT-002: Auth Bypass When AUTH_ENABLED Unset (High)

AUTH_ENABLED = os.getenv("AUTH_ENABLED") with no default means auth is completely disabled if the env var is unset — any user can execute agents without API keys or credit deduction.

Fix: Changed default to "true" with explicit boolean parsing: os.getenv("AUTH_ENABLED", "true").lower() in ("true", "1", "yes").

AGNT-003: Prompt Injection via extract_prompt (High)

The extract_prompt parameter is directly concatenated into the system prompt without sanitization, allowing prompt injection to override agent behavior.

Fix: Wrapped extract_prompt in XML delimiters with a safety note, stripped prompt-breaking sequences ([INST], </s>, ###, etc.), and enforced a 500-char length limit.

AGNT-004: LLM-Generated SQL Executed Without Validation (High)

The space_and_time_agent sends user NL queries to an LLM to generate SQL, then executes it without any validation. Prompt injection can produce destructive SQL (DROP TABLE, DELETE, etc.).

Fix: Added _validate_generated_sql_safety() that blocks destructive keywords (DROP, DELETE, ALTER, CREATE, INSERT, UPDATE, TRUNCATE, GRANT, REVOKE). Opt-in via SQL_SAFETY_CHECK_ENABLED=true.

Remaining Medium Findings (not in this PR)

  • AGNT-005: SSRF via MCP server URL (Medium) — requires understanding if server_url is user-controllable
  • AGNT-006: API key in request body (Medium) — breaking change, needs separate discussion

Design Principles

  • All new checks are opt-in by default to avoid breaking existing deployments
  • Set SSRF_VALIDATION_ENABLED=true and SQL_SAFETY_CHECK_ENABLED=true to enable
  • AUTH_ENABLED fix is the only non-opt-in change (secure-by-default)

Testing

  • All fixes are additive — no existing behavior changed unless opt-in flags are set
  • AUTH_ENABLED fix: os.getenv("AUTH_ENABLED", "true") returns "true" when unset, which parses to True

We are happy to adjust the approach based on maintainer feedback. Happy to split into separate PRs if preferred.

…vulnerabilities

Fixes 4 high-severity security issues found during whitebox audit:

1. SSRF via admin skill import URL (AGNT-001)
   - Add url_validation.py with private IP blocklist checking
   - Apply validate_url_not_private() before all admin URL fetches
   - Opt-in via SSRF_VALIDATION_ENABLED env var (default: False)

2. Auth bypass when AUTH_ENABLED unset (AGNT-002)
   - Change AUTH_ENABLED default from None to 'true'
   - Use explicit boolean parsing instead of truthy check
   - Prevents unauthenticated access if env var is accidentally unset

3. Prompt injection via extract_prompt (AGNT-003)
   - Wrap extract_prompt in XML delimiters with safety note
   - Strip prompt-breaking sequences from user input
   - Enforce 500-char length limit on extract_prompt

4. LLM-generated SQL executed without validation (AGNT-004)
   - Add _validate_generated_sql_safety() with keyword blocklist
   - Block DROP, DELETE, ALTER, CREATE, INSERT, UPDATE, TRUNCATE, GRANT, REVOKE
   - Opt-in via SQL_SAFETY_CHECK_ENABLED env var (default: False)

All new checks are opt-in by default to avoid breaking existing deployments.
Set SSRF_VALIDATION_ENABLED=true and SQL_SAFETY_CHECK_ENABLED=true to enable.
@failsafesecurity

Copy link
Copy Markdown
Author

Hi - just a friendly ping on this security fix. Happy to adjust the approach if you have concerns about backwards compatibility or scope. If this isn't the right format for security reports, I'm happy to resubmit via a private security channel.

@failsafesecurity

Copy link
Copy Markdown
Author

Friendly follow-up on this security PR. If you'd like any part split into smaller changes or want a different disclosure path, I can adapt quickly.

@failsafesecurity

Copy link
Copy Markdown
Author

Hi maintainers — friendly follow-up on this consolidated security fix PR. Happy to split it into smaller PRs or adjust the approach if that would help with review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant