Skip to content

Security: arunsdev10/text-summarizer

Security

SECURITY.md

Security Policy

Reporting a vulnerability

Please do not open a public issue for a security vulnerability.

Report it privately through GitHub's private vulnerability reporting: open the repository's Security tab and choose Report a vulnerability. This creates a draft advisory visible only to the maintainers.

Maintainers: private reporting must be switched on for this repository under Settings → Code security and analysis → Private vulnerability reporting, otherwise the link above will not be available to reporters.

Please include:

  • what an attacker can achieve, and the impact;
  • the affected file, endpoint or configuration;
  • reproduction steps or a proof of concept;
  • the version or commit you tested.

What to expect: acknowledgement within 7 days, an assessment with a planned fix window within 14 days, and credit in the advisory unless you prefer otherwise. Please give us a reasonable window to ship a fix before disclosing publicly.

Out of scope

  • Findings that require an already-compromised server or database.
  • Missing hardening that is the deployer's responsibility and documented in the checklist below (for example, running with DJANGO_DEBUG=true).
  • Vulnerabilities in Groq, Google reCAPTCHA, or other third-party services — report those to the vendor.
  • Automated scanner output with no demonstrated impact.

Supported versions

This project has a single supported line: the latest commit on main. Security fixes are not backported.


Safe-deployment checklist

Work through this before exposing the app to the internet.

Secrets

  • DJANGO_SECRET_KEY is set to a freshly generated random value, unique to this deployment. Generate with: python -c "from django.core.management.utils import get_random_secret_key as k; print(k())"
  • GROQ_API_KEY is set, and is a key scoped to this application so it can be rotated independently.
  • No .env file is committed. .gitignore excludes .env and .env.* while keeping .env.example.
  • IP_HASH_SALT is set explicitly if you ever rotate DJANGO_SECRET_KEY and want stored IP hashes to remain comparable.

Django configuration

  • DJANGO_DEBUG=false. The app refuses to start in production without a secret key or allowed hosts, but debug mode disables those guards — make sure it is genuinely off.
  • DJANGO_ALLOWED_HOSTS names your real hostnames. Never *.
  • CORS_ALLOWED_ORIGINS lists only the origins that must call the API. Never a wildcard, and never a private/LAN address in a public deployment.
  • CSRF_TRUSTED_ORIGINS matches your frontend origin.
  • python manage.py check --deploy reports no issues.
  • Served over HTTPS. Keep SECURE_SSL_REDIRECT=true unless a proxy in front already terminates TLS and redirects.
  • A strong, unique Django admin password; consider removing the /admin/ route entirely if you do not use it.

Abuse and cost control

  • API_THROTTLE_RATE is tuned for your traffic. Every summarization request costs a Groq API call, so an unthrottled public endpoint is a direct billing risk.
  • MAX_UPLOAD_SIZE is set appropriately; requests are processed synchronously, so large documents tie up a worker.
  • Consider a WAF or rate limiter at the edge in addition to the DRF throttle, which is per-IP and trivially bypassed with a proxy pool.
  • Both reCAPTCHA halves (RECAPTCHA_SECRET_KEY and VITE_RECAPTCHA_SITE_KEY) are configured, or the contact form will reject every submission.

Data protection

  • You have read the "Data collected" section of the README and accept what is stored.
  • Decide whether you need request logging at all — set ENABLE_REQUEST_LOGGING=false to store nothing per request.
  • Put a retention policy in place. Nothing expires automatically.
  • The database file or server is not world-readable and is backed up somewhere private. db.sqlite3 and *.csv are gitignored — keep it that way.
  • Users are told that submitted text is sent to Groq for processing.

Infrastructure

  • Containers run as the non-root app / nginx users as shipped; do not override with user: root.
  • Never run manage.py runserver or vite dev in production. The shipped images use gunicorn and nginx.
  • Keep dependencies patched: pip-audit for the backend and npm audit --omit=dev for the frontend both run in CI.
  • The /textsummery/health/ endpoint is unauthenticated by design; it exposes only {"status": "ok"}.

Security-relevant design notes

  • POS/NER output is rendered as raw HTML in the frontend via dangerouslySetInnerHTML. The backend HTML-escapes every user-derived token before building that markup (pos_html in backend/textApp/utils/entity.py, covered by a regression test). Any change to that rendering path must preserve the escaping or it becomes stored XSS.
  • Client IPs are hashed, never stored raw. X-Forwarded-For is trusted only for reading the client address — deploy behind a proxy that sets it, or the value is attacker-controlled.
  • Secrets fail loudly. Missing DJANGO_SECRET_KEY, DJANGO_ALLOWED_HOSTS or GROQ_API_KEY raise ImproperlyConfigured at startup when debug is off, rather than silently falling back to an insecure default.
  • Upstream failures surface as 5xx, never as an empty or fabricated summary.

There aren't any published security advisories