Skip to content

Security audit: hardcoded secrets, auth hardening, permissive config, and vulnerable dependencies #116

Description

@robotyaga-gigachain

Security audit findings

This is a point-in-time security review of the repository covering four areas: hardcoded secrets/credentials, unsafe handling of user input, overly permissive configuration, and dependencies with known vulnerabilities. Findings are ranked by severity. No secret values are reproduced in this report.

Scope note: several items are intentional trade-offs for local/self-hosted single-tenant dev use. They are still flagged because the same code paths ship in the Docker deployment assets and can be exposed if the service is put on a network. Please confirm the intended deployment/threat model.


Critical

C1. Vulnerable jupyter-server (stored XSS + path traversal) bundled in the code-execution image

  • Where: backend/pyproject.toml optional jupyter / jupyter-full extras (jupyter-server>=2.0.0), locked at 2.17.0 in backend/uv.lock.
  • Issue: 2.17.0 is affected by CVE-2026-44727 (stored XSS, critical), CVE-2026-35397 (path traversal), CVE-2026-40110, CVE-2026-40934. This runs inside the sandbox that executes agent/user-supplied code, so the blast radius is significant.
  • Remediation: bump to jupyter-server>=2.20.0 and rebuild the sandbox image.

High

H1. Known-vulnerable security-critical dependencies (backend)

  • Where: backend/uv.lock / backend/pyproject.toml.
  • Issue (highest-impact, from OSV.dev against locked versions):
    • pyjwt 2.12.1CVE-2026-48526 (forged HS256) and related; JWT is the core auth mechanism (modules/auth/security.py). Fixed in 2.13.0.
    • starlette 0.50.0CVE-2026-48818 (SSRF) + others; fixed in 1.3.1 (major; coordinate with fastapi ~=0.127.0).
    • python-multipart 0.0.26CVE-2026-53539 / CVE-2026-42561 (DoS on multipart parsing, reachable via file-upload endpoints). Fixed in 0.0.31.
    • urllib3 2.6.3CVE-2026-44432 / CVE-2026-44431. Fixed in 2.7.0.
    • cryptography 46.0.7GHSA-537c-gmf6-5ccf (bundled OpenSSL). Fixed in 48.0.1.
    • aiohttp 3.13.5, mako 1.3.11, mistune 3.2.0, msgpack 1.1.2, tornado 6.5.5, langchain-classic 1.0.4, langsmith 0.7.32, pydantic-settings 2.13.1, idna 3.11, nltk 3.9.4 (no fix yet) also flagged.
  • Remediation: run pip-audit in CI, then upgrade. Prioritize pyjwt, python-multipart, starlette, urllib3, cryptography.

H2. Known-vulnerable dependencies (frontend), incl. auth-token leakage in axios

  • Where: front/package.json / lockfile. npm audit reports 25 vulns (9 high, 15 moderate).
  • Issue (high): axios 1.15.0 (credential/proxy leak, prototype-pollution MITM, ReDoS, SSRF); @modelcontextprotocol/sdk 1.17.0 (ReDoS, cross-client data leak, DNS-rebind); vite 8.0.8 (server.fs.deny bypass); react-router(-dom) 7.10.x (XSS via open redirects, SSR XSS); transitive form-data, path-to-regexp, picomatch, langsmith (JS).
  • Remediation: 23 of 25 resolve with npm audit fix; react-syntax-highlighter needs a major bump to 16.1.1 (clears transitive prismjs/refractor DOM-clobbering).

H3. JWT access tokens never expire

  • Where: backend/giga_agent/modules/auth/security.py:9ACCESS_TOKEN_EXPIRE_MINUTES = None (# None = tokens never expire); create_access_token omits exp when no delta is passed, and login (modules/auth/api.py) passes none.
  • Issue: a leaked token (logs, browser history, proxy, XSS) is valid forever. There is no expiry and no server-side revocation/rotation, so the only remediation for a leak is rotating GIGA_AGENT_SECRET_KEY, which invalidates every user. A jti is embedded but not checked against any denylist.
  • Remediation: set a finite exp (e.g. hours/days), add refresh-token rotation, and/or a jti revocation list.

H4. Default admin credentials, weak default, and plaintext credential logging

  • Where: backend/giga_agent/conf.py:107-113 (admin@example.com / giga_agent_admin); backend/giga_agent/modules/auth/module.py:52 logs f"Admin user created: {admin_email}:{admin_password}".
  • Issue: on first boot a superuser is auto-created with well-known, guessable credentials, and the plaintext password is written to application logs. If the instance is reachable before the operator changes it, this is a full account takeover; the log line also persists the secret wherever logs are shipped.
  • Remediation: require the admin password to be set explicitly (fail closed / force a random password printed once), never log the password, and force a change-password on first login.

Medium

M1. Docker socket mounted read-write into the app container (host-root escalation)

  • Where: docker-compose.ymlgiga-agent service mounts /var/run/docker.sock:/var/run/docker.sock and sets DOCKER_HOST=unix:///var/run/docker.sock.
  • Issue: full access to the host Docker daemon is effectively host root. Combined with an RCE in the app (or the agent's code-execution features), this is a container-escape to the host.
  • Remediation: if the local-docker sandbox provider is not needed, remove the mount; otherwise use a rootless/proxied Docker socket (e.g. a socket-proxy restricting the API surface) and document the risk.

M2. TLS certificate verification disabled on outbound calls

  • Where: backend/giga_agent/connectors/gigachat.py:99,109,121,135; backend/giga_agent/embeddings/gigachat.py; backend/giga_agent/generators/image/gigachat.py:67 (httpx.AsyncClient(verify=False)).
  • Issue: verify_ssl_certs=False / verify=False disables certificate validation, exposing API traffic (including bearer credentials) to MITM. This is a common pattern for GigaChat's Russian root CA, but hardcoding it removes the option to verify.
  • Remediation: ship/trust the proper CA bundle and make verification configurable (default on), rather than hardcoding False.

M3. Default database passwords in Docker deployment

  • Where: docker-compose.yml — both Postgres services use POSTGRES_USER=postgres / POSTGRES_PASSWORD=postgres, and connection URLs use sslmode=disable.
  • Issue: default postgres:postgres creds and unencrypted DB connections. Low risk while the DB is confined to the internal compose network, but dangerous if a port is published or the network is shared.
  • Remediation: parameterize credentials via env/secrets with no insecure default, and prefer TLS for DB connections in non-loopback deployments.

M4. Hardcoded dev secret key

  • Where: backend/start_aegra.py:24os.environ["GIGA_AGENT_SECRET_KEY"] = "secret".
  • Issue: this dev launcher forces the JWT signing key to the literal secret. Any token signed under it is trivially forgeable. It is a dev-only entrypoint, but there is no guard preventing it from being used outside dev.
  • Remediation: read from env and fail if unset (as core/agent/base.py already does elsewhere); do not hardcode a signing key even in dev helpers.

Low / informational

L1. verify_password timing / no account lockout

  • Where: backend/giga_agent/modules/auth/api.py login handler.
  • Issue: bcrypt is used correctly, but there is no rate limiting / lockout on the token endpoint, enabling online password brute force (relevant given the weak default admin password in H4).
  • Remediation: add rate limiting / exponential backoff on failed logins (a rate_limits route already exists to build on).

L2. Positive: no obvious injection in reviewed code

  • SQL access uses SQLAlchemy with parameterized text(... :param ...) bindings (e.g. models/migrations/...), no string-formatted SQL found.
  • No eval/exec on user input; the local_functions directory picker (routes/local_functions.py) uses fixed argv lists (no shell, no user-controlled args).
  • Sandbox subprocess usage passes argument lists (no shell=True with user input observed). Kept here so reviewers know these were checked, not skipped.

Suggested next steps

  1. Add pip-audit (backend) and npm audit/Dependabot (frontend) to CI to catch H1/H2/C1 continuously.
  2. Address auth hardening together: token expiry + revocation (H3) and admin bootstrap (H4).
  3. Decide the deployment threat model and gate M1/M3/M2 accordingly (loopback-only dev vs. network-exposed).

Line references are against the audited commit; verify before patching. This report intentionally contains no secret values.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions