Skip to content

security: the three remaining red-team lows (cleartext key, symlink write, unpinned dep)#70

Merged
inth3shadows merged 2 commits into
mainfrom
security-lows-batch
Jul 11, 2026
Merged

security: the three remaining red-team lows (cleartext key, symlink write, unpinned dep)#70
inth3shadows merged 2 commits into
mainfrom
security-lows-batch

Conversation

@inth3shadows

Copy link
Copy Markdown
Owner

The three remaining Lows from the /redteam pass, batched. All defensive; none change happy-path behavior.

[Low] Cleartext Bearer key in the fluency eval tool

  • Where: fluency.py openai_answerer
  • Issue: Sent Authorization: Bearer <key> to any base_url, including http://, leaking the key in cleartext on the wire.
  • Fix: Refuses http to a non-loopback host when a key is set (raises ValueError at construction). Loopback http (local LiteLLM/CCR gateway) and https are unaffected; http with no key is still allowed (nothing to leak).

[Low] _secure_io followed symlinks on write

  • Where: _secure_io.py write_restricted / append_restricted
  • Issue: Opened the final path component without O_NOFOLLOW, so a pre-planted symlink in a terse-managed dir could redirect a secret-bearing write (config, backup, captured payload) onto an attacker-chosen target.
  • Fix: Both opens add O_NOFOLLOW via getattr(os, "O_NOFOLLOW", 0) — a no-op on a platform lacking it rather than a crash. Guards the final component (the standard O_NOFOLLOW limitation).

[Low] Unpinned tiktoken

  • Where: pyproject.toml
  • Issue: Bare "tiktoken" — a lockfile-less pip install terse could resolve to an arbitrarily old release.
  • Fix: Pinned a floor tiktoken>=0.7; uv.lock still pins the exact version for this repo.

Tests (+6)

  • openai_answerer: rejects http+key to a remote host; allows loopback-http+key, https+key, and http+no-key.
  • _secure_io: refuses to write/append through a symlink and leaves the target untouched (skipped where O_NOFOLLOW is absent).

452 pass, ruff clean. Completes the redteam remediation — no open findings remain.

[Low] Cleartext Bearer key in the fluency eval tool. openai_answerer sent
Authorization: Bearer <key> to whatever base_url it was given, including an
http:// one. It now refuses http to a non-loopback host when a key is set
(raises ValueError at construction); loopback http (local LiteLLM/CCR) and
https are unaffected, and http with no key is still allowed.

[Low] _secure_io followed symlinks on write. write_restricted/append_restricted
opened the final path component without O_NOFOLLOW, so a pre-planted symlink in
a terse-managed dir could redirect a secret-bearing write onto an attacker
target. Both opens now add O_NOFOLLOW (via getattr, so it's a no-op on a
platform without the flag rather than a crash).

[Low] Unpinned tiktoken. pyproject listed a bare "tiktoken"; a lockfile-less
install could resolve to an arbitrarily old release. Pinned a floor
(tiktoken>=0.7); uv.lock still pins the exact version for this repo.

Tests: openai_answerer rejects http+key to a remote host, allows loopback-http
+key / https+key / http+no-key; _secure_io refuses to write/append through a
symlink (skipped where O_NOFOLLOW is absent) and leaves the target untouched.
452 pass, ruff clean.
The pyproject constraint change (previous commit) leaves uv.lock's recorded
requires-dist specifier stale; regenerate it so lock and manifest agree. No
resolved-version change — tiktoken stays at the locked 0.13.0, which satisfies
>=0.7.
@inth3shadows inth3shadows merged commit a931314 into main Jul 11, 2026
5 checks passed
@inth3shadows inth3shadows deleted the security-lows-batch branch July 11, 2026 17:39
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